diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6191c7a55..333ba2a71 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -190,6 +190,7 @@ jobs: if: contains(github.ref, 'develop') with: prerelease: true + generate_release_notes: true body: ${{ needs.versioning.outputs.changelog }} name: ${{ needs.versioning.outputs.tag }} tag_name: ${{ needs.versioning.outputs.tag }} diff --git a/.github/workflows/issue-check.yml b/.github/workflows/issue-check.yml index 9dfe5cc45..51b87b8d3 100644 --- a/.github/workflows/issue-check.yml +++ b/.github/workflows/issue-check.yml @@ -8,9 +8,6 @@ jobs: issueCheck: runs-on: ubuntu-latest steps: - - name: Output version - run: | - echo "log: ${{ github.event.issue.body }}" - if: startsWith(github.event.issue.body , '**Describe the bug**') == false name: Close Issue diff --git a/CHANGELOG.md b/CHANGELOG.md index 17dad0980..ac28afc2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,376 +1,309 @@ -## [4.10.2](https://github.com/Ombi-app/Ombi/compare/v4.10.1...v4.10.2) (2022-01-22) + +## [4.16.10](https://github.com/Ombi-app/Ombi/compare/v4.16.9...v4.16.10) (2022-04-13) -## [4.10.1](https://github.com/Ombi-app/Ombi/compare/v4.10.0...v4.10.1) (2022-01-22) +## [4.16.9](https://github.com/Ombi-app/Ombi/compare/v4.16.8...v4.16.9) (2022-04-13) + + +### Bug Fixes + +* **plex-watchlist:** Only request the latest season when importing from the watchlist ([77a47ff](https://github.com/Ombi-app/Ombi/commit/77a47ff157c6c5feafe3f2a29a3fcba8df4fdfef)) -## [4.3.3](https://github.com/Ombi-app/Ombi/compare/v4.3.2...v4.3.3) (2021-11-05) +## [4.16.8](https://github.com/Ombi-app/Ombi/compare/v4.16.7...v4.16.8) (2022-04-13) + + +### Bug Fixes + +* **availability:** Fixed an issue where we wouldn't mark a available 4k movie as available (when 4K request feature is disabled) ([b492699](https://github.com/Ombi-app/Ombi/commit/b49269961d4830a530e3054976a47f519524948b)) -# [4.10.0](https://github.com/Ombi-app/Ombi/compare/v4.9.2...v4.10.0) (2022-01-14) +## [4.16.7](https://github.com/Ombi-app/Ombi/compare/v4.16.6...v4.16.7) (2022-04-12) + + + +## [4.16.6](https://github.com/Ombi-app/Ombi/compare/v4.16.5...v4.16.6) (2022-04-11) + + + +## [4.16.5](https://github.com/Ombi-app/Ombi/compare/v4.16.4...v4.16.5) (2022-04-08) + + +### Bug Fixes + +* **watchlist:** actually fixed it this time... ([d962a32](https://github.com/Ombi-app/Ombi/commit/d962a3211eca29520662ddce962676e3aea17ec5)) + + + +## [4.16.4](https://github.com/Ombi-app/Ombi/compare/v4.16.3...v4.16.4) (2022-04-08) + + + +## [4.16.3](https://github.com/Ombi-app/Ombi/compare/v4.16.2...v4.16.3) (2022-04-08) + + +### Bug Fixes + +* **plex-watchlist:** :bug: Fixed the issue where the watchlist didn't work for users logging in via OAuth ([6398f6a](https://github.com/Ombi-app/Ombi/commit/6398f6a4f7755281ebeac537e3ff623df5cfa0f3)) + + + +## [4.16.2](https://github.com/Ombi-app/Ombi/compare/v4.16.1...v4.16.2) (2022-04-07) + + +### Bug Fixes + +* **wizard:** Fixed an issue when using Plex OAuth it could fail setting up ([b743cf4](https://github.com/Ombi-app/Ombi/commit/b743cf4fafa7341ad1b163276f006d7ab0e9dcff)) + + + +## [4.16.1](https://github.com/Ombi-app/Ombi/compare/v4.16.0...v4.16.1) (2022-04-07) + + + +# [4.16.0](https://github.com/Ombi-app/Ombi/compare/v4.15.6...v4.16.0) (2022-04-07) + + + +## [4.15.6](https://github.com/Ombi-app/Ombi/compare/v4.15.5...v4.15.6) (2022-04-07) + + +### Bug Fixes + +* **radarr:** Fixed an issue where we couldn't sync radarr content [#4577](https://github.com/Ombi-app/Ombi/issues/4577) ([a5355a3](https://github.com/Ombi-app/Ombi/commit/a5355a3023e6900c4dd1b0da4722d7596c03907f)) + + + +## [4.15.5](https://github.com/Ombi-app/Ombi/compare/v4.15.4...v4.15.5) (2022-04-06) + + + +## [4.15.4](https://github.com/Ombi-app/Ombi/compare/v4.15.3...v4.15.4) (2022-03-29) + + + +## [4.15.3](https://github.com/Ombi-app/Ombi/compare/v4.15.2...v4.15.3) (2022-03-24) + + + +## [4.15.2](https://github.com/Ombi-app/Ombi/compare/v4.15.1...v4.15.2) (2022-03-23) + + +### Bug Fixes + +* **metadata:** improved the metadata job to also lookup the media in Plex to see if it has any more uptodate metadata ([83d1a15](https://github.com/Ombi-app/Ombi/commit/83d1a15cc9d0ee91be73bd91c4672cf1bcf2728a)) + + + +## [4.15.1](https://github.com/Ombi-app/Ombi/compare/v4.15.0...v4.15.1) (2022-03-18) + + +### Bug Fixes + +* **mediaserver:** fixed an issue where we were not detecting available content correctly [#4542](https://github.com/Ombi-app/Ombi/issues/4542) ([9cdd6f4](https://github.com/Ombi-app/Ombi/commit/9cdd6f41cdab8825a984905c089611409c53c753)) + + + +# [4.15.0](https://github.com/Ombi-app/Ombi/compare/v4.14.4...v4.15.0) (2022-03-17) + + +### Bug Fixes + +* **jellyfin:** :bug: Fixed an issue where Jellyfin content was showing the Play on Emby button ([18b167d](https://github.com/Ombi-app/Ombi/commit/18b167d16a3d682b5060ee36dedbbb069bef09de)), closes [#4542](https://github.com/Ombi-app/Ombi/issues/4542) + + + +## [4.14.4](https://github.com/Ombi-app/Ombi/compare/v4.14.3...v4.14.4) (2022-03-10) + + +### Bug Fixes + +* :bug: Fixed the Request On Behalf autocomplete not filtering correctly ([a8ba2f3](https://github.com/Ombi-app/Ombi/commit/a8ba2f3544a1c01c57f217c4036a277ab0e67a09)), closes [#4539](https://github.com/Ombi-app/Ombi/issues/4539) +* **translations:** 🌐 New translations from Crowdin [skip ci] ([356c742](https://github.com/Ombi-app/Ombi/commit/356c7424e0ce8c1c5063b04bc6ed9b809f214d65)) +* **translations:** 🌐 New translations from Crowdin [skip ci] ([6fcaecf](https://github.com/Ombi-app/Ombi/commit/6fcaecf80b766f2d43ac7082d74364238e1638b7)) +* **translations:** 🌐 New translations from Crowdin [skip ci] ([132f4d4](https://github.com/Ombi-app/Ombi/commit/132f4d4e609b7fb7e37f38ee2f395926e2911abe)) +* **translations:** 🌐 New translations from Crowdin [skip ci] ([f292006](https://github.com/Ombi-app/Ombi/commit/f292006a08894a8d0ba899c8c6e9fe863e558dda)) + + + +## [4.14.3](https://github.com/Ombi-app/Ombi/compare/v4.14.2...v4.14.3) (2022-03-06) + + +### Bug Fixes + +* **availability:** :bug: Fixed an issue where with 4k content, we could repeat notifications ([f9ebc1c](https://github.com/Ombi-app/Ombi/commit/f9ebc1cc2e13c7cd335121cd86295b10eda529ba)) + + + +## [4.14.2](https://github.com/Ombi-app/Ombi/compare/v4.14.1...v4.14.2) (2022-03-05) + + +### Bug Fixes + +* **Sonarr:** :bug: Fixed an issue where some seasons were not being monitored correctly in sonarr ([60cfd41](https://github.com/Ombi-app/Ombi/commit/60cfd41f68e9006555c1a419dcff1aaa24b3e09f)), closes [#4506](https://github.com/Ombi-app/Ombi/issues/4506) + + + +## [4.14.1](https://github.com/Ombi-app/Ombi/compare/v4.14.0...v4.14.1) (2022-03-03) + + + +# [4.14.0](https://github.com/Ombi-app/Ombi/compare/v4.13.2...v4.14.0) (2022-03-02) + + + +## [4.13.2](https://github.com/Ombi-app/Ombi/compare/v4.13.1...v4.13.2) (2022-03-01) + + +### Bug Fixes + +* **requests:** :bug: Fixed an issue where you couldn't approve movies from the request list ([1611ef9](https://github.com/Ombi-app/Ombi/commit/1611ef9198befbb7a4db50a4f0953e50f29a788f)) + + + +## [4.13.1](https://github.com/Ombi-app/Ombi/compare/v4.13.0...v4.13.1) (2022-03-01) + + +### Bug Fixes + +* **details:** :bug: Fixed the missing Play on Media server button for 4k content [#4529](https://github.com/Ombi-app/Ombi/issues/4529) ([68600f3](https://github.com/Ombi-app/Ombi/commit/68600f3b45376e12dd2ef263d81ca4040c84cbca)) +* **discover:** :bug: Fixed the issue where there was an option on the discover to request 4k shows (that's not supported currently) ([dcfd688](https://github.com/Ombi-app/Ombi/commit/dcfd688c8d2337e55fa9c6c33b7c3e80fc560cda)) +* **requests:** :bug: Fixed the issue where we could no longer approve TV Requests from the requests list ([19fe4e3](https://github.com/Ombi-app/Ombi/commit/19fe4e342efe5578c26ab8ba7ee2f2e64bbc9418)) +* **translations:** 🌐 New translations from Crowdin [skip ci] ([#4526](https://github.com/Ombi-app/Ombi/issues/4526)) ([7e9f54f](https://github.com/Ombi-app/Ombi/commit/7e9f54fc80a09c938184e6be40ce5f49ce9673ef)) + + + +# [4.13.0](https://github.com/Ombi-app/Ombi/compare/v4.12.7...v4.13.0) (2022-02-25) + + +### Bug Fixes + +* **4k:** Hide 'Has 4K Request' column list if 4k feature is disabled ([#4521](https://github.com/Ombi-app/Ombi/issues/4521)) ([a9a6067](https://github.com/Ombi-app/Ombi/commit/a9a60678e74d22fa7ba34051a2645db86b600b4a)) +* **issues:** Fix label ID in chatbox page ([#4520](https://github.com/Ombi-app/Ombi/issues/4520)) ([76882ad](https://github.com/Ombi-app/Ombi/commit/76882adf231f92e1cdd396239933c13467c112b3)) +* **localisation:** Localize request types in notifications ([#4516](https://github.com/Ombi-app/Ombi/issues/4516)) ([e09435d](https://github.com/Ombi-app/Ombi/commit/e09435da455b12fc429f129372de31e0654da797)) +* **notifications:** Remove generic admin email in favour of admins' email ([#4519](https://github.com/Ombi-app/Ombi/issues/4519)) ([b90fc5f](https://github.com/Ombi-app/Ombi/commit/b90fc5fea771a83e6cf576c71a307066efd59ea4)) +* **tv:** Display TV show as requested if all episodes are requested ([#4518](https://github.com/Ombi-app/Ombi/issues/4518)) ([2ed8c48](https://github.com/Ombi-app/Ombi/commit/2ed8c48d128a69f0d144c5d332286dbf3b0bdf28)) ### Features -* **notifications:** :sparkles: Send new request email notifications to power users ([#4462](https://github.com/Ombi-app/Ombi/issues/4462)) ([10cc0c0](https://github.com/Ombi-app/Ombi/commit/10cc0c0951f13221179516f8ff5c44dbecc9a0fd)) +* **email-notifications:** Add a link to Ombi details page in email notifications ([#4517](https://github.com/Ombi-app/Ombi/issues/4517)) ([a3e97b3](https://github.com/Ombi-app/Ombi/commit/a3e97b31e2298d95e7deebd71268095b8ed5e9dc)) +* **media-details:** Add Trakt to social icons ([#4522](https://github.com/Ombi-app/Ombi/issues/4522)) ([d6ae79c](https://github.com/Ombi-app/Ombi/commit/d6ae79ce9eddbd5b7b888ab1b9f7e342d9d9ff9e)) -## [4.9.2](https://github.com/Ombi-app/Ombi/compare/v4.9.1...v4.9.2) (2022-01-14) +## [4.12.7](https://github.com/Ombi-app/Ombi/compare/v4.12.6...v4.12.7) (2022-02-23) + + + +## [4.12.6](https://github.com/Ombi-app/Ombi/compare/v4.12.5...v4.12.6) (2022-02-22) ### Bug Fixes -* :bug: Add UI for Emby recently added cronjob settings ([#4469](https://github.com/Ombi-app/Ombi/issues/4469)) ([7d47bbe](https://github.com/Ombi-app/Ombi/commit/7d47bbe92204855bf75d70b8fa548f9c3f3612bc)) -* **sonarr:** :bug: Fixed an issue where we could attempt to add a series to sonarr before sonarr has got all the metadata [#4459](https://github.com/Ombi-app/Ombi/issues/4459) ([5c691dc](https://github.com/Ombi-app/Ombi/commit/5c691dc98437a4cd24560ff625414fe05dd22f89)) -* **wizard:** :bug: Fixed the issue where the Application Url wasn't validated in the wizard ([33b8d11](https://github.com/Ombi-app/Ombi/commit/33b8d1111a1c6663d8c0bbd912be4660da7d013f)), closes [#4417](https://github.com/Ombi-app/Ombi/issues/4417) +* **emby/jellyfin:** :bug: Fixed another issue where we were not correctly displaying the correct status' for movies ([5c0556e](https://github.com/Ombi-app/Ombi/commit/5c0556e6f44b8997a611f3a4d8e9e4e05d08bd13)) +* **mediaserver:** fixed some more issues in the media server sync and availability checks ([f3ea979](https://github.com/Ombi-app/Ombi/commit/f3ea979b8bd77842780ce8e6928b16237dd779cf)) -## [4.9.1](https://github.com/Ombi-app/Ombi/compare/v4.9.0...v4.9.1) (2022-01-14) +## [4.12.5](https://github.com/Ombi-app/Ombi/compare/v4.12.4...v4.12.5) (2022-02-21) ### Bug Fixes -* **discover:** 🌐 Localize episodes names in TV details ([#4467](https://github.com/Ombi-app/Ombi/issues/4467)) [skip ci] ([35806ea](https://github.com/Ombi-app/Ombi/commit/35806ea2d2c866d628cf08577026a02ab04e49d9)) -* **email-notifications:** :bug: Fixed the issue where legacy requests were showing broken poster images [#4452](https://github.com/Ombi-app/Ombi/issues/4452) ([0ece2fd](https://github.com/Ombi-app/Ombi/commit/0ece2fd6e0eb01e0b7d4d2a01e1a276c7a9c5a51)) -* **emby/jellyfin:** :bug: A more reliable Emby and Jellyfin sync [skip ci] ([ad677fa](https://github.com/Ombi-app/Ombi/commit/ad677fa02eb75633014e9c9791c21ed2d6a23229)) +* **emby:** :bug: Fixed the emby content sync [#4513](https://github.com/Ombi-app/Ombi/issues/4513) ([2927504](https://github.com/Ombi-app/Ombi/commit/2927504f0e0b4e7251e69b44e0e30c7ec9519980)) +* **emby:** :bug: Fixed the emby content sync [#4513](https://github.com/Ombi-app/Ombi/issues/4513) ([bd441cb](https://github.com/Ombi-app/Ombi/commit/bd441cb54fd77d6befb03fae321dc36c29f0de2e)) -# [4.9.0](https://github.com/Ombi-app/Ombi/compare/v4.8.1...v4.9.0) (2022-01-05) +## [4.12.4](https://github.com/Ombi-app/Ombi/compare/v4.12.3...v4.12.4) (2022-02-17) + + + +## [4.12.3](https://github.com/Ombi-app/Ombi/compare/v4.12.2...v4.12.3) (2022-02-16) + + + +## [4.12.2](https://github.com/Ombi-app/Ombi/compare/v4.12.1...v4.12.2) (2022-02-16) + + +### Bug Fixes + +* **requests:** :bug: Fixed the approve 4k option on the requests list not working as expected ([c0189da](https://github.com/Ombi-app/Ombi/commit/c0189dad478ea375beda61ba3bee3f029a39b8e5)) + + + +## [4.12.1](https://github.com/Ombi-app/Ombi/compare/v4.12.0...v4.12.1) (2022-02-16) + + +### Bug Fixes + +* **requests:** :bug: Fixed the issue where Approving a 4K Request wouldn't send it to the correct 4K radarr instance ([87cb990](https://github.com/Ombi-app/Ombi/commit/87cb9903db30e1dead25ee8c5ea34305eb084a03)), closes [#4509](https://github.com/Ombi-app/Ombi/issues/4509) + + + +# [4.12.0](https://github.com/Ombi-app/Ombi/compare/v4.11.8...v4.12.0) (2022-02-14) ### Features -* **customization:** :sparkles: Added possibility for custom favicons ([40af659](https://github.com/Ombi-app/Ombi/commit/40af6593b668d4712327c18f92f5b7b5a0a65e26)) +* **radarr:** 4K Requests and Radarr 4K support ([ba88848](https://github.com/Ombi-app/Ombi/commit/ba88848866b0a9dedb1e79b55c4d81a0fd453843)) -## [4.8.1](https://github.com/Ombi-app/Ombi/compare/v4.8.0...v4.8.1) (2022-01-04) - - - -# [4.8.0](https://github.com/Ombi-app/Ombi/compare/v4.7.11...v4.8.0) (2021-12-22) +## [4.11.8](https://github.com/Ombi-app/Ombi/compare/v4.11.7...v4.11.8) (2022-02-13) ### Bug Fixes -* **auto-delete:** :bug: We now also auto delete music requests, this was previously missing ([9fe1f8e](https://github.com/Ombi-app/Ombi/commit/9fe1f8e988aa31d36e7a685ae19f72d9c8414dc0)) - - -### Features - -* **details:** :sparkles: Added the notify button back into the details pages for requests ([8b33cdc](https://github.com/Ombi-app/Ombi/commit/8b33cdccef83db8794414b247438214b00860fac)) +* **settings:** :bug: Fixed an issue where we were not displaying the excluded keyworks correctly in the TheMovieDbSettings page ([d3b3316](https://github.com/Ombi-app/Ombi/commit/d3b3316cbac18356b2f6b0912a3deb2c183e6534)) -## [4.7.11](https://github.com/Ombi-app/Ombi/compare/v4.7.10...v4.7.11) (2021-12-17) +## [4.11.7](https://github.com/Ombi-app/Ombi/compare/v4.11.6...v4.11.7) (2022-02-12) ### Bug Fixes -* **availability-rules:** :bug: Show the 'Requested' button when a show has all of the episodes marked as requested ([cb7ecf6](https://github.com/Ombi-app/Ombi/commit/cb7ecf684ac3ab204f329a28baecfd4f6cd408f7)) +* **notifications:** :bug: This is a fix for some of the duplicate notification issues [#3825](https://github.com/Ombi-app/Ombi/issues/3825) ([22bb422](https://github.com/Ombi-app/Ombi/commit/22bb4226ead2d62e8c2c2c05be47d7da621402e2)) -## [4.7.10](https://github.com/Ombi-app/Ombi/compare/v4.7.9...v4.7.10) (2021-12-16) +## [4.11.6](https://github.com/Ombi-app/Ombi/compare/v4.11.5...v4.11.6) (2022-02-10) ### Bug Fixes -* **discover:** :bug: Fixed an issue where monitored movies in radarr were not correctly represented on the search results ([75b15bc](https://github.com/Ombi-app/Ombi/commit/75b15bc7cba21f0a14a18c8e64fd52482f5c6325)) +* **plex:** Fixed an issue where in a rare case we couldn't sync the data [#4502](https://github.com/Ombi-app/Ombi/issues/4502) ([191318d](https://github.com/Ombi-app/Ombi/commit/191318ddad5a8148422955bf928f1c49b890e3eb)) -## [4.7.9](https://github.com/Ombi-app/Ombi/compare/v4.7.8...v4.7.9) (2021-12-16) +## [4.11.5](https://github.com/Ombi-app/Ombi/compare/v4.11.4...v4.11.5) (2022-02-05) ### Bug Fixes -* **sonarr:** :bug: Fixed an issue where we were sometimes incorrectly setting the state of episodes that are already monitored in sonarr ([fd1acb8](https://github.com/Ombi-app/Ombi/commit/fd1acb88cbc5e73f91b7f81e6e28ee06d66b277e)) +* **sonarr:** Fixed where requesting all seasons would only mark the latest as monitored [#4496](https://github.com/Ombi-app/Ombi/issues/4496) ([cfb85c2](https://github.com/Ombi-app/Ombi/commit/cfb85c23d77626b9ec1d99a6cf76497c438d0338)) -## [4.7.8](https://github.com/Ombi-app/Ombi/compare/v4.7.7...v4.7.8) (2021-12-11) +## [4.11.4](https://github.com/Ombi-app/Ombi/compare/v4.11.3...v4.11.4) (2022-02-05) ### Bug Fixes -* **notifications:** :bug: Fixed the DenyReason sometimes not appearing in the notification message [#4409](https://github.com/Ombi-app/Ombi/issues/4409) ([209e311](https://github.com/Ombi-app/Ombi/commit/209e31175c95f6ee8909d878d45bf8269a9842d9)) -* **oauth:** :lock: Fixed the issue where some users running their browsers in a different language could not open the Plex OAuth window ([d5404ea](https://github.com/Ombi-app/Ombi/commit/d5404eaad7837010d6e4563cd8f7a1009231d362)), closes [#4408](https://github.com/Ombi-app/Ombi/issues/4408) -* **translations:** 🌐 New translations from Crowdin ([5cfb76c](https://github.com/Ombi-app/Ombi/commit/5cfb76cad7a25eed8b452bf9c01cef8c32804369)) +* **media-sync:** Add sanity checks upon media server sync ([#4493](https://github.com/Ombi-app/Ombi/issues/4493)) ([9915234](https://github.com/Ombi-app/Ombi/commit/9915234d38d4701c527081ccc21b566980375331)), closes [#4472](https://github.com/Ombi-app/Ombi/issues/4472) +* **newsletter:** Fix newsletter not publishing double episodes ([#4495](https://github.com/Ombi-app/Ombi/issues/4495)) ([ddf63fb](https://github.com/Ombi-app/Ombi/commit/ddf63fbed0b9cbe458aec37318758c76b99b2de9)) - -## [4.7.7](https://github.com/Ombi-app/Ombi/compare/v4.7.6...v4.7.7) (2021-12-08) +## [4.11.3](https://github.com/Ombi-app/Ombi/compare/v4.11.2...v4.11.3) (2022-02-03) ### Bug Fixes -* **notifications:** 🐛 Do not notify user upon auto approval of a TV show ([#4432](https://github.com/Ombi-app/Ombi/issues/4432)) ([3ad3bdd](https://github.com/Ombi-app/Ombi/commit/3ad3bddd8313d607ee2a39a51a92e61a3673082c)), closes [#4431](https://github.com/Ombi-app/Ombi/issues/4431) -* **translations:** 🌐 New translations from Crowdin ([8943a97](https://github.com/Ombi-app/Ombi/commit/8943a978bf459eaeb496d50c61c4d1506c727366)) - - - -## [4.7.6](https://github.com/Ombi-app/Ombi/compare/v4.7.5...v4.7.6) (2021-12-02) - - -### Bug Fixes - -* **user-management:** :bug: Fixed an issue where you couldn't 'unset' a users custom quality and root folders ([bae96af](https://github.com/Ombi-app/Ombi/commit/bae96af17f50a80ae3ade235a5ef68d5d2dc12ba)) - - - -## [4.7.5](https://github.com/Ombi-app/Ombi/compare/v4.7.4...v4.7.5) (2021-11-28) - - -### Bug Fixes - -* **notifications:** fixed an error that could happen when Ombi sends out a issue notification ([7442dcf](https://github.com/Ombi-app/Ombi/commit/7442dcf59da5d2190cc3087b10402e85bcfcf83b)) -* **translations:** 🌐 Fix incorrect text translation reference RequestedByOn ([#4420](https://github.com/Ombi-app/Ombi/issues/4420)) ([202d155](https://github.com/Ombi-app/Ombi/commit/202d155493c29a6ddd4c5507186bf376a28f4c1d)) -* **translations:** 🌐 New translations from Crowdin ([473c172](https://github.com/Ombi-app/Ombi/commit/473c1724922515fe376e0b2058ac391807c923f2)) - - - -## [4.7.4](https://github.com/Ombi-app/Ombi/compare/v4.7.3...v4.7.4) (2021-11-25) - - -### Bug Fixes - -* **availability-rules:** :bug: Fixed a small issue where some shows would not appear as Available even know they had no future unaired episodes listed ([914b096](https://github.com/Ombi-app/Ombi/commit/914b096781c9b73292a533a010a5dd05ecfd0aac)) -* **emby:** :bug: Fixed an issue where we were not properly syncing episodes ([75529dd](https://github.com/Ombi-app/Ombi/commit/75529dd972c5102f3c5234a2acf6fe664a1bcfad)) - - - -## [4.7.3](https://github.com/Ombi-app/Ombi/compare/v4.7.2...v4.7.3) (2021-11-23) - - - -## [4.7.2](https://github.com/Ombi-app/Ombi/compare/v4.7.1...v4.7.2) (2021-11-22) - - -### Bug Fixes - -* **request-list:** :bug: Fixed an issue where the bulk delete would not work for movie requests ([4b540fb](https://github.com/Ombi-app/Ombi/commit/4b540fb45bcc389664f0953159802288d005db9f)) - - - -## [4.7.1](https://github.com/Ombi-app/Ombi/compare/v4.7.0...v4.7.1) (2021-11-22) - - -### Bug Fixes - -* **emby:** :bug: Fixed an issue where we slightly broke the full sync ([332d934](https://github.com/Ombi-app/Ombi/commit/332d9344d002a5ffd5aeac516c7441dcdec52248)) - - - -# [4.7.0](https://github.com/Ombi-app/Ombi/compare/v4.6.5...v4.7.0) (2021-11-19) - - -### Features - -* **emby:** :sparkles: Added a emby recently added sync! ([a0e1406](https://github.com/Ombi-app/Ombi/commit/a0e14068f4bc457f8a4a565de71707a8f16c803c)) - - - -## [4.6.5](https://github.com/Ombi-app/Ombi/compare/v4.6.4...v4.6.5) (2021-11-15) - - -### Bug Fixes - -* **issues:** :bug: Added the issue category to the issue 'cards' [#4403](https://github.com/Ombi-app/Ombi/issues/4403) ([a3739f3](https://github.com/Ombi-app/Ombi/commit/a3739f375c49f48e34da12f0a74e4e068f12ab40)) -* **issues:** :bug: Added the issues back to the details page for TV Shows ([0225000](https://github.com/Ombi-app/Ombi/commit/02250000c08a253e57d8a0a855c2d30b8a1e5baa)) -* **issues:** :bug: Fixed an issue where you couldn't navigate to the details page from TV issues ([1a2825b](https://github.com/Ombi-app/Ombi/commit/1a2825bf3839b891b16e1dde4030afe53efe090e)) -* **issues:** :bug: Fixed where we did not show the poster when an issue is raised for media we do not have a request for [#4402](https://github.com/Ombi-app/Ombi/issues/4402) ([15e37b5](https://github.com/Ombi-app/Ombi/commit/15e37b532a83097dbdf1a9fea3eead7d0e211898)) - - - -## [4.6.4](https://github.com/Ombi-app/Ombi/compare/v4.6.3...v4.6.4) (2021-11-12) - - - -## [4.6.3](https://github.com/Ombi-app/Ombi/compare/v4.6.2...v4.6.3) (2021-11-11) - - -### Bug Fixes - -* **discover:** :bug: Display TV + movies on actor page in user language ([#4395](https://github.com/Ombi-app/Ombi/issues/4395)) ([fe635c7](https://github.com/Ombi-app/Ombi/commit/fe635c7106bc487ff879bdc8a73bab16cb389b97)) -* **permissions:** :bug: Improved the security around the role "Manage Own Requests" ([#4397](https://github.com/Ombi-app/Ombi/issues/4397)) ([334a32b](https://github.com/Ombi-app/Ombi/commit/334a32bca42f90198d9b720d2bdb710a583be47f)), closes [#4391](https://github.com/Ombi-app/Ombi/issues/4391) -* **search:** Fixed some cases where search wouldn't work correctly ([#4398](https://github.com/Ombi-app/Ombi/issues/4398)) ([4410790](https://github.com/Ombi-app/Ombi/commit/4410790bc096826bc11554098f846e3acb59589a)) - - - -## [4.6.2](https://github.com/Ombi-app/Ombi/compare/v4.6.1...v4.6.2) (2021-11-10) - - -### Bug Fixes - -* **discover:** TV shows now display on the Actor Pages ([#4388](https://github.com/Ombi-app/Ombi/issues/4388)) ([6b716e7](https://github.com/Ombi-app/Ombi/commit/6b716e722076e3d1e6bf2097c5263645d5ea9edf)) - - - -## [4.6.1](https://github.com/Ombi-app/Ombi/compare/v4.6.0...v4.6.1) (2021-11-10) - - -### Bug Fixes - -* :bug: Fixed the MySQL issue after .net 6 upgrade [#4393](https://github.com/Ombi-app/Ombi/issues/4393) ([fea7ff0](https://github.com/Ombi-app/Ombi/commit/fea7ff05139e9ff50c8097fa5389b4ef9ad21a15)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([c6acb45](https://github.com/Ombi-app/Ombi/commit/c6acb45f8d3f371c0b4024c4272849d0d0cc867f)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([18c220a](https://github.com/Ombi-app/Ombi/commit/18c220a0cd0d19e45a07d0c319da2b9512778a8a)) - - - -# [4.6.0](https://github.com/Ombi-app/Ombi/compare/v4.4.0...v4.6.0) (2021-11-09) - - -### Features - -* :sparkles: Upgrade Ombi to .NET 6 ([#4390](https://github.com/Ombi-app/Ombi/issues/4390)) ([719eb7d](https://github.com/Ombi-app/Ombi/commit/719eb7dbe37b3a72d264e2f670067518eef70694)), closes [#4392](https://github.com/Ombi-app/Ombi/issues/4392) - - - -# [4.4.0](https://github.com/Ombi-app/Ombi/compare/v4.3.3...v4.4.0) (2021-11-06) - - -### Bug Fixes - -* **request-list:** :bug: Fixed an issue where the request options were not appearing for Music requests ([c0406a2](https://github.com/Ombi-app/Ombi/commit/c0406a2ddebafb03d98ed25cdf7d89dc9a600c7d)) - - -### Features - -* **mass-email:** :sparkles: Added the ability to configure the Mass Email, we can now send BCC and we are less likely to be rate limited when not using bcc [#4377](https://github.com/Ombi-app/Ombi/issues/4377) ([ca655ae](https://github.com/Ombi-app/Ombi/commit/ca655ae57042dec44106a2f2ef5ba2e6f1019ee4)) - - - -## [4.3.3](https://github.com/Ombi-app/Ombi/compare/v4.3.2...v4.3.3) (2021-11-05) - - - -## [4.3.2](https://github.com/Ombi-app/Ombi/compare/v4.3.1...v4.3.2) (2021-11-02) - - -### Bug Fixes - -* **translations:** 🌐 Localization - Ensuring all of the app including backend are localized [#4366](https://github.com/Ombi-app/Ombi/issues/4366) ([5e140ab](https://github.com/Ombi-app/Ombi/commit/5e140ab6183b887a7665f5e870eb0bd05d487ace)) - - - -## [4.3.1](https://github.com/Ombi-app/Ombi/compare/v4.3.0...v4.3.1) (2021-10-27) - - -### Bug Fixes - -* :bug: Hides no results message during search. ([#4375](https://github.com/Ombi-app/Ombi/issues/4375)) ([b819b0e](https://github.com/Ombi-app/Ombi/commit/b819b0e007e578bf3d8425f19591f87029c64d06)) - - - -# [4.3.0](https://github.com/Ombi-app/Ombi/compare/v4.2.13...v4.3.0) (2021-10-20) - - -### Bug Fixes - -* **translations:** 🌐 New translations from Crowdin [skip ci] ([b0f3abb](https://github.com/Ombi-app/Ombi/commit/b0f3abb9ceebdbe5d6c20af98b7355df2999eb58)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([77d017b](https://github.com/Ombi-app/Ombi/commit/77d017b3d8ffd1714a2f6efecc8c900d56d062e4)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([f6e9784](https://github.com/Ombi-app/Ombi/commit/f6e9784367d3678d899ed79bef6caa52005b6661)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([601a877](https://github.com/Ombi-app/Ombi/commit/601a87762a2ad393ee5fa2fe52052ceeeefb1bef)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([a4a80ba](https://github.com/Ombi-app/Ombi/commit/a4a80ba4da49733a65e691003646c0f349bd4c5f)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([2961319](https://github.com/Ombi-app/Ombi/commit/2961319f61e95b2871480152b86ddca3375576a1)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([fc8d108](https://github.com/Ombi-app/Ombi/commit/fc8d108b660d53f499538328bfc271b05ac47d2b)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([1e03651](https://github.com/Ombi-app/Ombi/commit/1e03651c3b0eb77e45f9f6c55d31ee672eacd51e)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([c0dd327](https://github.com/Ombi-app/Ombi/commit/c0dd327426514e305a88750d7c3deb21c194108f)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([2156129](https://github.com/Ombi-app/Ombi/commit/2156129f175335746f204bb123035c070f518e96)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([aef0368](https://github.com/Ombi-app/Ombi/commit/aef0368de3aec306245bd1b16bc0de596a20d451)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([a38090b](https://github.com/Ombi-app/Ombi/commit/a38090b8dde17d1d150af0bca2830ea45d013a0e)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([c5f1d33](https://github.com/Ombi-app/Ombi/commit/c5f1d3355758a5c3648479d44e50397c7f6c1a9d)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([3846d56](https://github.com/Ombi-app/Ombi/commit/3846d56a6e561a1b1dc65c385151d90fdd6217ee)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([dafe9c1](https://github.com/Ombi-app/Ombi/commit/dafe9c1a19d84f00c13f0a51ba90927c24282926)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([edb418a](https://github.com/Ombi-app/Ombi/commit/edb418a6f05887c68a0c24c48decc691996f97e4)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([dadabf9](https://github.com/Ombi-app/Ombi/commit/dadabf93e1582a0c39321fd9bf3de3fb11e3f406)) - - -### Features - -* **request-limits:** :sparkles: Added the new request limit options into the user importer ([01d4f4d](https://github.com/Ombi-app/Ombi/commit/01d4f4d718fe85ac181dae52565fb1b427965b4f)) -* **request-limits:** :sparkles: Added the new request limit options to the bulk edit ([03bc23a](https://github.com/Ombi-app/Ombi/commit/03bc23a74e4308aa6b4c6b25636edcdeb65c1f0e)) - - - -## [4.2.13](https://github.com/Ombi-app/Ombi/compare/v4.2.12...v4.2.13) (2021-10-20) - - -### Bug Fixes - -* **translations:** 🌐 New translations %two_letters_code% from Crowdin [skip ci] ([8fbd267](https://github.com/Ombi-app/Ombi/commit/8fbd267b516ddaa80fd16c091bae532b860fbf45)) - - - -## [4.2.12](https://github.com/Ombi-app/Ombi/compare/v4.2.11...v4.2.12) (2021-10-20) - - -### Bug Fixes - -* **newsletter:** :bug: Fixed a few small bugs in the newsletter ([21dba4c](https://github.com/Ombi-app/Ombi/commit/21dba4c524b98b9f2b883d97e7e13329425a8762)) -* **translations:** 🌐 New translations en.json from Crowdin [skip ci] ([52eda6a](https://github.com/Ombi-app/Ombi/commit/52eda6ab917a73842bc02b0d8e0c442e564ca8f0)) -* **translations:** 🌐 New translations en.json from Crowdin [skip ci] ([1095d52](https://github.com/Ombi-app/Ombi/commit/1095d524962648a1e427f0bcd8105fa734dd5b60)) - - - -## [4.2.11](https://github.com/Ombi-app/Ombi/compare/v4.2.10...v4.2.11) (2021-10-18) - - - -## [4.2.10](https://github.com/Ombi-app/Ombi/compare/v4.2.9...v4.2.10) (2021-10-15) - - -### Bug Fixes - -* :bug: Really really fix it this time? ([543d36e](https://github.com/Ombi-app/Ombi/commit/543d36e5615341bc8378cac377b843a3dbc1ef99)) - - - -## [4.2.9](https://github.com/Ombi-app/Ombi/compare/v4.2.8...v4.2.9) (2021-10-15) - - -### Bug Fixes - -* :fire: Really fix the base url issue this time ([9f36923](https://github.com/Ombi-app/Ombi/commit/9f36923c51bfabf9cb026f2da14f9947050af0d9)) - - - -## [4.2.8](https://github.com/Ombi-app/Ombi/compare/v4.2.7...v4.2.8) (2021-10-15) - - -### Bug Fixes - -* :adhesive_bandage: See if this fixes the proxy issue ([74d1aca](https://github.com/Ombi-app/Ombi/commit/74d1acae499707a7e21401f53eb2bb90c5bb9cfa)) -* :bug: Fixed Ombi not writing the baseUrl correctly ([e9cc8b6](https://github.com/Ombi-app/Ombi/commit/e9cc8b6fe71d3e10c1a901e70227989b3362afe3)) - - - -## [4.2.7](https://github.com/Ombi-app/Ombi/compare/v4.2.6...v4.2.7) (2021-10-14) - - -### Bug Fixes - -* :bug: Fixed the issue parsing TheMovieDB dates. They have broken something... ([6e397e0](https://github.com/Ombi-app/Ombi/commit/6e397e02e95f894a92e8bf02428efdcac1275b31)) - - - -## [4.2.6](https://github.com/Ombi-app/Ombi/compare/v4.2.5...v4.2.6) (2021-10-14) - - -### Performance Improvements - -* :zap: Use ngxs store for the whole customization section of the app ([97b493d](https://github.com/Ombi-app/Ombi/commit/97b493d869feee59d360b484a6c59388a2aead1f)) - - - -## [4.2.5](https://github.com/Ombi-app/Ombi/compare/v4.2.4...v4.2.5) (2021-10-14) - +* **API:** Fixed an issue where the API key couldn't delete a request [#4489](https://github.com/Ombi-app/Ombi/issues/4489) ([8e42dbf](https://github.com/Ombi-app/Ombi/commit/8e42dbf8f78caa51ca891bf3d702c6b0ac401f9c)) diff --git a/README.md b/README.md index 6b785e94f..32552817e 100644 --- a/README.md +++ b/README.md @@ -106,14 +106,21 @@ Here are some of the features Ombi has: Anojh Thayaparan + + + sephrat +
+ Sephrat +
+ + Magikarplvl4
Magikarp Lvl 4
- - + MrTopCat @@ -135,13 +142,6 @@ Here are some of the features Ombi has: Matt Jeanes - - - sephrat -
- Sephrat -
- bernarden @@ -243,6 +243,13 @@ Here are some of the features Ombi has: + + + fservida +
+ Francesco Servida +
+ Patricol @@ -277,15 +284,15 @@ Here are some of the features Ombi has:
Aptalca
- + + mhann
Mhann
- - + ombi-bot @@ -320,15 +327,15 @@ Here are some of the features Ombi has:
D34DC3N73R
- + + pooley182
David Pooley
- - + Fredrik81 @@ -363,15 +370,15 @@ Here are some of the features Ombi has:
Marius Schiffer
- + + Qstick
Qstick
- - + Vbgf @@ -406,15 +413,15 @@ Here are some of the features Ombi has:
Alexander Standke
- + + Alasano
Aljosa Asanovic
- - + Ashyni @@ -449,15 +456,15 @@ Here are some of the features Ombi has:
Christopher Demicoli
- + + Codehhh
Codehhh
- - + danopia @@ -492,15 +499,15 @@ Here are some of the features Ombi has:
Eli
- + + Fish2
Fish2
- - + hariesramdhani @@ -535,15 +542,15 @@ Here are some of the features Ombi has:
Joe Groocock
- + + errorhandler
Joe Harvey
- - + jonbloom @@ -578,15 +585,15 @@ Here are some of the features Ombi has:
Lightkeeper
- + + devbymadde
Madeleine Schönemann
- - + mattmattmatt @@ -594,6 +601,13 @@ Here are some of the features Ombi has: Matt + + + LMaxence +
+ Maxence Lecanu +
+ AliMickey @@ -608,6 +622,14 @@ Here are some of the features Ombi has: Nathan Miller + + + cqxmzz +
+ Qiming Chen +
+ + randallbruder @@ -628,8 +650,7 @@ Here are some of the features Ombi has:
Samuel Bartík
- - + seancallinan @@ -650,7 +671,8 @@ Here are some of the features Ombi has:
Thomas Van Tilburg
- + + Tim-Trott @@ -671,8 +693,7 @@ Here are some of the features Ombi has:
Torkil
- - + bybeet @@ -693,7 +714,8 @@ Here are some of the features Ombi has:
Tim OBrien
- + + x-limitless-x @@ -714,8 +736,7 @@ Here are some of the features Ombi has:
Michael DiStaula
- - + baikunz @@ -736,7 +757,8 @@ Here are some of the features Ombi has:
Maartenheebink
- + + masterhuck @@ -757,8 +779,7 @@ Here are some of the features Ombi has:
Tdorsey
- - + thegame3202 diff --git a/crowdin.yml b/crowdin.yml index b7f48ef88..170fc200d 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -1,10 +1,10 @@ - commit_message: "fix(translations): 🌐 New translations from Crowdin [skip ci]" append_commit_message: false pull_request_title: "🌐 Translations Update" pull_request_labels: - translations - files: - source: /src/Ombi/wwwroot/translations/en.json translation: /src/Ombi/wwwroot/translations/%two_letters_code%.json + - source: /src/Ombi.I18n/Resources/Texts.resx + translation: /src/Ombi.I18n/Resources/Texts.%two_letters_code%.resx diff --git a/src/.idea/.idea.Ombi/.idea/contentModel.xml b/src/.idea/.idea.Ombi/.idea/contentModel.xml index 4affa7aee..438274536 100644 --- a/src/.idea/.idea.Ombi/.idea/contentModel.xml +++ b/src/.idea/.idea.Ombi/.idea/contentModel.xml @@ -929,7 +929,7 @@ - + @@ -1876,7 +1876,7 @@ - + diff --git a/src/Ombi.Api.CouchPotato/Ombi.Api.CouchPotato.csproj b/src/Ombi.Api.CouchPotato/Ombi.Api.CouchPotato.csproj index 6353f4bf9..89c47d251 100644 --- a/src/Ombi.Api.CouchPotato/Ombi.Api.CouchPotato.csproj +++ b/src/Ombi.Api.CouchPotato/Ombi.Api.CouchPotato.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Discord/Ombi.Api.Discord.csproj b/src/Ombi.Api.Discord/Ombi.Api.Discord.csproj index 4945a2fb2..70032d638 100644 --- a/src/Ombi.Api.Discord/Ombi.Api.Discord.csproj +++ b/src/Ombi.Api.Discord/Ombi.Api.Discord.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.DogNzb/Ombi.Api.DogNzb.csproj b/src/Ombi.Api.DogNzb/Ombi.Api.DogNzb.csproj index 6353f4bf9..89c47d251 100644 --- a/src/Ombi.Api.DogNzb/Ombi.Api.DogNzb.csproj +++ b/src/Ombi.Api.DogNzb/Ombi.Api.DogNzb.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Emby/EmbyApi.cs b/src/Ombi.Api.Emby/EmbyApi.cs index d911ca212..a1791494d 100644 --- a/src/Ombi.Api.Emby/EmbyApi.cs +++ b/src/Ombi.Api.Emby/EmbyApi.cs @@ -170,7 +170,7 @@ namespace Ombi.Api.Emby request.AddQueryString("Recursive", true.ToString()); request.AddQueryString("IncludeItemTypes", type); - request.AddQueryString("Fields", includeOverview ? "ProviderIds,Overview" : "ProviderIds"); + request.AddQueryString("Fields", includeOverview ? "ProviderIds,MediaStreams,Overview" : "ProviderIds,MediaStreams "); request.AddQueryString("startIndex", startIndex.ToString()); request.AddQueryString("limit", count.ToString()); request.AddQueryString("sortBy", "DateCreated"); @@ -221,7 +221,7 @@ namespace Ombi.Api.Emby request.AddQueryString("Recursive", true.ToString()); request.AddQueryString("IncludeItemTypes", type); - request.AddQueryString("Fields", includeOverview ? "ProviderIds,Overview" : "ProviderIds"); + request.AddQueryString("Fields", includeOverview ? "ProviderIds,Overview,MediaStreams" : "ProviderIds,MediaStreams"); request.AddQueryString("startIndex", startIndex.ToString()); request.AddQueryString("limit", count.ToString()); if (!string.IsNullOrEmpty(parentIdFilder)) diff --git a/src/Ombi.Api.Emby/Models/EmbyMediaType.cs b/src/Ombi.Api.Emby/Models/EmbyMediaType.cs deleted file mode 100644 index 7b33f8972..000000000 --- a/src/Ombi.Api.Emby/Models/EmbyMediaType.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ombi.Api.Emby.Models -{ - public enum EmbyMediaType - { - Movie = 0, - Series = 1, - Music = 2, - Episode = 3 - } -} \ No newline at end of file diff --git a/src/Ombi.Api.Emby/Models/Media/EmbyMediastream.cs b/src/Ombi.Api.Emby/Models/Media/EmbyMediastream.cs index 01032e0e7..f633f4ce0 100644 --- a/src/Ombi.Api.Emby/Models/Media/EmbyMediastream.cs +++ b/src/Ombi.Api.Emby/Models/Media/EmbyMediastream.cs @@ -2,35 +2,6 @@ namespace Ombi.Api.Emby.Models.Movie { public class EmbyMediastream { - public string Codec { get; set; } - public string Language { get; set; } - public string TimeBase { get; set; } - public string CodecTimeBase { get; set; } - public string NalLengthSize { get; set; } - public bool IsInterlaced { get; set; } - public bool IsAVC { get; set; } - public int BitRate { get; set; } - public int BitDepth { get; set; } - public int RefFrames { get; set; } - public bool IsDefault { get; set; } - public bool IsForced { get; set; } - public int Height { get; set; } - public int Width { get; set; } - public float AverageFrameRate { get; set; } - public float RealFrameRate { get; set; } - public string Profile { get; set; } - public string Type { get; set; } - public string AspectRatio { get; set; } - public int Index { get; set; } - public bool IsExternal { get; set; } - public bool IsTextSubtitleStream { get; set; } - public bool SupportsExternalStream { get; set; } - public string PixelFormat { get; set; } - public int Level { get; set; } - public bool IsAnamorphic { get; set; } public string DisplayTitle { get; set; } - public string ChannelLayout { get; set; } - public int Channels { get; set; } - public int SampleRate { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Api.Emby/Models/Media/EmbyProviderids.cs b/src/Ombi.Api.Emby/Models/Media/EmbyProviderids.cs index 8302ee3ee..4a19025de 100644 --- a/src/Ombi.Api.Emby/Models/Media/EmbyProviderids.cs +++ b/src/Ombi.Api.Emby/Models/Media/EmbyProviderids.cs @@ -1,12 +1,10 @@ -namespace Ombi.Api.Emby.Models.Movie -{ - public class EmbyProviderids - { - public string Tmdb { get; set; } - public string Imdb { get; set; } - public string TmdbCollection { get; set; } +using Ombi.Api.MediaServer.Models; - public string Tvdb { get; set; } +namespace Ombi.Api.Emby.Models.Movie +{ + public class EmbyProviderids: BaseProviderids + { + public string TmdbCollection { get; set; } public string Zap2It { get; set; } public string TvRage { get; set; } } diff --git a/src/Ombi.Api.Emby/Models/Media/Movie/EmbyMovie.cs b/src/Ombi.Api.Emby/Models/Media/Movie/EmbyMovie.cs index a10ddaae6..e127f75f6 100644 --- a/src/Ombi.Api.Emby/Models/Media/Movie/EmbyMovie.cs +++ b/src/Ombi.Api.Emby/Models/Media/Movie/EmbyMovie.cs @@ -30,5 +30,6 @@ namespace Ombi.Api.Emby.Models.Movie public int CriticRating { get; set; } public string Overview { get; set; } public EmbyProviderids ProviderIds { get; set; } + public EmbyMediastream[] MediaStreams { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Api.Emby/Ombi.Api.Emby.csproj b/src/Ombi.Api.Emby/Ombi.Api.Emby.csproj index f167146af..f60971192 100644 --- a/src/Ombi.Api.Emby/Ombi.Api.Emby.csproj +++ b/src/Ombi.Api.Emby/Ombi.Api.Emby.csproj @@ -6,12 +6,13 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild + diff --git a/src/Ombi.Api.FanartTv/Ombi.Api.FanartTv.csproj b/src/Ombi.Api.FanartTv/Ombi.Api.FanartTv.csproj index 4945a2fb2..70032d638 100644 --- a/src/Ombi.Api.FanartTv/Ombi.Api.FanartTv.csproj +++ b/src/Ombi.Api.FanartTv/Ombi.Api.FanartTv.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Github/Ombi.Api.Github.csproj b/src/Ombi.Api.Github/Ombi.Api.Github.csproj index 6353f4bf9..89c47d251 100644 --- a/src/Ombi.Api.Github/Ombi.Api.Github.csproj +++ b/src/Ombi.Api.Github/Ombi.Api.Github.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj b/src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj index 1285c073c..be32916f8 100644 --- a/src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj +++ b/src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.GroupMe/Ombi.Api.GroupMe.csproj b/src/Ombi.Api.GroupMe/Ombi.Api.GroupMe.csproj index 6353f4bf9..89c47d251 100644 --- a/src/Ombi.Api.GroupMe/Ombi.Api.GroupMe.csproj +++ b/src/Ombi.Api.GroupMe/Ombi.Api.GroupMe.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Jellyfin/JellyfinApi.cs b/src/Ombi.Api.Jellyfin/JellyfinApi.cs index 2fafbfd86..f6afb7912 100644 --- a/src/Ombi.Api.Jellyfin/JellyfinApi.cs +++ b/src/Ombi.Api.Jellyfin/JellyfinApi.cs @@ -157,7 +157,7 @@ namespace Ombi.Api.Jellyfin request.AddQueryString("Recursive", true.ToString()); request.AddQueryString("IncludeItemTypes", type); - request.AddQueryString("Fields", includeOverview ? "ProviderIds,Overview,ParentId" : "ProviderIds,ParentId"); + request.AddQueryString("Fields", includeOverview ? "ProviderIds,MediaStreams Overview,ParentId" : "ProviderIds,ParentId,MediaStreams"); request.AddQueryString("startIndex", startIndex.ToString()); request.AddQueryString("limit", count.ToString()); if(!string.IsNullOrEmpty(parentIdFilder)) diff --git a/src/Ombi.Api.Jellyfin/Models/JellyfinMediaType.cs b/src/Ombi.Api.Jellyfin/Models/JellyfinMediaType.cs deleted file mode 100644 index 2c4f75be0..000000000 --- a/src/Ombi.Api.Jellyfin/Models/JellyfinMediaType.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ombi.Api.Jellyfin.Models -{ - public enum JellyfinMediaType - { - Movie = 0, - Series = 1, - Music = 2, - Episode = 3 - } -} \ No newline at end of file diff --git a/src/Ombi.Api.Jellyfin/Models/Media/JellyfinMediastream.cs b/src/Ombi.Api.Jellyfin/Models/Media/JellyfinMediastream.cs index 89da2651a..e15a21e7b 100644 --- a/src/Ombi.Api.Jellyfin/Models/Media/JellyfinMediastream.cs +++ b/src/Ombi.Api.Jellyfin/Models/Media/JellyfinMediastream.cs @@ -2,35 +2,6 @@ namespace Ombi.Api.Jellyfin.Models.Movie { public class JellyfinMediastream { - public string Codec { get; set; } - public string Language { get; set; } - public string TimeBase { get; set; } - public string CodecTimeBase { get; set; } - public string NalLengthSize { get; set; } - public bool IsInterlaced { get; set; } - public bool IsAVC { get; set; } - public int BitRate { get; set; } - public int BitDepth { get; set; } - public int RefFrames { get; set; } - public bool IsDefault { get; set; } - public bool IsForced { get; set; } - public int Height { get; set; } - public int Width { get; set; } - public float AverageFrameRate { get; set; } - public float RealFrameRate { get; set; } - public string Profile { get; set; } - public string Type { get; set; } - public string AspectRatio { get; set; } - public int Index { get; set; } - public bool IsExternal { get; set; } - public bool IsTextSubtitleStream { get; set; } - public bool SupportsExternalStream { get; set; } - public string PixelFormat { get; set; } - public int Level { get; set; } - public bool IsAnamorphic { get; set; } public string DisplayTitle { get; set; } - public string ChannelLayout { get; set; } - public int Channels { get; set; } - public int SampleRate { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Api.Jellyfin/Models/Media/JellyfinProviderids.cs b/src/Ombi.Api.Jellyfin/Models/Media/JellyfinProviderids.cs index 9b47f9a1a..0896ec4e9 100644 --- a/src/Ombi.Api.Jellyfin/Models/Media/JellyfinProviderids.cs +++ b/src/Ombi.Api.Jellyfin/Models/Media/JellyfinProviderids.cs @@ -1,12 +1,10 @@ -namespace Ombi.Api.Jellyfin.Models.Movie -{ - public class JellyfinProviderids - { - public string Tmdb { get; set; } - public string Imdb { get; set; } - public string TmdbCollection { get; set; } +using Ombi.Api.MediaServer.Models; - public string Tvdb { get; set; } +namespace Ombi.Api.Jellyfin.Models.Movie +{ + public class JellyfinProviderids: BaseProviderids + { + public string TmdbCollection { get; set; } public string Zap2It { get; set; } public string TvRage { get; set; } } diff --git a/src/Ombi.Api.Jellyfin/Models/Media/Movie/JellyfinMovie.cs b/src/Ombi.Api.Jellyfin/Models/Media/Movie/JellyfinMovie.cs index d86bf5047..a83e1f087 100644 --- a/src/Ombi.Api.Jellyfin/Models/Media/Movie/JellyfinMovie.cs +++ b/src/Ombi.Api.Jellyfin/Models/Media/Movie/JellyfinMovie.cs @@ -30,5 +30,6 @@ namespace Ombi.Api.Jellyfin.Models.Movie public int CriticRating { get; set; } public string Overview { get; set; } public JellyfinProviderids ProviderIds { get; set; } + public JellyfinMediastream[] MediaStreams { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Api.Jellyfin/Ombi.Api.Jellyfin.csproj b/src/Ombi.Api.Jellyfin/Ombi.Api.Jellyfin.csproj index f167146af..0c745556e 100644 --- a/src/Ombi.Api.Jellyfin/Ombi.Api.Jellyfin.csproj +++ b/src/Ombi.Api.Jellyfin/Ombi.Api.Jellyfin.csproj @@ -6,13 +6,14 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild + \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/Ombi.Api.Lidarr.csproj b/src/Ombi.Api.Lidarr/Ombi.Api.Lidarr.csproj index 6353f4bf9..89c47d251 100644 --- a/src/Ombi.Api.Lidarr/Ombi.Api.Lidarr.csproj +++ b/src/Ombi.Api.Lidarr/Ombi.Api.Lidarr.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj b/src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj index a25024b6c..16c3a8558 100644 --- a/src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj +++ b/src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.MediaServer/Models/BaseProviderids.cs b/src/Ombi.Api.MediaServer/Models/BaseProviderids.cs new file mode 100644 index 000000000..6044288c6 --- /dev/null +++ b/src/Ombi.Api.MediaServer/Models/BaseProviderids.cs @@ -0,0 +1,11 @@ +namespace Ombi.Api.MediaServer.Models +{ + public class BaseProviderids + { + public string Tmdb { get; set; } + public string Imdb { get; set; } + public string Tvdb { get; set; } + public bool Any() => + !string.IsNullOrEmpty(Imdb) || !string.IsNullOrEmpty(Tmdb) || !string.IsNullOrEmpty(Tvdb); + } +} \ No newline at end of file diff --git a/src/Ombi.Api.MediaServer/Ombi.Api.MediaServer.csproj b/src/Ombi.Api.MediaServer/Ombi.Api.MediaServer.csproj new file mode 100644 index 000000000..a1b98b765 --- /dev/null +++ b/src/Ombi.Api.MediaServer/Ombi.Api.MediaServer.csproj @@ -0,0 +1,18 @@ + + + + net6.0 + 3.0.0.0 + 3.0.0.0 + + + latest + Debug;Release;NonUiBuild + + + + + + + + \ No newline at end of file diff --git a/src/Ombi.Api.MusicBrainz/Ombi.Api.MusicBrainz.csproj b/src/Ombi.Api.MusicBrainz/Ombi.Api.MusicBrainz.csproj index 584b980ce..c8a78e491 100644 --- a/src/Ombi.Api.MusicBrainz/Ombi.Api.MusicBrainz.csproj +++ b/src/Ombi.Api.MusicBrainz/Ombi.Api.MusicBrainz.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Notifications/Ombi.Api.Notifications.csproj b/src/Ombi.Api.Notifications/Ombi.Api.Notifications.csproj index f84a8add6..6406ef9de 100644 --- a/src/Ombi.Api.Notifications/Ombi.Api.Notifications.csproj +++ b/src/Ombi.Api.Notifications/Ombi.Api.Notifications.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Plex/IPlexApi.cs b/src/Ombi.Api.Plex/IPlexApi.cs index a4597765e..746c85b77 100644 --- a/src/Ombi.Api.Plex/IPlexApi.cs +++ b/src/Ombi.Api.Plex/IPlexApi.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; using Ombi.Api.Plex.Models; using Ombi.Api.Plex.Models.Friends; @@ -16,9 +17,9 @@ namespace Ombi.Api.Plex Task GetServer(string authToken); Task GetLibrarySections(string authToken, string plexFullHost); Task GetLibrary(string authToken, string plexFullHost, string libraryId); - Task GetEpisodeMetaData(string authToken, string host, int ratingKey); - Task GetMetadata(string authToken, string plexFullHost, int itemId); - Task GetSeasons(string authToken, string plexFullHost, int ratingKey); + Task GetEpisodeMetaData(string authToken, string host, string ratingKey); + Task GetMetadata(string authToken, string plexFullHost, string itemId); + Task GetSeasons(string authToken, string plexFullHost, string ratingKey); Task GetAllEpisodes(string authToken, string host, string section, int start, int retCount); Task GetUsers(string authToken); Task GetAccount(string authToken); @@ -26,5 +27,7 @@ namespace Ombi.Api.Plex Task GetPin(int pinId); Task GetOAuthUrl(string code, string applicationUrl); Task AddUser(string emailAddress, string serverId, string authToken, int[] libs); + Task GetWatchlist(string plexToken, CancellationToken cancellationToken); + Task GetWatchlistMetadata(string ratingKey, string plexToken, CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/src/Ombi.Api.Plex/Models/Metadata.cs b/src/Ombi.Api.Plex/Models/Metadata.cs index d0bb227ad..3481e9b57 100644 --- a/src/Ombi.Api.Plex/Models/Metadata.cs +++ b/src/Ombi.Api.Plex/Models/Metadata.cs @@ -4,7 +4,7 @@ namespace Ombi.Api.Plex.Models { public class Metadata { - public int ratingKey { get; set; } + public string ratingKey { get; set; } public string key { get; set; } public string studio { get; set; } public string type { get; set; } @@ -12,26 +12,18 @@ namespace Ombi.Api.Plex.Models public string contentRating { get; set; } public string summary { get; set; } public int index { get; set; } - public float rating { get; set; } - //public int viewCount { get; set; } - //public int lastViewedAt { get; set; } public int year { get; set; } public string thumb { get; set; } public string art { get; set; } public string banner { get; set; } public string theme { get; set; } - //public string duration { get; set; } - //public string originallyAvailableAt { get; set; } public int leafCount { get; set; } public int viewedLeafCount { get; set; } public int childCount { get; set; } - //public long addedAt { get; set; } - //public int updatedAt { get; set; } public Genre[] Genre { get; set; } - //public Role[] Role { get; set; } public string primaryExtraKey { get; set; } - public int parentRatingKey { get; set; } - public int grandparentRatingKey { get; set; } + public string parentRatingKey { get; set; } + public string grandparentRatingKey { get; set; } public string guid { get; set; } public int librarySectionID { get; set; } public string librarySectionKey { get; set; } @@ -47,12 +39,10 @@ namespace Ombi.Api.Plex.Models public string chapterSource { get; set; } public Medium[] Media { get; set; } public List Guid { get; set; } = new List(); - // public Director[] Director { get; set; } - // public Writer[] Writer { get; set; } } public class PlexGuids { public string Id { get; set; } } -} \ No newline at end of file +} diff --git a/src/Ombi.Api.Plex/Models/PlexWatchlist.cs b/src/Ombi.Api.Plex/Models/PlexWatchlist.cs new file mode 100644 index 000000000..52ca82cf9 --- /dev/null +++ b/src/Ombi.Api.Plex/Models/PlexWatchlist.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace Ombi.Api.Plex.Models +{ + public class PlexWatchlist + { + public string librarySectionID { get; set; } + public string librarySectionTitle { get; set; } + public int offset { get; set; } + public int totalSize { get; set; } + public int size { get; set; } + public List Metadata { get; set; } = new List(); + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Plex/Models/PlexWatchlistContainer.cs b/src/Ombi.Api.Plex/Models/PlexWatchlistContainer.cs new file mode 100644 index 000000000..b208c189f --- /dev/null +++ b/src/Ombi.Api.Plex/Models/PlexWatchlistContainer.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace Ombi.Api.Plex.Models +{ + public class PlexWatchlistContainer + { + public PlexWatchlist MediaContainer { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Plex/Models/PlexWatchlistMetadataContainer.cs b/src/Ombi.Api.Plex/Models/PlexWatchlistMetadataContainer.cs new file mode 100644 index 000000000..b582ca4e1 --- /dev/null +++ b/src/Ombi.Api.Plex/Models/PlexWatchlistMetadataContainer.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; + +namespace Ombi.Api.Plex.Models +{ + public class PlexWatchlistMetadataContainer + { + public PlexWatchlistMetadata MediaContainer { get; set; } + } + + + public class PlexWatchlistMetadata + { + public int offset { get; set; } + public int totalSize { get; set; } + public string identifier { get; set; } + public int size { get; set; } + public WatchlistMetadata[] Metadata { get; set; } + } + + public class WatchlistMetadata + { + public string guid { get; set; } + public string key { get; set; } + public string primaryExtraKey { get; set; } + public string ratingKey { get; set; } + public string type { get; set; } + public string slug { get; set; } + public string title { get; set; } + public List Guid { get; set; } = new List(); + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Plex/Ombi.Api.Plex.csproj b/src/Ombi.Api.Plex/Ombi.Api.Plex.csproj index 4945a2fb2..70032d638 100644 --- a/src/Ombi.Api.Plex/Ombi.Api.Plex.csproj +++ b/src/Ombi.Api.Plex/Ombi.Api.Plex.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Plex/PlexApi.cs b/src/Ombi.Api.Plex/PlexApi.cs index 176af31ec..9f91c540c 100644 --- a/src/Ombi.Api.Plex/PlexApi.cs +++ b/src/Ombi.Api.Plex/PlexApi.cs @@ -1,5 +1,6 @@ using System; using System.Net.Http; +using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json; using Ombi.Api.Plex.Models; @@ -66,6 +67,7 @@ namespace Ombi.Api.Plex private const string FriendsUri = "https://plex.tv/pms/friends/all"; private const string GetAccountUri = "https://plex.tv/users/account.json"; private const string ServerUri = "https://plex.tv/pms/servers.xml"; + private const string WatchlistUri = "https://metadata.provider.plex.tv/"; /// /// Sign into the Plex API @@ -145,21 +147,21 @@ namespace Ombi.Api.Plex /// /// /// - public async Task GetEpisodeMetaData(string authToken, string plexFullHost, int ratingKey) + public async Task GetEpisodeMetaData(string authToken, string plexFullHost, string ratingKey) { var request = new Request($"/library/metadata/{ratingKey}", plexFullHost, HttpMethod.Get); await AddHeaders(request, authToken); return await Api.Request(request); } - public async Task GetMetadata(string authToken, string plexFullHost, int itemId) + public async Task GetMetadata(string authToken, string plexFullHost, string itemId) { var request = new Request($"library/metadata/{itemId}", plexFullHost, HttpMethod.Get); await AddHeaders(request, authToken); return await Api.Request(request); } - public async Task GetSeasons(string authToken, string plexFullHost, int ratingKey) + public async Task GetSeasons(string authToken, string plexFullHost, string ratingKey) { var request = new Request($"library/metadata/{ratingKey}/children", plexFullHost, HttpMethod.Get); await AddHeaders(request, authToken); @@ -288,6 +290,26 @@ namespace Ombi.Api.Plex } } + public async Task GetWatchlist(string plexToken, CancellationToken cancellationToken) + { + var request = new Request("library/sections/watchlist/all", WatchlistUri, HttpMethod.Get); + await AddHeaders(request, plexToken); + + var result = await Api.Request(request, cancellationToken); + + return result; + } + + public async Task GetWatchlistMetadata(string ratingKey, string plexToken, CancellationToken cancellationToken) + { + var request = new Request($"library/metadata/{ratingKey}", WatchlistUri, HttpMethod.Get); + await AddHeaders(request, plexToken); + + var result = await Api.Request(request, cancellationToken); + + return result; + } + /// /// Adds the required headers and also the authorization header diff --git a/src/Ombi.Api.Pushbullet/Ombi.Api.Pushbullet.csproj b/src/Ombi.Api.Pushbullet/Ombi.Api.Pushbullet.csproj index 4945a2fb2..70032d638 100644 --- a/src/Ombi.Api.Pushbullet/Ombi.Api.Pushbullet.csproj +++ b/src/Ombi.Api.Pushbullet/Ombi.Api.Pushbullet.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Pushover/Ombi.Api.Pushover.csproj b/src/Ombi.Api.Pushover/Ombi.Api.Pushover.csproj index 1285c073c..be32916f8 100644 --- a/src/Ombi.Api.Pushover/Ombi.Api.Pushover.csproj +++ b/src/Ombi.Api.Pushover/Ombi.Api.Pushover.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Radarr/Models/V2/MovieResponse.cs b/src/Ombi.Api.Radarr/Models/V2/MovieResponse.cs index 6eb2f1c5a..f40dfcd80 100644 --- a/src/Ombi.Api.Radarr/Models/V2/MovieResponse.cs +++ b/src/Ombi.Api.Radarr/Models/V2/MovieResponse.cs @@ -44,7 +44,10 @@ namespace Ombi.Api.Radarr.Models public int id { get; set; } } - + public class MovieQuality + { + public V3.Quality quality { get; set; } + } public class Moviefile { public int movieId { get; set; } @@ -54,7 +57,7 @@ namespace Ombi.Api.Radarr.Models public DateTime dateAdded { get; set; } public string sceneName { get; set; } public int indexerFlags { get; set; } - public V3.Quality quality { get; set; } + public MovieQuality quality { get; set; } public Mediainfo mediaInfo { get; set; } public string originalFilePath { get; set; } public bool qualityCutoffNotMet { get; set; } @@ -74,13 +77,10 @@ namespace Ombi.Api.Radarr.Models public class Mediainfo { public string audioAdditionalFeatures { get; set; } - public int audioBitrate { get; set; } public float audioChannels { get; set; } public string audioCodec { get; set; } public string audioLanguages { get; set; } public int audioStreamCount { get; set; } - public int videoBitDepth { get; set; } - public int videoBitrate { get; set; } public string videoCodec { get; set; } public float videoFps { get; set; } public string resolution { get; set; } @@ -119,4 +119,4 @@ namespace Ombi.Api.Radarr.Models public int id { get; set; } public string name { get; set; } } -} \ No newline at end of file +} diff --git a/src/Ombi.Api.Radarr/Models/V3/RadarrV3QualityProfile.cs b/src/Ombi.Api.Radarr/Models/V3/RadarrV3QualityProfile.cs index d985da358..6eca4af87 100644 --- a/src/Ombi.Api.Radarr/Models/V3/RadarrV3QualityProfile.cs +++ b/src/Ombi.Api.Radarr/Models/V3/RadarrV3QualityProfile.cs @@ -25,5 +25,4 @@ public int resolution { get; set; } public string modifier { get; set; } } - } diff --git a/src/Ombi.Api.Radarr/Ombi.Api.Radarr.csproj b/src/Ombi.Api.Radarr/Ombi.Api.Radarr.csproj index f14df4f5f..889aa0ea6 100644 --- a/src/Ombi.Api.Radarr/Ombi.Api.Radarr.csproj +++ b/src/Ombi.Api.Radarr/Ombi.Api.Radarr.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.RottenTomatoes/Ombi.Api.RottenTomatoes.csproj b/src/Ombi.Api.RottenTomatoes/Ombi.Api.RottenTomatoes.csproj index 6353f4bf9..89c47d251 100644 --- a/src/Ombi.Api.RottenTomatoes/Ombi.Api.RottenTomatoes.csproj +++ b/src/Ombi.Api.RottenTomatoes/Ombi.Api.RottenTomatoes.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Service/Ombi.Api.Service.csproj b/src/Ombi.Api.Service/Ombi.Api.Service.csproj index a344de142..38bcd678a 100644 --- a/src/Ombi.Api.Service/Ombi.Api.Service.csproj +++ b/src/Ombi.Api.Service/Ombi.Api.Service.csproj @@ -8,7 +8,7 @@ Ombi.Api.Service Ombi.Api.Service - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.SickRage/Ombi.Api.SickRage.csproj b/src/Ombi.Api.SickRage/Ombi.Api.SickRage.csproj index 6353f4bf9..89c47d251 100644 --- a/src/Ombi.Api.SickRage/Ombi.Api.SickRage.csproj +++ b/src/Ombi.Api.SickRage/Ombi.Api.SickRage.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Slack/Ombi.Api.Slack.csproj b/src/Ombi.Api.Slack/Ombi.Api.Slack.csproj index 4945a2fb2..70032d638 100644 --- a/src/Ombi.Api.Slack/Ombi.Api.Slack.csproj +++ b/src/Ombi.Api.Slack/Ombi.Api.Slack.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Sonarr/Ombi.Api.Sonarr.csproj b/src/Ombi.Api.Sonarr/Ombi.Api.Sonarr.csproj index 4945a2fb2..70032d638 100644 --- a/src/Ombi.Api.Sonarr/Ombi.Api.Sonarr.csproj +++ b/src/Ombi.Api.Sonarr/Ombi.Api.Sonarr.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Telegram/Ombi.Api.Telegram.csproj b/src/Ombi.Api.Telegram/Ombi.Api.Telegram.csproj index 6353f4bf9..89c47d251 100644 --- a/src/Ombi.Api.Telegram/Ombi.Api.Telegram.csproj +++ b/src/Ombi.Api.Telegram/Ombi.Api.Telegram.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Trakt/Ombi.Api.Trakt.csproj b/src/Ombi.Api.Trakt/Ombi.Api.Trakt.csproj index e07f40c60..fd9632e56 100644 --- a/src/Ombi.Api.Trakt/Ombi.Api.Trakt.csproj +++ b/src/Ombi.Api.Trakt/Ombi.Api.Trakt.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.TvMaze/ITvMazeApi.cs b/src/Ombi.Api.TvMaze/ITvMazeApi.cs index 819051d83..983858810 100644 --- a/src/Ombi.Api.TvMaze/ITvMazeApi.cs +++ b/src/Ombi.Api.TvMaze/ITvMazeApi.cs @@ -8,10 +8,8 @@ namespace Ombi.Api.TvMaze public interface ITvMazeApi { Task> EpisodeLookup(int showId); - Task> GetSeasons(int id); Task> Search(string searchTerm); Task ShowLookup(int showId); Task ShowLookupByTheTvDbId(int theTvDbId); - Task GetTvFullInformation(int id); } } \ No newline at end of file diff --git a/src/Ombi.Api.TvMaze/Ombi.Api.TvMaze.csproj b/src/Ombi.Api.TvMaze/Ombi.Api.TvMaze.csproj index f167146af..a1b98b765 100644 --- a/src/Ombi.Api.TvMaze/Ombi.Api.TvMaze.csproj +++ b/src/Ombi.Api.TvMaze/Ombi.Api.TvMaze.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.TvMaze/TvMazeApi.cs b/src/Ombi.Api.TvMaze/TvMazeApi.cs index 5d761da47..3f37d7488 100644 --- a/src/Ombi.Api.TvMaze/TvMazeApi.cs +++ b/src/Ombi.Api.TvMaze/TvMazeApi.cs @@ -64,27 +64,5 @@ namespace Ombi.Api.TvMaze return null; } } - - public async Task> GetSeasons(int id) - { - var request = new Request($"shows/{id}/seasons", Uri, HttpMethod.Get); - - request.AddContentHeader("Content-Type", "application/json"); - - return await Api.Request>(request); - } - - public async Task GetTvFullInformation(int id) - { - var request = new Request($"shows/{id}", Uri, HttpMethod.Get); - - request.AddQueryString("embed[]", "cast"); - request.AddQueryString("embed[]", "crew"); - request.AddQueryString("embed[]", "episodes"); - - request.AddContentHeader("Content-Type", "application/json"); - - return await Api.Request(request); - } } } diff --git a/src/Ombi.Api/Ombi.Api.csproj b/src/Ombi.Api/Ombi.Api.csproj index 83c3ee62e..7670d4d14 100644 --- a/src/Ombi.Api/Ombi.Api.csproj +++ b/src/Ombi.Api/Ombi.Api.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Core.Tests/Engine/CalendarEngineTests.cs b/src/Ombi.Core.Tests/Engine/CalendarEngineTests.cs index b922a21c0..0a85fd058 100644 --- a/src/Ombi.Core.Tests/Engine/CalendarEngineTests.cs +++ b/src/Ombi.Core.Tests/Engine/CalendarEngineTests.cs @@ -10,6 +10,7 @@ using Ombi.Core.Authentication; using Ombi.Core.Engine.V2; using Ombi.Store.Entities.Requests; using Ombi.Store.Repository.Requests; +using Ombi.Core.Helpers; namespace Ombi.Core.Tests.Engine { @@ -25,7 +26,7 @@ namespace Ombi.Core.Tests.Engine { MovieRepo = new Mock(); TvRepo = new Mock(); - var principle = new Mock(); + var principle = new Mock(); var identity = new Mock(); identity.Setup(x => x.Name).Returns("UnitTest"); principle.Setup(x => x.Identity).Returns(identity.Object); diff --git a/src/Ombi.Core.Tests/Engine/MovieRequestEngineTests.cs b/src/Ombi.Core.Tests/Engine/MovieRequestEngineTests.cs index 9b12e0b01..f8ced161f 100644 --- a/src/Ombi.Core.Tests/Engine/MovieRequestEngineTests.cs +++ b/src/Ombi.Core.Tests/Engine/MovieRequestEngineTests.cs @@ -1,135 +1,520 @@ -//using System.Collections.Generic; -//using System.Linq; -//using System.Threading.Tasks; -//using Moq; -//using NUnit.Framework; -//using Ombi.Core.Engine; -//using Ombi.Core.Models.Requests; -//using Ombi.Store.Entities.Requests; -//using Ombi.Store.Repository; -//using Assert = Xunit.Assert; +using MockQueryable.Moq; +using Moq; +using Moq.AutoMock; +using NUnit.Framework; +using Ombi.Core.Authentication; +using Ombi.Core.Engine; +using Ombi.Core.Helpers; +using Ombi.Core.Models.Requests; +using Ombi.Store.Entities; +using Ombi.Store.Entities.Requests; +using Ombi.Store.Repository; +using Ombi.Store.Repository.Requests; +using Ombi.Test.Common; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Principal; +using System.Threading.Tasks; -//namespace Ombi.Core.Tests.Engine -//{ -// [TestFixture] -// public class MovieRequestEngineTests -// { -// public MovieRequestEngineTests() -// { -// RequestService = new Mock(); -// var requestService = new RequestService(null, RequestService.Object); -// Engine = new MovieRequestEngine(null, requestService, null, null, null, null, null, null); -// } +namespace Ombi.Core.Tests.Engine +{ + [TestFixture] + public class MovieRequestEngineTests + { + private MovieRequestEngine _subject; + private Mock _repoMock; + private AutoMocker _mocker; -// private MovieRequestEngine Engine { get; } -// private Mock RequestService { get; } + [SetUp] + public void Setup() + { + _mocker = new AutoMocker(); + var userManager = MockHelper.MockUserManager(new List { new OmbiUser { NormalizedUserName = "TEST", Id = "a" } }); + userManager.Setup(x => x.IsInRoleAsync(It.IsAny(), It.IsAny())).ReturnsAsync(true); + var principle = new Mock(); + var identity = new Mock(); + identity.Setup(x => x.Name).Returns("Test"); + principle.Setup(x => x.Identity).Returns(identity.Object); + var currentUser = new Mock(); + currentUser.Setup(x => x.Identity).Returns(identity.Object); + currentUser.Setup(x => x.Username).Returns("Test"); + currentUser.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { NormalizedUserName = "TEST", Id = "a" }); -// [Test] -// public async Task GetNewRequests_Should_ReturnEmpty_WhenThereAreNoNewRequests() -// { -// var requests = new List -// { -// new MovieRequests { Available = true }, -// new MovieRequests { Approved = true }, -// }; + _repoMock = new Mock(); + var requestServiceMock = new Mock(); + requestServiceMock.Setup(x => x.MovieRequestService).Returns(_repoMock.Object); -// var r = DbHelper.GetQueryable(requests[0], requests[1]); -// RequestService.Setup(x => x.Get()).Returns(r); + _mocker.Use(principle.Object); + _mocker.Use(currentUser.Object); + _mocker.Use(userManager.Object); + _mocker.Use(requestServiceMock); -// var result = await Engine.GetNewRequests(); + _subject = _mocker.CreateInstance(); + var list = DbHelper.GetQueryableMockDbSet(new RequestSubscription()); + _mocker.Setup, IQueryable>(x => x.GetAll()).Returns(new List().AsQueryable().BuildMock().Object); + } -// Assert.False(result.Any()); -// } + [Test] + public async Task GetRequestByStatus_PendingRequests_Non4K() + { + var movies = RegularRequestData(); + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); -// [Test] -// public async Task GetNewRequests_Should_ReturnOnlyNewRequests_WhenThereAreMultipleRequests() -// { -// var requests = new List -// { -// new MovieRequests { Available = true }, -// new MovieRequests { Approved = true }, -// new MovieRequests(), -// }; -// RequestService.Setup(x => x.Get()).Returns(requests.AsQueryable); + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", Models.Requests.RequestStatus.PendingApproval); -// var result = await Engine.GetNewRequests(); + Assert.That(result.Total, Is.EqualTo(1)); + Assert.That(result.Collection.First().Id, Is.EqualTo(4)); + } -// Assert.Single(result); -// Assert.All(result, x => -// { -// Assert.False(x.Available); -// Assert.False(x.Approved); -// }); -// } + [Test] + public async Task GetRequestByStatus_PendingRequests_4K() + { + var movies = new List + { + new MovieRequests + { + Id= 1, + Approved4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 2, + Approved4K = false, + Available4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 3, + Denied4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 4, + Has4KRequest = true, + Approved4K = false, + Available4K = false, + Denied4K = false, + RequestedDate = DateTime.MinValue + } + }; + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); -// [Test] -// public async Task GetApprovedRequests_Should_ReturnEmpty_WhenThereAreNoApprovedRequests() -// { -// var requests = new List -// { -// new MovieRequests { Available = true }, -// }; -// RequestService.Setup(x => x.Get()).Returns(requests.AsQueryable); + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", RequestStatus.PendingApproval); -// var result = await Engine.GetApprovedRequests(); + Assert.That(result.Total, Is.EqualTo(1)); + Assert.That(result.Collection.First().Id, Is.EqualTo(4)); + } -// Assert.False(result.Any()); -// } -// [Test] -// public async Task GetApprovedRequests_Should_ReturnOnlyApprovedRequests_WhenThereAreMultipleRequests() -// { -// var requests = new List -// { -// new MovieRequests { Available = true }, -// new MovieRequests { Approved = true }, -// new MovieRequests(), -// }; -// RequestService.Setup(x => x.Get()).Returns(requests.AsQueryable); + [Test] + public async Task GetRequestByStatus_PendingRequests_Both4K_And_Regular() + { + var movies = new List + { + new MovieRequests + { + Id= 1, + Approved = false, + Approved4K = true, + Has4KRequest = true, + RequestedDate = DateTime.Now + }, + new MovieRequests + { + Id = 2, + Approved4K = false, + Available4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 3, + Denied4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 4, + Has4KRequest = true, + Approved4K = false, + Available4K = false, + Denied4K = false, + RequestedDate = DateTime.MinValue + } + }; + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); -// var result = await Engine.GetApprovedRequests(); + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", RequestStatus.PendingApproval); -// Assert.Single(result); -// Assert.All(result, x => -// { -// Assert.False(x.Available); -// Assert.True(x.Approved); -// }); -// } + Assert.That(result.Total, Is.EqualTo(2)); + Assert.That(result.Collection.First().Id, Is.EqualTo(1)); + Assert.That(result.Collection.ToArray()[1].Id, Is.EqualTo(4)); + } -// [Test] -// public async Task GetAvailableRequests_Should_ReturnEmpty_WhenThereAreNoAvailableRequests() -// { -// var requests = new List -// { -// new MovieRequests { Approved = true }, -// }; -// RequestService.Setup(x => x.Get()).Returns(requests.AsQueryable); -// var result = await Engine.GetAvailableRequests(); + [Test] + public async Task GetRequestByStatus_ProcessingRequests_Non4K() + { + var movies = RegularRequestData(); + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); -// Assert.False(result.Any()); -// } + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", Models.Requests.RequestStatus.ProcessingRequest); -// [Test] -// public async Task GetAvailableRequests_Should_ReturnOnlyAvailableRequests_WhenThereAreMultipleRequests() -// { -// var requests = new List -// { -// new MovieRequests { Available = true }, -// new MovieRequests { Approved = true }, -// new MovieRequests(), -// }; -// RequestService.Setup(x => x.Get()).Returns(requests.AsQueryable); + Assert.That(result.Total, Is.EqualTo(1)); + Assert.That(result.Collection.First().Id, Is.EqualTo(1)); + } -// var result = await Engine.GetAvailableRequests(); + [Test] + public async Task GetRequestByStatus_ProcessingRequests_4K() + { + var movies = new List + { + new MovieRequests + { + Id= 1, + Approved4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 2, + Approved4K = false, + Available4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 3, + Denied4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 4, + Has4KRequest = true, + Approved4K = false, + Available4K = false, + Denied4K = false, + RequestedDate = DateTime.MinValue + } + }; + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); -// Assert.Single(result); -// Assert.All(result, x => -// { -// Assert.True(x.Available); -// Assert.False(x.Approved); -// }); -// } -// } -//} \ No newline at end of file + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", RequestStatus.ProcessingRequest); + + Assert.That(result.Total, Is.EqualTo(1)); + Assert.That(result.Collection.First().Id, Is.EqualTo(1)); + } + + + [Test] + public async Task GetRequestByStatus_ProcessingRequests_Both4K_And_Regular() + { + var movies = new List + { + new MovieRequests + { + Id= 1, + Approved = false, + Approved4K = true, + Has4KRequest = true, + RequestedDate = DateTime.Now + }, + new MovieRequests + { + Id = 2, + Approved4K = false, + Available4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 3, + Denied4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 4, + Has4KRequest = true, + Approved4K = false, + Approved = true, + Available4K = false, + Denied4K = false, + RequestedDate = DateTime.Now + } + }; + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); + + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", RequestStatus.ProcessingRequest); + + Assert.That(result.Total, Is.EqualTo(2)); + Assert.That(result.Collection.First().Id, Is.EqualTo(1)); + Assert.That(result.Collection.ToArray()[1].Id, Is.EqualTo(4)); + } + + + [Test] + public async Task GetRequestByStatus_AvailableRequests_Non4K() + { + List movies = RegularRequestData(); + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); + + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", Models.Requests.RequestStatus.Available); + + Assert.That(result.Total, Is.EqualTo(1)); + Assert.That(result.Collection.First().Id, Is.EqualTo(2)); + } + + + + [Test] + public async Task GetRequestByStatus_AvailableRequests_4K() + { + var movies = new List + { + new MovieRequests + { + Id= 1, + Approved4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 2, + Approved4K = false, + Available4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 3, + Denied4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 4, + Has4KRequest = true, + Approved4K = false, + Available4K = false, + Denied4K = false, + RequestedDate = DateTime.MinValue + } + }; + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); + + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", RequestStatus.Available); + + Assert.That(result.Total, Is.EqualTo(1)); + Assert.That(result.Collection.First().Id, Is.EqualTo(2)); + } + + + [Test] + public async Task GetRequestByStatus_AvailableRequests_Both4K_And_Regular() + { + var movies = new List + { + new MovieRequests + { + Id= 1, + Available = true, + Approved = false, + Approved4K = true, + Has4KRequest = true, + RequestedDate = DateTime.Now + }, + new MovieRequests + { + Id = 2, + Approved4K = false, + Available4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 3, + Denied4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 4, + Has4KRequest = true, + Approved4K = false, + Approved = true, + Available4K = false, + Denied4K = false, + RequestedDate = DateTime.Now + } + }; + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); + + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", RequestStatus.Available); + + Assert.That(result.Total, Is.EqualTo(2)); + Assert.That(result.Collection.First().Id, Is.EqualTo(1)); + Assert.That(result.Collection.ToArray()[1].Id, Is.EqualTo(2)); + } + + [Test] + public async Task GetRequestByStatus_DeniedRequests_Non4K() + { + List movies = RegularRequestData(); + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); + + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", Models.Requests.RequestStatus.Denied); + + Assert.That(result.Total, Is.EqualTo(1)); + Assert.That(result.Collection.First().Id, Is.EqualTo(3)); + } + + [Test] + public async Task GetRequestByStatus_DeniedRequests_4K() + { + var movies = new List + { + new MovieRequests + { + Id= 1, + Approved4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 2, + Approved4K = false, + Available4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 3, + Denied4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 4, + Has4KRequest = true, + Approved4K = false, + Available4K = false, + Denied4K = false, + RequestedDate = DateTime.MinValue + } + }; + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); + + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", RequestStatus.Denied); + + Assert.That(result.Total, Is.EqualTo(1)); + Assert.That(result.Collection.First().Id, Is.EqualTo(3)); + } + + + [Test] + public async Task GetRequestByStatus_DeniedRequests_Both4K_And_Regular() + { + var movies = new List + { + new MovieRequests + { + Id= 1, + Available = true, + Approved = false, + Approved4K = true, + Has4KRequest = true, + RequestedDate = DateTime.Now + }, + new MovieRequests + { + Id = 2, + Approved4K = false, + Available4K = true, + Denied = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 3, + Denied4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 4, + Has4KRequest = true, + Approved4K = false, + Approved = true, + Available4K = false, + Denied4K = false, + RequestedDate = DateTime.Now + } + }; + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); + + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", RequestStatus.Denied); + + Assert.That(result.Total, Is.EqualTo(2)); + Assert.That(result.Collection.First().Id, Is.EqualTo(2)); + Assert.That(result.Collection.ToArray()[1].Id, Is.EqualTo(3)); + } + + private static List RegularRequestData() + { + return new List + { + new MovieRequests + { + Id= 1, + Approved = true, + RequestedDate = DateTime.Now + }, + new MovieRequests + { + Id = 2, + Approved = false, + Available = true, + RequestedDate = DateTime.Now + }, + new MovieRequests + { + Id = 3, + Denied = true, + RequestedDate = DateTime.Now + }, + new MovieRequests + { + Id = 4, + Approved = false, + RequestedDate = DateTime.Now + } + }; + } + } +} \ No newline at end of file diff --git a/src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs b/src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs index a28081ebc..88e1c75d2 100644 --- a/src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs +++ b/src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs @@ -4,6 +4,7 @@ using Moq.AutoMock; using NUnit.Framework; using Ombi.Core.Authentication; using Ombi.Core.Engine; +using Ombi.Core.Helpers; using Ombi.Core.Models; using Ombi.Core.Services; using Ombi.Helpers; @@ -36,6 +37,13 @@ namespace Ombi.Core.Tests.Engine var identityMock = new Mock(); identityMock.SetupGet(x => x.Name).Returns("Test"); principleMock.SetupGet(x => x.Identity).Returns(identityMock.Object); + + var currentUser = new Mock(); + currentUser.Setup(x => x.Identity).Returns(identityMock.Object); + currentUser.Setup(x => x.Username).Returns("Test"); + currentUser.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "Test", NormalizedUserName = "TEST", Id = "a" }); + + _mocker.Use(currentUser.Object); _mocker.Use(principleMock.Object); _subject = _mocker.CreateInstance(); @@ -429,6 +437,7 @@ namespace Ombi.Core.Tests.Engine Id = "id1" }; var lastWeek = new DateTime(2020, 09, 05).AddMonths(-1).AddDays(-1); + var today = new DateTime(2020, 09, 15, 13, 0, 0); var log = new List { new RequestLog @@ -441,7 +450,7 @@ namespace Ombi.Core.Tests.Engine var repoMock = _mocker.GetMock>(); repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object); - var result = await _subject.GetRemainingMovieRequests(user); + var result = await _subject.GetRemainingMovieRequests(user, today); Assert.That(result, Is.InstanceOf() .With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true) @@ -474,7 +483,7 @@ namespace Ombi.Core.Tests.Engine var repoMock = _mocker.GetMock>(); repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object); - var result = await _subject.GetRemainingMovieRequests(user); + var result = await _subject.GetRemainingMovieRequests(user, today); Assert.That(result, Is.InstanceOf() .With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true) @@ -494,7 +503,7 @@ namespace Ombi.Core.Tests.Engine MovieRequestLimitType = RequestLimitType.Month, Id = "id1" }; - var today = DateTime.UtcNow; + var today = new DateTime(2022,2,2,13,0,0); var firstDayOfMonth = new DateTime(today.Year, today.Month, 1); var log = new List { @@ -514,7 +523,7 @@ namespace Ombi.Core.Tests.Engine var repoMock = _mocker.GetMock>(); repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object); - var result = await _subject.GetRemainingMovieRequests(user); + var result = await _subject.GetRemainingMovieRequests(user, today); Assert.That(result, Is.InstanceOf() .With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true) diff --git a/src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs b/src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs index d79e70322..93dd5050d 100644 --- a/src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs +++ b/src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs @@ -4,6 +4,7 @@ using Moq.AutoMock; using NUnit.Framework; using Ombi.Core.Authentication; using Ombi.Core.Engine; +using Ombi.Core.Helpers; using Ombi.Core.Models; using Ombi.Core.Services; using Ombi.Helpers; @@ -36,7 +37,12 @@ namespace Ombi.Core.Tests.Engine var identityMock = new Mock(); identityMock.SetupGet(x => x.Name).Returns("Test"); principleMock.SetupGet(x => x.Identity).Returns(identityMock.Object); + var currentUser = new Mock(); + currentUser.Setup(x => x.Identity).Returns(identityMock.Object); + currentUser.Setup(x => x.Username).Returns("Test"); + currentUser.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "Test", NormalizedUserName = "TEST", Id = "a" }); _mocker.Use(principleMock.Object); + _mocker.Use(currentUser.Object); _subject = _mocker.CreateInstance(); } @@ -494,7 +500,7 @@ namespace Ombi.Core.Tests.Engine MusicRequestLimitType = RequestLimitType.Month, Id = "id1" }; - var today = DateTime.UtcNow; + var today = new DateTime(2022, 2, 2, 13, 0, 0); var firstDayOfMonth = new DateTime(today.Year, today.Month, 1); var log = new List { @@ -514,7 +520,7 @@ namespace Ombi.Core.Tests.Engine var repoMock = _mocker.GetMock>(); repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object); - var result = await _subject.GetRemainingMusicRequests(user); + var result = await _subject.GetRemainingMusicRequests(user, today); Assert.That(result, Is.InstanceOf() .With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true) diff --git a/src/Ombi.Core.Tests/Engine/TvRequestLimitsTests.cs b/src/Ombi.Core.Tests/Engine/TvRequestLimitsTests.cs index e601ab84d..ba383da6c 100644 --- a/src/Ombi.Core.Tests/Engine/TvRequestLimitsTests.cs +++ b/src/Ombi.Core.Tests/Engine/TvRequestLimitsTests.cs @@ -4,6 +4,7 @@ using Moq.AutoMock; using NUnit.Framework; using Ombi.Core.Authentication; using Ombi.Core.Engine; +using Ombi.Core.Helpers; using Ombi.Core.Models; using Ombi.Core.Services; using Ombi.Helpers; @@ -33,7 +34,12 @@ namespace Ombi.Core.Tests.Engine var identityMock = new Mock(); identityMock.SetupGet(x => x.Name).Returns("Test"); principleMock.SetupGet(x => x.Identity).Returns(identityMock.Object); + var currentUser = new Mock(); + currentUser.Setup(x => x.Identity).Returns(identityMock.Object); + currentUser.Setup(x => x.Username).Returns("Test"); + currentUser.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "Test", NormalizedUserName = "TEST", Id = "a" }); _mocker.Use(principleMock.Object); + _mocker.Use(currentUser.Object); _subject = _mocker.CreateInstance(); } diff --git a/src/Ombi.Core.Tests/Engine/V2/MovieRequestEngineTests.cs b/src/Ombi.Core.Tests/Engine/V2/MovieRequestEngineTests.cs index 3c651b167..16b7cb811 100644 --- a/src/Ombi.Core.Tests/Engine/V2/MovieRequestEngineTests.cs +++ b/src/Ombi.Core.Tests/Engine/V2/MovieRequestEngineTests.cs @@ -7,8 +7,10 @@ using Moq; using NUnit.Framework; using Ombi.Api.TheMovieDb; using Ombi.Core.Engine; +using Ombi.Core.Helpers; using Ombi.Core.Models.Requests; using Ombi.Core.Rule.Interfaces; +using Ombi.Core.Services; using Ombi.Core.Settings; using Ombi.Helpers; using Ombi.Settings.Settings.Models; @@ -32,7 +34,7 @@ namespace Ombi.Core.Tests.Engine.V2 var requestService = new Mock(); _movieRequestRepository = new Mock(); requestService.Setup(x => x.MovieRequestService).Returns(_movieRequestRepository.Object); - var user = new Mock(); + var user = new Mock(); var notificationHelper = new Mock(); var rules = new Mock(); var movieSender = new Mock(); @@ -43,8 +45,9 @@ namespace Ombi.Core.Tests.Engine.V2 var ombiSettings = new Mock>(); var requestSubs = new Mock>(); var mediaCache = new Mock(); + var featureService = new Mock(); _engine = new MovieRequestEngine(movieApi.Object, requestService.Object, user.Object, notificationHelper.Object, rules.Object, movieSender.Object, - logger.Object, userManager.Object, requestLogRepo.Object, cache.Object, ombiSettings.Object, requestSubs.Object, mediaCache.Object); + logger.Object, userManager.Object, requestLogRepo.Object, cache.Object, ombiSettings.Object, requestSubs.Object, mediaCache.Object, featureService.Object); } [Test] diff --git a/src/Ombi.Core.Tests/Engine/V2/MusicSearchEngineV2Tests.cs b/src/Ombi.Core.Tests/Engine/V2/MusicSearchEngineV2Tests.cs index 50ab63346..1b773f060 100644 --- a/src/Ombi.Core.Tests/Engine/V2/MusicSearchEngineV2Tests.cs +++ b/src/Ombi.Core.Tests/Engine/V2/MusicSearchEngineV2Tests.cs @@ -23,6 +23,7 @@ using Ombi.Store.Entities; using Ombi.Store.Repository; using Ombi.Test.Common; using Artist = Hqub.MusicBrainz.API.Entities.Artist; +using Ombi.Core.Helpers; namespace Ombi.Core.Tests.Engine.V2 { @@ -45,7 +46,7 @@ namespace Ombi.Core.Tests.Engine.V2 .ForEach(b => F.Behaviors.Remove(b)); F.Behaviors.Add(new OmitOnRecursionBehavior()); - var principle = new Mock(); + var principle = new Mock(); var requestService = new Mock(); var ruleEval = new Mock(); var um = MockHelper.MockUserManager(new List()); diff --git a/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs b/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs index be874669c..4194ae0ea 100644 --- a/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs +++ b/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs @@ -9,6 +9,7 @@ using NUnit.Framework; using Ombi.Core.Authentication; using Ombi.Core.Engine; using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Helpers; using Ombi.Core.Models; using Ombi.Core.Rule.Interfaces; using Ombi.Core.Settings; @@ -32,8 +33,9 @@ namespace Ombi.Core.Tests.Engine TvRequestEngine = new Mock(); MovieRequestEngine = new Mock(); MovieRequestEngine = new Mock(); - User = new Mock(); - User.Setup(x => x.Identity.Name).Returns("abc"); + User = new Mock(); + User.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "abc", NormalizedUserName = "ABC", Id = "abc" }); + UserManager = MockHelper.MockUserManager(new List { new OmbiUser { Id = "abc", UserName = "abc", NormalizedUserName = "ABC" } }); Rule = new Mock(); Engine = new VoteEngine(VoteRepository.Object, User.Object, UserManager.Object, Rule.Object, VoteSettings.Object, MusicRequestEngine.Object, @@ -48,7 +50,7 @@ namespace Ombi.Core.Tests.Engine public Fixture F { get; set; } public VoteEngine Engine { get; set; } - public Mock User { get; set; } + public Mock User { get; set; } public Mock UserManager { get; set; } public Mock Rule { get; set; } public Mock> VoteRepository { get; set; } @@ -83,7 +85,7 @@ namespace Ombi.Core.Tests.Engine Assert.That(result.Result, Is.True); VoteRepository.Verify(x => x.Add(It.Is(c => c.UserId == "abc" && c.VoteType == type)), Times.Once); VoteRepository.Verify(x => x.Delete(It.IsAny()), Times.Never); - MovieRequestEngine.Verify(x => x.ApproveMovieById(1), Times.Never); + MovieRequestEngine.Verify(x => x.ApproveMovieById(1, false), Times.Never); } public static IEnumerable VoteData { @@ -129,7 +131,7 @@ namespace Ombi.Core.Tests.Engine Assert.That(result.Result, Is.False); VoteRepository.Verify(x => x.Delete(It.IsAny()), Times.Never); - MovieRequestEngine.Verify(x => x.ApproveMovieById(1), Times.Never); + MovieRequestEngine.Verify(x => x.ApproveMovieById(1, false), Times.Never); } public static IEnumerable AttemptedTwiceData { @@ -175,7 +177,7 @@ namespace Ombi.Core.Tests.Engine Assert.That(result.Result, Is.True); VoteRepository.Verify(x => x.Delete(It.IsAny()), Times.Once); VoteRepository.Verify(x => x.Add(It.Is(v => v.VoteType == type)), Times.Once); - MovieRequestEngine.Verify(x => x.ApproveMovieById(1), Times.Never); + MovieRequestEngine.Verify(x => x.ApproveMovieById(1, false), Times.Never); } public static IEnumerable VoteConvertData { diff --git a/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs b/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs index 595ba39e0..c73237097 100644 --- a/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs @@ -10,6 +10,8 @@ using Ombi.Test.Common; using System.Collections.Generic; using Ombi.Store.Entities; using System; +using Ombi.Core.Services; +using Ombi.Core.Helpers; namespace Ombi.Core.Tests.Rule.Request { @@ -26,23 +28,26 @@ namespace Ombi.Core.Tests.Rule.Request public void Setup() { - PrincipalMock = new Mock(); - PrincipalMock.Setup(x => x.Identity.Name).Returns("abc"); + FeatureService = new Mock(); + + PrincipalMock = new Mock(); + PrincipalMock.Setup(x => x.Username).Returns("abc"); + PrincipalMock.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "abc", NormalizedUserName = "ABC", Id = "a" }); UserManager = MockHelper.MockUserManager(_users); - Rule = new AutoApproveRule(PrincipalMock.Object, UserManager.Object); + Rule = new AutoApproveRule(PrincipalMock.Object, UserManager.Object, FeatureService.Object); } - private AutoApproveRule Rule { get; set; } - private Mock PrincipalMock { get; set; } + private Mock PrincipalMock { get; set; } private Mock UserManager { get; set; } + private Mock FeatureService { get; set; } [Test] public async Task Should_ReturnSuccess_WhenAdminAndRequestMovie() { UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.Admin)).ReturnsAsync(true); - var request = new BaseRequest() { RequestType = Store.Entities.RequestType.Movie }; + var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie }; var result = await Rule.Execute(request); Assert.True(result.Success); @@ -64,7 +69,7 @@ namespace Ombi.Core.Tests.Rule.Request public async Task Should_ReturnSuccess_WhenAutoApproveMovieAndRequestMovie() { UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.AutoApproveMovie)).ReturnsAsync(true); - var request = new BaseRequest() { RequestType = Store.Entities.RequestType.Movie }; + var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie }; var result = await Rule.Execute(request); Assert.True(result.Success); @@ -96,7 +101,8 @@ namespace Ombi.Core.Tests.Rule.Request [Test] public async Task Should_ReturnSuccess_WhenSystemUserAndRequestTV() { - PrincipalMock.Setup(x => x.Identity.Name).Returns("sys"); + PrincipalMock.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "sys", NormalizedUserName = "SYS", Id = "a" }); + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.AutoApproveTv)).ReturnsAsync(false); var request = new BaseRequest() { RequestType = Store.Entities.RequestType.TvShow }; var result = await Rule.Execute(request); @@ -137,5 +143,17 @@ namespace Ombi.Core.Tests.Rule.Request Assert.True(result.Success); Assert.False(request.Approved); } + + [Test] + public async Task Should_ReturnFail_When4kRequestAndFeatureNotEnabled() + { + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), It.IsAny())).ReturnsAsync(false); + var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie, Is4kRequest = true }; + var result = await Rule.Execute(request); + + Assert.True(result.Success); + Assert.False(request.Approved); + Assert.False(request.Approved4K); + } } } diff --git a/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs b/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs index 03dc6f68c..9d8db25d1 100644 --- a/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Moq; using NUnit.Framework; using Ombi.Core.Authentication; +using Ombi.Core.Helpers; using Ombi.Core.Rule.Rules; using Ombi.Core.Rule.Rules.Request; using Ombi.Helpers; @@ -26,8 +27,9 @@ namespace Ombi.Core.Tests.Rule.Request public void Setup() { - PrincipalMock = new Mock(); - PrincipalMock.Setup(x => x.Identity.Name).Returns("abc"); + PrincipalMock = new Mock(); + PrincipalMock.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "abc", NormalizedUserName = "ABC", Id = "a" }); + UserManager = MockHelper.MockUserManager(_users); Rule = new CanRequestRule(PrincipalMock.Object, UserManager.Object); @@ -35,14 +37,49 @@ namespace Ombi.Core.Tests.Rule.Request private CanRequestRule Rule { get; set; } - private Mock PrincipalMock { get; set; } + private Mock PrincipalMock { get; set; } private Mock UserManager { get; set; } [Test] public async Task Should_ReturnSuccess_WhenRequestingMovieWithMovieRole() { UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.RequestMovie)).ReturnsAsync(true); - var request = new BaseRequest() { RequestType = Store.Entities.RequestType.Movie }; + var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie }; + var result = await Rule.Execute(request); + + Assert.True(result.Success); + } + + [Test] + public async Task Should_ReturnSuccess_WhenRequestingMovie4KWithMovieRole() + { + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.RequestMovie)).ReturnsAsync(true); + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.Request4KMovie)).ReturnsAsync(true); + var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie, Has4KRequest = true }; + var result = await Rule.Execute(request); + + Assert.True(result.Success); + } + + [Test] + public async Task Should_ReturnFailure_WhenRequestingMovie4KWithMovieRole() + { + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.RequestMovie)).ReturnsAsync(true); + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.Request4KMovie)).ReturnsAsync(false); + var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie, Is4kRequest = true }; + var result = await Rule.Execute(request); + + Assert.False(result.Success); + Assert.False(string.IsNullOrEmpty(result.Message)); + } + + [Test] + public async Task Should_ReturnSuccess_WhenRequestingMovie4KWithAutoApprove() + { + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.RequestMovie)).ReturnsAsync(true); + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.AutoApproveMovie)).ReturnsAsync(true); + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.Request4KMovie)).ReturnsAsync(false); + var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie, Has4KRequest = true }; var result = await Rule.Execute(request); Assert.True(result.Success); @@ -52,7 +89,7 @@ namespace Ombi.Core.Tests.Rule.Request public async Task Should_ReturnFail_WhenRequestingMovieWithoutMovieRole() { UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.RequestMovie)).ReturnsAsync(false); - var request = new BaseRequest() { RequestType = Store.Entities.RequestType.Movie }; + var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie }; var result = await Rule.Execute(request); Assert.False(result.Success); @@ -72,7 +109,8 @@ namespace Ombi.Core.Tests.Rule.Request [Test] public async Task Should_ReturnSuccess_WhenRequestingMovieWithSystemRole() { - PrincipalMock.Setup(x => x.Identity.Name).Returns("sys"); + PrincipalMock.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "sys", NormalizedUserName = "SYS", Id = "a" }); + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.Admin)).ReturnsAsync(false); var request = new BaseRequest() { RequestType = Store.Entities.RequestType.Movie }; var result = await Rule.Execute(request); diff --git a/src/Ombi.Core.Tests/Rule/Request/ExistingMovieRequestRuleTests.cs b/src/Ombi.Core.Tests/Rule/Request/ExistingMovieRequestRuleTests.cs index 7ff69c9f2..682d4bf4d 100644 --- a/src/Ombi.Core.Tests/Rule/Request/ExistingMovieRequestRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Request/ExistingMovieRequestRuleTests.cs @@ -9,7 +9,9 @@ using NUnit.Framework; using Ombi.Core.Authentication; using Ombi.Core.Rule.Rules; using Ombi.Core.Rule.Rules.Request; +using Ombi.Core.Services; using Ombi.Helpers; +using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; using Ombi.Store.Repository.Requests; @@ -24,12 +26,14 @@ namespace Ombi.Core.Tests.Rule.Request public void Setup() { ContextMock = new Mock(); - Rule = new ExistingMovieRequestRule(ContextMock.Object); + FeatureService = new Mock(); + Rule = new ExistingMovieRequestRule(ContextMock.Object, FeatureService.Object); } private ExistingMovieRequestRule Rule { get; set; } private Mock ContextMock { get; set; } + private Mock FeatureService { get; set; } [Test] public async Task ExistingRequestRule_Movie_Has_Been_Requested_With_TheMovieDBId() @@ -96,5 +100,82 @@ namespace Ombi.Core.Tests.Rule.Request Assert.That(result.Success, Is.True); Assert.That(result.Message, Is.Null.Or.Empty); } + + [Test] + public async Task ExistingRequestRule_Movie_HasAlready4K_Request() + { + ContextMock.Setup(x => x.GetAll()).Returns(new List + { + new MovieRequests + { + TheMovieDbId = 2, + ImdbId = "2", + RequestType = RequestType.Movie, + Is4kRequest = true + } + }.AsQueryable().BuildMock().Object); + var o = new MovieRequests + { + TheMovieDbId = 2, + ImdbId = "1", + Has4KRequest = true + }; + var result = await Rule.Execute(o); + + Assert.That(result.Success, Is.False); + Assert.That(result.Message, Is.Not.Empty); + } + + [Test] + public async Task ExistingRequestRule_Movie_4K_Request() + { + FeatureService.Setup(x => x.FeatureEnabled(FeatureNames.Movie4KRequests)).ReturnsAsync(true); + ContextMock.Setup(x => x.GetAll()).Returns(new List + { + new MovieRequests + { + TheMovieDbId = 2, + ImdbId = "2", + RequestType = RequestType.Movie, + Is4kRequest = false + } + }.AsQueryable().BuildMock().Object); + var o = new MovieRequests + { + TheMovieDbId = 2, + ImdbId = "1", + Is4kRequest = true + }; + var result = await Rule.Execute(o); + + Assert.That(result.Success, Is.True); + Assert.That(result.Message, Is.Null.Or.Empty); + } + + [Test] + public async Task ExistingRequestRule_Movie_4K_Request_FeatureNotEnabled() + { + FeatureService.Setup(x => x.FeatureEnabled(FeatureNames.Movie4KRequests)).ReturnsAsync(false); + ContextMock.Setup(x => x.GetAll()).Returns(new List + { + new MovieRequests + { + TheMovieDbId = 2, + ImdbId = "2", + RequestType = RequestType.Movie, + Is4kRequest = false + } + }.AsQueryable().BuildMock().Object); + var o = new MovieRequests + { + TheMovieDbId = 2, + ImdbId = "1", + Is4kRequest = true + }; + var result = await Rule.Execute(o); + + Assert.That(result.Success, Is.False); + Assert.That(result.Message, Is.Not.Null); + } } } diff --git a/src/Ombi.Core.Tests/Rule/Request/ExistingPlexRequestRuleTests.cs b/src/Ombi.Core.Tests/Rule/Request/ExistingPlexRequestRuleTests.cs index f5a362303..314b543b8 100644 --- a/src/Ombi.Core.Tests/Rule/Request/ExistingPlexRequestRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Request/ExistingPlexRequestRuleTests.cs @@ -1,6 +1,7 @@ using MockQueryable.Moq; using Moq; using NUnit.Framework; +using Ombi.Core.Engine; using Ombi.Core.Rule.Rules.Request; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; @@ -176,17 +177,58 @@ namespace Ombi.Core.Tests.Rule.Request Assert.That(result.Success, Is.True); } + [Test] + public async Task RequestMovie_IsSuccessful() + { + SetupMockData(); + + var req = new MovieRequests + { + RequestType = RequestType.Movie, + TheMovieDbId = 123, + Id = 1, + }; + var result = await Rule.Execute(req); + + + Assert.That(result.Success, Is.True); + } + + [Test] + public async Task RequestMovie_IsAlreadyAvailable() + { + var content = new List { + new PlexServerContent + { + TheMovieDbId = 123.ToString(), + } + }; + PlexContentRepo.Setup(x => x.GetAll()).Returns(content.AsQueryable().BuildMock().Object); + + var req = new MovieRequests + { + RequestType = RequestType.Movie, + TheMovieDbId = 123, + Id = 1, + }; + var result = await Rule.Execute(req); + + + Assert.That(result.Success, Is.False); + Assert.That(result.ErrorCode, Is.EqualTo(ErrorCode.AlreadyRequested)); + } + private void SetupMockData() { var childRequests = new List { new PlexServerContent { - Type = PlexMediaTypeEntity.Show, + Type = MediaType.Series, TheMovieDbId = "1", Title = "Test", ReleaseYear = "2001", - Episodes = new List + Episodes = new List { new PlexEpisode { diff --git a/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs index 132f51e49..484e872e2 100644 --- a/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs @@ -1,11 +1,14 @@ using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Rules.Search; +using Ombi.Core.Services; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; +using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; using Ombi.Store.Repository; using Ombi.Store.Repository.Requests; @@ -18,21 +21,23 @@ namespace Ombi.Core.Tests.Rule.Search public void Setup() { ContextMock = new Mock(); - SettingsMock = new Mock>(); - Rule = new EmbyAvailabilityRule(ContextMock.Object, SettingsMock.Object); + LoggerMock = new Mock>(); + FeatureMock = new Mock(); + Rule = new EmbyAvailabilityRule(ContextMock.Object, LoggerMock.Object, FeatureMock.Object); } private EmbyAvailabilityRule Rule { get; set; } private Mock ContextMock { get; set; } - private Mock> SettingsMock { get; set; } + private Mock> LoggerMock { get; set; } + private Mock FeatureMock { get; set; } [Test] public async Task Movie_ShouldBe_Available_WhenFoundInEmby() { - SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new EmbySettings()); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new EmbyContent { - ProviderId = "123" + TheMovieDbId = "123", + Quality = "1" }); var search = new SearchMovieViewModel() { @@ -45,24 +50,13 @@ namespace Ombi.Core.Tests.Rule.Search } [Test] - public async Task Movie_Has_Custom_Url_When_Specified_In_Settings() + public async Task Movie_ShouldBe_Available_WhenFoundInEmby_4K() { - SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new EmbySettings - { - Enable = true, - Servers = new List - { - new EmbyServers - { - ServerHostname = "http://test.com/", - ServerId = "8" - } - } - }); + FeatureMock.Setup(x => x.FeatureEnabled(FeatureNames.Movie4KRequests)).ReturnsAsync(true); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new EmbyContent { - ProviderId = "123", - EmbyId = 1.ToString(), + TheMovieDbId = "123", + Has4K = true }); var search = new SearchMovieViewModel() { @@ -71,28 +65,19 @@ namespace Ombi.Core.Tests.Rule.Search var result = await Rule.Execute(search); Assert.True(result.Success); - Assert.That(search.EmbyUrl, Is.EqualTo("http://test.com/web/index.html#!/item?id=1&serverId=8")); + Assert.True(search.Available4K); + Assert.False(search.Available); } [Test] - public async Task Movie_Uses_Default_Url_When() + public async Task Movie_ShouldBe_Available_WhenFoundInEmby_Both() { - SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new EmbySettings - { - Enable = true, - Servers = new List - { - new EmbyServers - { - ServerHostname = string.Empty, - ServerId = "8" - } - } - }); + FeatureMock.Setup(x => x.FeatureEnabled(FeatureNames.Movie4KRequests)).ReturnsAsync(true); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new EmbyContent { - ProviderId = "123", - EmbyId = 1.ToString() + TheMovieDbId = "123", + Has4K = true, + Quality = "1" }); var search = new SearchMovieViewModel() { @@ -101,7 +86,8 @@ namespace Ombi.Core.Tests.Rule.Search var result = await Rule.Execute(search); Assert.True(result.Success); - Assert.That(search.EmbyUrl, Is.EqualTo("https://app.emby.media/web/index.html#!/item?id=1&serverId=8")); + Assert.True(search.Available4K); + Assert.True(search.Available); } [Test] diff --git a/src/Ombi.Core.Tests/Rule/Search/ExistingRequestRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/ExistingRequestRuleTests.cs index 11860ce28..66601f936 100644 --- a/src/Ombi.Core.Tests/Rule/Search/ExistingRequestRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/ExistingRequestRuleTests.cs @@ -30,13 +30,14 @@ namespace Ombi.Core.Tests.Rule.Search [Test] - public async Task ShouldBe_Requested_WhenExisitngMovie() + public async Task ShouldBe_Requested_WhenExistingMovie() { var list = new MovieRequests { TheMovieDbId = 123, Approved = true, - RequestType = RequestType.Movie + RequestType = RequestType.Movie, + RequestedDate = System.DateTime.Now, }; MovieMock.Setup(x => x.GetRequestAsync(123)).ReturnsAsync(list); diff --git a/src/Ombi.Core.Tests/Rule/Search/JellyfinAvailabilityRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/JellyfinAvailabilityRuleTests.cs index 1b838f102..f56876e48 100644 --- a/src/Ombi.Core.Tests/Rule/Search/JellyfinAvailabilityRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/JellyfinAvailabilityRuleTests.cs @@ -1,11 +1,14 @@ using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Rules.Search; +using Ombi.Core.Services; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; +using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; using Ombi.Store.Repository; using Ombi.Store.Repository.Requests; @@ -18,21 +21,23 @@ namespace Ombi.Core.Tests.Rule.Search public void Setup() { ContextMock = new Mock(); - SettingsMock = new Mock>(); - Rule = new JellyfinAvailabilityRule(ContextMock.Object, SettingsMock.Object); + LoggerMock = new Mock>(); + FeatureMock = new Mock(); + Rule = new JellyfinAvailabilityRule(ContextMock.Object, LoggerMock.Object, FeatureMock.Object); } private JellyfinAvailabilityRule Rule { get; set; } private Mock ContextMock { get; set; } - private Mock> SettingsMock { get; set; } + private Mock> LoggerMock { get; set; } + private Mock FeatureMock { get; set; } [Test] public async Task Movie_ShouldBe_Available_WhenFoundInJellyfin() { - SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new JellyfinSettings()); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new JellyfinContent { - ProviderId = "123" + TheMovieDbId = "123", + Quality = "1080" }); var search = new SearchMovieViewModel() { @@ -45,24 +50,13 @@ namespace Ombi.Core.Tests.Rule.Search } [Test] - public async Task Movie_Has_Custom_Url_When_Specified_In_Settings() + public async Task Movie_ShouldBe_Available_WhenFoundInJellyfin_4K() { - SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new JellyfinSettings - { - Enable = true, - Servers = new List - { - new JellyfinServers - { - ServerHostname = "http://test.com/", - ServerId = "8" - } - } - }); + FeatureMock.Setup(x => x.FeatureEnabled(FeatureNames.Movie4KRequests)).ReturnsAsync(true); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new JellyfinContent { - ProviderId = "123", - JellyfinId = 1.ToString(), + TheMovieDbId = "123", + Has4K = true }); var search = new SearchMovieViewModel() { @@ -71,29 +65,37 @@ namespace Ombi.Core.Tests.Rule.Search var result = await Rule.Execute(search); Assert.True(result.Success); - Assert.That(search.JellyfinUrl, Is.EqualTo("http://test.com/web/index.html#!/details?id=1&serverId=8")); + Assert.False(search.Available); + Assert.True(search.Available4K); + } + + [Test] + public async Task Movie_ShouldBe_Available_WhenFoundInJellyfin_Both() + { + FeatureMock.Setup(x => x.FeatureEnabled(FeatureNames.Movie4KRequests)).ReturnsAsync(true); + ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new JellyfinContent + { + TheMovieDbId = "123", + Has4K = true, + Quality = "1" + }); + var search = new SearchMovieViewModel() + { + TheMovieDbId = "123", + }; + var result = await Rule.Execute(search); + + Assert.True(result.Success); + Assert.True(search.Available); + Assert.True(search.Available4K); } [Test] public async Task Movie_Uses_Default_Url_When() { - SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new JellyfinSettings - { - Enable = true, - Servers = new List - { - new JellyfinServers - { - Ip = "8080", - Port = 9090, - ServerHostname = string.Empty, - ServerId = "8" - } - } - }); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new JellyfinContent { - ProviderId = "123", + TheMovieDbId = "123", JellyfinId = 1.ToString() }); var search = new SearchMovieViewModel() diff --git a/src/Ombi.Core.Tests/Rule/Search/RadarrCacheRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/RadarrCacheRuleTests.cs index 94efe89a2..8c5e0c662 100644 --- a/src/Ombi.Core.Tests/Rule/Search/RadarrCacheRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/RadarrCacheRuleTests.cs @@ -28,25 +28,67 @@ namespace Ombi.Core.Tests.Rule.Search { var list = new List(){new RadarrCache { - TheMovieDbId = 123 + TheMovieDbId = 123, + HasRegular = true }}.AsQueryable(); - + ContextMock.Setup(x => x.GetAll()).Returns(list); var request = new SearchMovieViewModel { Id = 123 }; - var result =await Rule.Execute(request); + var result = await Rule.Execute(request); Assert.True(result.Success); Assert.True(request.Approved); } + [Test] + public async Task Should_ReturnAvailabl_WhenMovieIsInRadarr_4K() + { + var list = new List(){new RadarrCache + { + TheMovieDbId = 123, + Has4K = true, + HasFile = true + }}.AsQueryable(); + + ContextMock.Setup(x => x.GetAll()).Returns(list); + + var request = new SearchMovieViewModel { Id = 123 }; + var result = await Rule.Execute(request); + + Assert.True(result.Success); + Assert.False(request.Available); + Assert.True(request.Available4K); + } + + [Test] + public async Task Should_ReturnAvailable_WhenMovieIsInRadarr_Both() + { + var list = new List(){new RadarrCache + { + TheMovieDbId = 123, + Has4K = true, + HasRegular = true, + HasFile = true + }}.AsQueryable(); + + ContextMock.Setup(x => x.GetAll()).Returns(list); + + var request = new SearchMovieViewModel { Id = 123 }; + var result = await Rule.Execute(request); + + Assert.True(result.Success); + Assert.True(request.Available); + Assert.True(request.Available4K); + + } [Test] public async Task Should_ReturnNotApproved_WhenMovieIsNotInRadarr() { var list = DbHelper.GetQueryableMockDbSet(new RadarrCache { - TheMovieDbId = 000012 + TheMovieDbId = 000012, }); ContextMock.Setup(x => x.GetAll()).Returns(list); diff --git a/src/Ombi.Core/Authentication/OmbiUserManager.cs b/src/Ombi.Core/Authentication/OmbiUserManager.cs index 87f82c1de..124ff1aeb 100644 --- a/src/Ombi.Core/Authentication/OmbiUserManager.cs +++ b/src/Ombi.Core/Authentication/OmbiUserManager.cs @@ -116,16 +116,25 @@ namespace Ombi.Core.Authentication public async Task GetOmbiUserFromPlexToken(string plexToken) { var plexAccount = await _plexApi.GetAccount(plexToken); - + // Check for a ombi user - if (plexAccount?.user != null) + if (plexAccount?.user == null) { - var potentialOmbiUser = await Users.FirstOrDefaultAsync(x => - x.ProviderUserId == plexAccount.user.id); - return potentialOmbiUser; + return null; } - return null; + var potentialOmbiUser = await Users.FirstOrDefaultAsync(x => + x.ProviderUserId == plexAccount.user.id); + // Update ombi user with the token + + if (potentialOmbiUser != null) + { + potentialOmbiUser.MediaServerToken = plexAccount.user.authentication_token; + await UpdateAsync(potentialOmbiUser); + } + + return potentialOmbiUser; + } @@ -142,6 +151,10 @@ namespace Ombi.Core.Authentication var result = await _plexApi.SignIn(new UserRequest { password = password, login = login }); if (result.user?.authentication_token != null) { + // Update ombi user with the token + user.MediaServerToken = result.user?.authentication_token; + await UpdateAsync(user); + return true; } return false; diff --git a/src/Ombi.Core/Engine/BaseMediaEngine.cs b/src/Ombi.Core/Engine/BaseMediaEngine.cs index 277144ab1..ee1ce55a8 100644 --- a/src/Ombi.Core/Engine/BaseMediaEngine.cs +++ b/src/Ombi.Core/Engine/BaseMediaEngine.cs @@ -26,7 +26,7 @@ namespace Ombi.Core.Engine private Dictionary _dbMovies; private Dictionary _dbTv; - protected BaseMediaEngine(IPrincipal identity, IRequestServiceMain requestService, + protected BaseMediaEngine(ICurrentUser identity, IRequestServiceMain requestService, IRuleEvaluator rules, OmbiUserManager um, ICacheService cache, ISettingsService ombiSettings, IRepository sub) : base(identity, um, rules) { RequestService = requestService; diff --git a/src/Ombi.Core/Engine/Demo/DemoMovieSearchEngine.cs b/src/Ombi.Core/Engine/Demo/DemoMovieSearchEngine.cs index f392bf7ad..af88813d9 100644 --- a/src/Ombi.Core/Engine/Demo/DemoMovieSearchEngine.cs +++ b/src/Ombi.Core/Engine/Demo/DemoMovieSearchEngine.cs @@ -11,6 +11,7 @@ using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; using Ombi.Config; using Ombi.Core.Authentication; +using Ombi.Core.Helpers; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; @@ -24,7 +25,7 @@ namespace Ombi.Core.Engine.Demo { public class DemoMovieSearchEngine : MovieSearchEngine, IDemoMovieSearchEngine { - public DemoMovieSearchEngine(IPrincipal identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, + public DemoMovieSearchEngine(ICurrentUser identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, ILogger logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService s, IRepository sub, IOptions lists) : base(identity, service, movApi, mapper, logger, r, um, mem, s, sub) diff --git a/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs b/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs index 2c91a458f..706a5337d 100644 --- a/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs +++ b/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs @@ -4,6 +4,7 @@ using Ombi.Api.Trakt; using Ombi.Api.TvMaze; using Ombi.Config; using Ombi.Core.Authentication; +using Ombi.Core.Helpers; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; @@ -24,7 +25,7 @@ namespace Ombi.Core.Engine.Demo public class DemoTvSearchEngine : TvSearchEngine, IDemoTvSearchEngine { - public DemoTvSearchEngine(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, + public DemoTvSearchEngine(ICurrentUser identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ICacheService memCache, ISettingsService s, IRepository sub, IOptions lists, IImageService imageService, ISettingsService custom) diff --git a/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs b/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs index e949ac297..2c68ea371 100644 --- a/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs @@ -1,42 +1,35 @@ using System; using Ombi.Core.Rule; using System.Collections.Generic; -using System.Security.Principal; using System.Threading.Tasks; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; using Ombi.Store.Entities.Requests; using Ombi.Store.Entities; -using Microsoft.EntityFrameworkCore; using Ombi.Core.Authentication; -using Ombi.Helpers; +using Ombi.Core.Helpers; namespace Ombi.Core.Engine.Interfaces { public abstract class BaseEngine { - protected BaseEngine(IPrincipal user, OmbiUserManager um, IRuleEvaluator rules) + protected BaseEngine(ICurrentUser user, OmbiUserManager um, IRuleEvaluator rules) { - UserPrinciple = user; + CurrentUser = user; Rules = rules; UserManager = um; } - protected IPrincipal UserPrinciple { get; } + protected ICurrentUser CurrentUser { get; } protected IRuleEvaluator Rules { get; } - protected OmbiUserManager UserManager { get; } - protected string Username => UserPrinciple.Identity.Name; + protected OmbiUserManager UserManager { get; } + protected string Username => CurrentUser.Username; + protected Task GetUser() => CurrentUser.GetUser(); - private OmbiUser _user; - protected async Task GetUser() - { - if(!Username.HasValue()) - { - return null; - } - var username = Username.ToUpper(); - return _user ??= await UserManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); - } + /// + /// Only used for background tasks + /// + public void SetUser(OmbiUser user) => CurrentUser.SetUser(user); protected async Task UserAlias() { @@ -45,9 +38,14 @@ namespace Ombi.Core.Engine.Interfaces protected async Task IsInRole(string roleName) { - return await UserManager.IsInRoleAsync(await GetUser(), roleName); + if (Username.Equals("API", StringComparison.CurrentCultureIgnoreCase)) + { + return true; + } + var user = await GetUser(); + return await UserManager.IsInRoleAsync(user, roleName); } - + public async Task> RunRequestRules(BaseRequest model) { var ruleResults = await Rules.StartRequestRules(model); diff --git a/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs b/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs index 7cc64bee2..ab7a9079a 100644 --- a/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs @@ -18,9 +18,9 @@ namespace Ombi.Core.Engine.Interfaces Task RemoveAllMovieRequests(); Task GetRequest(int requestId); Task UpdateMovieRequest(MovieRequests request); - Task ApproveMovie(MovieRequests request); - Task ApproveMovieById(int requestId); - Task DenyMovieById(int modelId, string denyReason); + Task ApproveMovie(MovieRequests request, bool is4K); + Task ApproveMovieById(int requestId, bool is4K); + Task DenyMovieById(int modelId, string denyReason, bool is4K); Task> GetRequests(int count, int position, string sortProperty, string sortOrder); Task> GetUnavailableRequests(int count, int position, string sortProperty, diff --git a/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs b/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs index 44278753f..01300287e 100644 --- a/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs @@ -19,11 +19,12 @@ namespace Ombi.Core.Engine.Interfaces Task> GetRequests(); Task UserHasRequest(string userId); - Task MarkUnavailable(int modelId); - Task MarkAvailable(int modelId); + Task MarkUnavailable(int modelId, bool is4K); + Task MarkAvailable(int modelId, bool is4K); Task GetTotal(); Task UnSubscribeRequest(int requestId, RequestType type); Task SubscribeToRequest(int requestId, RequestType type); - Task ReProcessRequest(int requestId, CancellationToken cancellationToken); + Task ReProcessRequest(int requestId, bool is4K, CancellationToken cancellationToken); + void SetUser(OmbiUser user); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index f69e890be..cb4cb4ba6 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -22,15 +22,18 @@ using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; using Ombi.Core.Models; using System.Threading; +using Ombi.Core.Services; +using Ombi.Core.Helpers; namespace Ombi.Core.Engine { public class MovieRequestEngine : BaseMediaEngine, IMovieRequestEngine { - public MovieRequestEngine(IMovieDbApi movieApi, IRequestServiceMain requestService, IPrincipal user, + public MovieRequestEngine(IMovieDbApi movieApi, IRequestServiceMain requestService, ICurrentUser user, INotificationHelper helper, IRuleEvaluator r, IMovieSender sender, ILogger log, OmbiUserManager manager, IRepository rl, ICacheService cache, - ISettingsService ombiSettings, IRepository sub, IMediaCacheService mediaCacheService) + ISettingsService ombiSettings, IRepository sub, IMediaCacheService mediaCacheService, + IFeatureService featureService) : base(user, requestService, r, manager, cache, ombiSettings, sub) { MovieApi = movieApi; @@ -39,6 +42,7 @@ namespace Ombi.Core.Engine Logger = log; _requestLog = rl; _mediaCacheService = mediaCacheService; + _featureService = featureService; } private IMovieDbApi MovieApi { get; } @@ -47,6 +51,7 @@ namespace Ombi.Core.Engine private ILogger Logger { get; } private readonly IRepository _requestLog; private readonly IMediaCacheService _mediaCacheService; + private readonly IFeatureService _featureService; /// /// Requests the movie. @@ -72,7 +77,8 @@ namespace Ombi.Core.Engine var userDetails = await GetUser(); var canRequestOnBehalf = model.RequestOnBehalf.HasValue(); - var isAdmin = await UserManager.IsInRoleAsync(userDetails, OmbiRoles.PowerUser) || await UserManager.IsInRoleAsync(userDetails, OmbiRoles.Admin); + var isAdmin = await UserManager.IsInRoleAsync(userDetails, OmbiRoles.PowerUser) + || await UserManager.IsInRoleAsync(userDetails, OmbiRoles.Admin); if (canRequestOnBehalf && !isAdmin) { return new RequestEngineResult @@ -93,27 +99,54 @@ namespace Ombi.Core.Engine }; } - var requestModel = new MovieRequests + var is4kFeatureEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests); + var is4kRequest = is4kFeatureEnabled && model.Is4kRequest; + + MovieRequests requestModel; + bool isExisting = false; + // Do we already have a request? 4k or non 4k + var existingRequest = await MovieRepository.GetRequestAsync(movieInfo.Id); + if (existingRequest != null && is4kFeatureEnabled) { - TheMovieDbId = movieInfo.Id, - RequestType = RequestType.Movie, - Overview = movieInfo.Overview, - ImdbId = movieInfo.ImdbId, - PosterPath = PosterPathHelper.FixPosterPath(movieInfo.PosterPath), - Title = movieInfo.Title, - ReleaseDate = !string.IsNullOrEmpty(movieInfo.ReleaseDate) - ? DateTime.Parse(movieInfo.ReleaseDate) - : DateTime.MinValue, - Status = movieInfo.Status, - RequestedDate = DateTime.UtcNow, - Approved = false, - RequestedUserId = canRequestOnBehalf ? model.RequestOnBehalf : userDetails.Id, - Background = movieInfo.BackdropPath, - LangCode = model.LanguageCode, - RequestedByAlias = model.RequestedByAlias, - RootPathOverride = model.RootFolderOverride.GetValueOrDefault(), - QualityOverride = model.QualityPathOverride.GetValueOrDefault() - }; + if (model.Is4kRequest) + { + existingRequest.Is4kRequest = true; + existingRequest.RequestedDate4k = DateTime.Now; + } + else + { + existingRequest.RequestedDate = DateTime.Now; + } + isExisting = true; + requestModel = existingRequest; + } + else + { + requestModel = new MovieRequests + { + TheMovieDbId = movieInfo.Id, + RequestType = RequestType.Movie, + Overview = movieInfo.Overview, + ImdbId = movieInfo.ImdbId, + PosterPath = PosterPathHelper.FixPosterPath(movieInfo.PosterPath), + Title = movieInfo.Title, + ReleaseDate = !string.IsNullOrEmpty(movieInfo.ReleaseDate) + ? DateTime.Parse(movieInfo.ReleaseDate) + : DateTime.MinValue, + Status = movieInfo.Status, + RequestedDate = model.Is4kRequest ? DateTime.MinValue : DateTime.Now, + Approved = false, + RequestedUserId = canRequestOnBehalf ? model.RequestOnBehalf : userDetails.Id, + Background = movieInfo.BackdropPath, + LangCode = model.LanguageCode, + RequestedByAlias = model.RequestedByAlias, + RootPathOverride = model.RootFolderOverride.GetValueOrDefault(), + QualityOverride = model.QualityPathOverride.GetValueOrDefault(), + RequestedDate4k = model.Is4kRequest ? DateTime.Now : DateTime.MinValue, + Is4kRequest = model.Is4kRequest, + Source = model.Source + }; + } var usDates = movieInfo.ReleaseDates?.Results?.FirstOrDefault(x => x.IsoCode == "US"); requestModel.DigitalReleaseDate = usDates?.ReleaseDate @@ -132,10 +165,10 @@ namespace Ombi.Core.Engine if (requestModel.Approved) // The rules have auto approved this { - var requestEngineResult = await AddMovieRequest(requestModel, fullMovieName, model.RequestOnBehalf); + var requestEngineResult = await AddMovieRequest(requestModel, fullMovieName, model.RequestOnBehalf, isExisting, is4kRequest); if (requestEngineResult.Result) { - var result = await ApproveMovie(requestModel); + var result = await ApproveMovie(requestModel, model.Is4kRequest); if (result.IsError) { Logger.LogWarning("Tried auto sending movie but failed. Message: {0}", result.Message); @@ -153,7 +186,7 @@ namespace Ombi.Core.Engine // If there are no providers then it's successful but movie has not been sent } - return await AddMovieRequest(requestModel, fullMovieName, model.RequestOnBehalf); + return await AddMovieRequest(requestModel, fullMovieName, model.RequestOnBehalf, isExisting, is4kRequest); } @@ -218,7 +251,7 @@ namespace Ombi.Core.Engine var requests = await (OrderMovies(allRequests, orderFilter.OrderType)).Skip(position).Take(count) .ToListAsync(); - await CheckForSubscription(shouldHide, requests); + await CheckForSubscription(shouldHide.UserId, requests); return new RequestsViewModel { Collection = requests, @@ -262,7 +295,7 @@ namespace Ombi.Core.Engine var total = requests.Count(); requests = requests.Skip(position).Take(count).ToList(); - await CheckForSubscription(shouldHide, requests); + await CheckForSubscription(shouldHide.UserId, requests); return new RequestsViewModel { Collection = requests, @@ -290,21 +323,44 @@ namespace Ombi.Core.Engine switch (status) { case RequestStatus.PendingApproval: - allRequests = allRequests.Where(x => !x.Approved && !x.Available && (!x.Denied.HasValue || !x.Denied.Value)); + allRequests = allRequests.Where(x => + (x.RequestedDate != DateTime.MinValue && !x.Approved && !x.Available && (!x.Denied.HasValue || !x.Denied.Value)) + || + (x.Has4KRequest && !x.Approved4K && !x.Available4K && (!x.Denied4K.HasValue || !x.Denied4K.Value)) + ); break; case RequestStatus.ProcessingRequest: - allRequests = allRequests.Where(x => x.Approved && !x.Available && (!x.Denied.HasValue || !x.Denied.Value)); + allRequests = allRequests.Where(x => + (x.RequestedDate != DateTime.MinValue && x.Approved && !x.Available && (!x.Denied.HasValue || !x.Denied.Value)) + || + (x.Has4KRequest && x.Approved4K && !x.Available && (!x.Denied.HasValue || !x.Denied.Value)) + ); break; case RequestStatus.Available: - allRequests = allRequests.Where(x => x.Available); + allRequests = allRequests.Where(x => x.Available || x.Available4K); break; case RequestStatus.Denied: - allRequests = allRequests.Where(x => x.Denied.HasValue && x.Denied.Value && !x.Available); + allRequests = allRequests.Where(x => + (x.Denied.HasValue && x.Denied.Value && !x.Available) + || + (x.Has4KRequest && x.Denied4K.HasValue && x.Denied4K.Value && !x.Available4K) + ); break; default: break; } + var requests = allRequests.ToList(); + var total = requests.Count; + if (total == 0) + { + return new RequestsViewModel + { + Collection = Enumerable.Empty(), + Total = total + }; + } + var prop = TypeDescriptor.GetProperties(typeof(MovieRequests)).Find(sortProperty, true); if (sortProperty.Contains('.')) @@ -317,14 +373,14 @@ namespace Ombi.Core.Engine //var secondProp = TypeDescriptor.GetProperties(propType).Find(properties[1], true); } - // TODO fix this so we execute this on the server - var requests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase) + requests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase) ? allRequests.ToList().OrderBy(x => prop.GetValue(x)).ToList() : allRequests.ToList().OrderByDescending(x => prop.GetValue(x)).ToList(); - var total = requests.Count(); + + // TODO fix this so we execute this on the server requests = requests.Skip(position).Take(count).ToList(); - await CheckForSubscription(shouldHide, requests); + await CheckForSubscription(shouldHide.UserId, requests); return new RequestsViewModel { Collection = requests, @@ -367,7 +423,7 @@ namespace Ombi.Core.Engine var total = requests.Count(); requests = requests.Skip(position).Take(count).ToList(); - await CheckForSubscription(shouldHide, requests); + await CheckForSubscription(shouldHide.UserId, requests); return new RequestsViewModel { Collection = requests, @@ -449,7 +505,7 @@ namespace Ombi.Core.Engine allRequests = await MovieRepository.GetWithUser().ToListAsync(); } - await CheckForSubscription(shouldHide, allRequests); + await CheckForSubscription(shouldHide.UserId, allRequests); return allRequests; } @@ -457,21 +513,21 @@ namespace Ombi.Core.Engine public async Task GetRequest(int requestId) { var request = await MovieRepository.GetWithUser().Where(x => x.Id == requestId).FirstOrDefaultAsync(); - await CheckForSubscription(new HideResult(), new List { request }); + await CheckForSubscription((await GetUser()).Id, new List { request }); return request; } - private async Task CheckForSubscription(HideResult shouldHide, List movieRequests) + private async Task CheckForSubscription(string UserId, List movieRequests) { var requestIds = movieRequests.Select(x => x.Id); var sub = await _subscriptionRepository.GetAll().Where(s => - s.UserId == shouldHide.UserId && requestIds.Contains(s.RequestId) && s.RequestType == RequestType.Movie) + s.UserId == UserId && requestIds.Contains(s.RequestId) && s.RequestType == RequestType.Movie) .ToListAsync(); foreach (var x in movieRequests) { x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath); - if (shouldHide.UserId == x.RequestedUserId) + if (UserId == x.RequestedUserId) { x.ShowSubscribe = false; } @@ -503,18 +559,18 @@ namespace Ombi.Core.Engine } var results = allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToList(); - await CheckForSubscription(shouldHide, results); + await CheckForSubscription(shouldHide.UserId, results); return results; } - public async Task ApproveMovieById(int requestId) + public async Task ApproveMovieById(int requestId, bool is4K) { var request = await MovieRepository.Find(requestId); - return await ApproveMovie(request); + return await ApproveMovie(request, is4K); } - public async Task DenyMovieById(int modelId, string denyReason) + public async Task DenyMovieById(int modelId, string denyReason, bool is4K) { var request = await MovieRepository.Find(modelId); if (request == null) @@ -525,8 +581,16 @@ namespace Ombi.Core.Engine }; } - request.Denied = true; - request.DeniedReason = denyReason; + if (is4K) + { + request.Denied4K = true; + request.DeniedReason4K = denyReason; + } + else + { + request.Denied = true; + request.DeniedReason = denyReason; + } await MovieRepository.Update(request); await _mediaCacheService.Purge(); @@ -540,7 +604,7 @@ namespace Ombi.Core.Engine }; } - public async Task ApproveMovie(MovieRequests request) + public async Task ApproveMovie(MovieRequests request, bool is4K) { if (request == null) { @@ -550,9 +614,18 @@ namespace Ombi.Core.Engine }; } - request.MarkedAsApproved = DateTime.Now; - request.Approved = true; - request.Denied = false; + if (is4K) + { + request.MarkedAsApproved4K = DateTime.Now; + request.Approved4K = true; + request.Denied4K = false; + } + else + { + request.MarkedAsApproved = DateTime.Now; + request.Approved = true; + request.Denied = false; + } await MovieRepository.Update(request); var canNotify = await RunSpecificRule(request, SpecificRules.CanSendNotification, string.Empty); @@ -562,7 +635,7 @@ namespace Ombi.Core.Engine } await _mediaCacheService.Purge(); - return await ProcessSendingMovie(request); + return await ProcessSendingMovie(request, is4K); } public async Task RequestCollection(int collectionId, CancellationToken cancellationToken) @@ -590,11 +663,11 @@ namespace Ombi.Core.Engine return new RequestEngineResult { Result = true, Message = $"The collection {collections.name} has been successfully added!", RequestId = results.FirstOrDefault().RequestId }; } - private async Task ProcessSendingMovie(MovieRequests request) + private async Task ProcessSendingMovie(MovieRequests request, bool is4K) { - if (request.Approved) + if (is4K ? request.Approved4K : request.Approved) { - var result = await Sender.Send(request); + var result = await Sender.Send(request, is4K); if (result.Success && result.Sent) { return new RequestEngineResult @@ -662,7 +735,7 @@ namespace Ombi.Core.Engine var result = await CheckCanManageRequest(request); if (result.IsError) return result; - + await MovieRepository.Delete(request); await _mediaCacheService.Purge(); return new RequestEngineResult @@ -683,7 +756,7 @@ namespace Ombi.Core.Engine return await MovieRepository.GetAll().AnyAsync(x => x.RequestedUserId == userId); } - public async Task ReProcessRequest(int requestId, CancellationToken cancellationToken) + public async Task ReProcessRequest(int requestId, bool is4K, CancellationToken cancellationToken) { var request = await MovieRepository.Find(requestId); if (request == null) @@ -695,10 +768,10 @@ namespace Ombi.Core.Engine }; } - return await ProcessSendingMovie(request); + return await ProcessSendingMovie(request, is4K); } - public async Task MarkUnavailable(int modelId) + public async Task MarkUnavailable(int modelId, bool is4K) { var request = await MovieRepository.Find(modelId); if (request == null) @@ -709,7 +782,14 @@ namespace Ombi.Core.Engine }; } - request.Available = false; + if (is4K) + { + request.Available4K = false; + } + else + { + request.Available = false; + } await MovieRepository.Update(request); await _mediaCacheService.Purge(); @@ -720,7 +800,7 @@ namespace Ombi.Core.Engine }; } - public async Task MarkAvailable(int modelId) + public async Task MarkAvailable(int modelId, bool is4K) { var request = await MovieRepository.Find(modelId); if (request == null) @@ -730,9 +810,16 @@ namespace Ombi.Core.Engine ErrorMessage = "Request does not exist" }; } - - request.Available = true; - request.MarkedAsAvailable = DateTime.Now; + if (!is4K) + { + request.Available = true; + request.MarkedAsAvailable = DateTime.Now; + } + else + { + request.Available4K = true; + request.MarkedAsAvailable4K = DateTime.Now; + } await NotificationHelper.Notify(request, NotificationType.RequestAvailable); await MovieRepository.Update(request); await _mediaCacheService.Purge(); @@ -744,9 +831,20 @@ namespace Ombi.Core.Engine }; } - private async Task AddMovieRequest(MovieRequests model, string movieName, string requestOnBehalf) + private async Task AddMovieRequest(MovieRequests model, string movieName, string requestOnBehalf, bool isExisting, bool is4k) { - await MovieRepository.Add(model); + if (is4k) + { + model.Has4KRequest = true; + } + if (!isExisting) + { + await MovieRepository.Add(model); + } + else + { + await MovieRepository.Update(model); + } var result = await RunSpecificRule(model, SpecificRules.CanSendNotification, requestOnBehalf); if (result.Success) diff --git a/src/Ombi.Core/Engine/MovieSearchEngine.cs b/src/Ombi.Core/Engine/MovieSearchEngine.cs index d911c1cf5..682a999eb 100644 --- a/src/Ombi.Core/Engine/MovieSearchEngine.cs +++ b/src/Ombi.Core/Engine/MovieSearchEngine.cs @@ -4,6 +4,7 @@ using Microsoft.Extensions.Logging; using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; using Ombi.Core.Authentication; +using Ombi.Core.Helpers; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; @@ -22,7 +23,7 @@ namespace Ombi.Core.Engine { public class MovieSearchEngine : BaseMediaEngine, IMovieEngine { - public MovieSearchEngine(IPrincipal identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, + public MovieSearchEngine(ICurrentUser identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, ILogger logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService s, IRepository sub) : base(identity, service, r, um, mem, s, sub) { @@ -46,7 +47,7 @@ namespace Ombi.Core.Engine { langCode = await DefaultLanguageCode(langCode); var movieInfo = await Cache.GetOrAddAsync(nameof(LookupImdbInformation) + langCode + theMovieDbId, - () => MovieApi.GetMovieInformationWithExtraInfo(theMovieDbId, langCode), + () => MovieApi.GetMovieInformationWithExtraInfo(theMovieDbId, langCode), DateTimeOffset.Now.AddHours(12)); var viewMovie = Mapper.Map(movieInfo); @@ -81,11 +82,11 @@ namespace Ombi.Core.Engine { return resultSet; } - + // Get this person movie credits var credits = await MovieApi.GetActorMovieCredits(person.id, langaugeCode); // Grab results from both cast and crew, prefer items in cast. we can handle directors like this. - var movieResults = (from role in credits.cast select new { Id = role.id, Title = role.title, ReleaseDate = role.release_date }).ToList(); + var movieResults = (from role in credits.cast select new { Id = role.id, Title = role.title, ReleaseDate = role.release_date }).ToList(); movieResults.AddRange((from job in credits.crew select new { Id = job.id, Title = job.title, ReleaseDate = job.release_date }).ToList()); movieResults = movieResults.Take(10).ToList(); @@ -120,7 +121,7 @@ namespace Ombi.Core.Engine /// public async Task> PopularMovies() { - + var result = await Cache.GetOrAddAsync(CacheKeys.PopularMovies, async () => { var langCode = await DefaultLanguageCode(null); @@ -201,7 +202,7 @@ namespace Ombi.Core.Engine protected async Task ProcessSingleMovie(SearchMovieViewModel viewMovie, bool lookupExtraInfo = false) { - if (lookupExtraInfo && viewMovie.ImdbId.IsNullOrEmpty()) + if (lookupExtraInfo && viewMovie.ImdbId.IsNullOrEmpty() && viewMovie.Id > 0) { var showInfo = await MovieApi.GetMovieInformation(viewMovie.Id); viewMovie.Id = showInfo.Id; // TheMovieDbId @@ -217,7 +218,7 @@ namespace Ombi.Core.Engine // This requires the rules to be run first to populate the RequestId property await CheckForSubscription(viewMovie); - + return viewMovie; } diff --git a/src/Ombi.Core/Engine/MusicRequestEngine.cs b/src/Ombi.Core/Engine/MusicRequestEngine.cs index b9aa183d2..640d2ade3 100644 --- a/src/Ombi.Core/Engine/MusicRequestEngine.cs +++ b/src/Ombi.Core/Engine/MusicRequestEngine.cs @@ -24,12 +24,13 @@ using Ombi.Settings.Settings.Models.External; using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; using System.ComponentModel; +using Ombi.Core.Helpers; namespace Ombi.Core.Engine { public class MusicRequestEngine : BaseMediaEngine, IMusicRequestEngine { - public MusicRequestEngine(IRequestServiceMain requestService, IPrincipal user, + public MusicRequestEngine(IRequestServiceMain requestService, ICurrentUser user, INotificationHelper helper, IRuleEvaluator r, ILogger log, OmbiUserManager manager, IRepository rl, ICacheService cache, ISettingsService ombiSettings, IRepository sub, ILidarrApi lidarr, diff --git a/src/Ombi.Core/Engine/MusicSearchEngine.cs b/src/Ombi.Core/Engine/MusicSearchEngine.cs index 89bae7069..2602bf71e 100644 --- a/src/Ombi.Core/Engine/MusicSearchEngine.cs +++ b/src/Ombi.Core/Engine/MusicSearchEngine.cs @@ -27,7 +27,7 @@ namespace Ombi.Core.Engine { public class MusicSearchEngine : BaseMediaEngine, IMusicSearchEngine { - public MusicSearchEngine(IPrincipal identity, IRequestServiceMain service, ILidarrApi lidarrApi, IMapper mapper, + public MusicSearchEngine(ICurrentUser identity, IRequestServiceMain service, ILidarrApi lidarrApi, IMapper mapper, ILogger logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService s, IRepository sub, ISettingsService lidarrSettings) : base(identity, service, r, um, mem, s, sub) diff --git a/src/Ombi.Core/Engine/RecentlyAddedEngine.cs b/src/Ombi.Core/Engine/RecentlyAddedEngine.cs index d597ec80b..25aba5547 100644 --- a/src/Ombi.Core/Engine/RecentlyAddedEngine.cs +++ b/src/Ombi.Core/Engine/RecentlyAddedEngine.cs @@ -30,26 +30,26 @@ namespace Ombi.Core.Engine public IEnumerable GetRecentlyAddedMovies(DateTime from, DateTime to) { - var plexMovies = _plex.GetAll().Where(x => x.Type == PlexMediaTypeEntity.Movie && x.AddedAt > from && x.AddedAt < to); - var embyMovies = _emby.GetAll().Where(x => x.Type == EmbyMediaType.Movie && x.AddedAt > from && x.AddedAt < to); - var jellyfinMovies = _jellyfin.GetAll().Where(x => x.Type == JellyfinMediaType.Movie && x.AddedAt > from && x.AddedAt < to); + var plexMovies = _plex.GetAll().Where(x => x.Type == MediaType.Movie && x.AddedAt > from && x.AddedAt < to); + var embyMovies = _emby.GetAll().Where(x => x.Type == MediaType.Movie && x.AddedAt > from && x.AddedAt < to); + var jellyfinMovies = _jellyfin.GetAll().Where(x => x.Type == MediaType.Movie && x.AddedAt > from && x.AddedAt < to); return GetRecentlyAddedMovies(plexMovies, embyMovies, jellyfinMovies).Take(30); } public IEnumerable GetRecentlyAddedMovies() { - var plexMovies = _plex.GetAll().Where(x => x.Type == PlexMediaTypeEntity.Movie); - var embyMovies = _emby.GetAll().Where(x => x.Type == EmbyMediaType.Movie); - var jellyfinMovies = _jellyfin.GetAll().Where(x => x.Type == JellyfinMediaType.Movie); + var plexMovies = _plex.GetAll().Where(x => x.Type == MediaType.Movie); + var embyMovies = _emby.GetAll().Where(x => x.Type == MediaType.Movie); + var jellyfinMovies = _jellyfin.GetAll().Where(x => x.Type == MediaType.Movie); return GetRecentlyAddedMovies(plexMovies, embyMovies, jellyfinMovies); } public IEnumerable GetRecentlyAddedTv(DateTime from, DateTime to, bool groupBySeason) { - var plexTv = _plex.GetAll().Include(x => x.Seasons).Include(x => x.Episodes).Where(x => x.Type == PlexMediaTypeEntity.Show && x.AddedAt > from && x.AddedAt < to); - var embyTv = _emby.GetAll().Include(x => x.Episodes).Where(x => x.Type == EmbyMediaType.Series && x.AddedAt > from && x.AddedAt < to); - var jellyfinTv = _jellyfin.GetAll().Include(x => x.Episodes).Where(x => x.Type == JellyfinMediaType.Series && x.AddedAt > from && x.AddedAt < to); + var plexTv = _plex.GetAll().Include(x => x.Seasons).Include(x => x.Episodes).Where(x => x.Type == MediaType.Series && x.AddedAt > from && x.AddedAt < to); + var embyTv = _emby.GetAll().Include(x => x.Episodes).Where(x => x.Type == MediaType.Series && x.AddedAt > from && x.AddedAt < to); + var jellyfinTv = _jellyfin.GetAll().Include(x => x.Episodes).Where(x => x.Type == MediaType.Series && x.AddedAt > from && x.AddedAt < to); return GetRecentlyAddedTv(plexTv, embyTv, jellyfinTv, groupBySeason).Take(30); } @@ -57,9 +57,9 @@ namespace Ombi.Core.Engine public IEnumerable GetRecentlyAddedTv(bool groupBySeason) { - var plexTv = _plex.GetAll().Include(x => x.Seasons).Include(x => x.Episodes).Where(x => x.Type == PlexMediaTypeEntity.Show); - var embyTv = _emby.GetAll().Include(x => x.Episodes).Where(x => x.Type == EmbyMediaType.Series); - var jellyfinTv = _jellyfin.GetAll().Include(x => x.Episodes).Where(x => x.Type == JellyfinMediaType.Series); + var plexTv = _plex.GetAll().Include(x => x.Seasons).Include(x => x.Episodes).Where(x => x.Type == MediaType.Series); + var embyTv = _emby.GetAll().Include(x => x.Episodes).Where(x => x.Type == MediaType.Series); + var jellyfinTv = _jellyfin.GetAll().Include(x => x.Episodes).Where(x => x.Type == MediaType.Series); return GetRecentlyAddedTv(plexTv, embyTv, jellyfinTv, groupBySeason); } @@ -76,7 +76,7 @@ namespace Ombi.Core.Engine { continue; } - if (p.Type == PlexMediaTypeEntity.Movie) + if (p.Type == MediaType.Movie) { recentlyAddedLog.Add(new RecentlyAddedLog { @@ -114,7 +114,7 @@ namespace Ombi.Core.Engine { continue; } - if (e.Type == EmbyMediaType.Movie) + if (e.Type == MediaType.Movie) { recentlyAddedLog.Add(new RecentlyAddedLog { @@ -152,7 +152,7 @@ namespace Ombi.Core.Engine { continue; } - if (e.Type == JellyfinMediaType.Movie) + if (e.Type == MediaType.Movie) { recentlyAddedLog.Add(new RecentlyAddedLog { diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index edfa7b392..5664d276f 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -32,7 +32,7 @@ namespace Ombi.Core.Engine { public class TvRequestEngine : BaseMediaEngine, ITvRequestEngine { - public TvRequestEngine(ITvMazeApi tvApi, IMovieDbApi movApi, IRequestServiceMain requestService, IPrincipal user, + public TvRequestEngine(ITvMazeApi tvApi, IMovieDbApi movApi, IRequestServiceMain requestService, ICurrentUser user, INotificationHelper helper, IRuleEvaluator rule, OmbiUserManager manager, ILogger logger, ITvSender sender, IRepository rl, ISettingsService settings, ICacheService cache, IRepository sub, IMediaCacheService mediaCacheService) : base(user, requestService, rule, manager, cache, settings, sub) @@ -188,7 +188,7 @@ namespace Ombi.Core.Engine (await tvBuilder .GetShowInfo(tv.TheMovieDbId, tv.languageCode)) .CreateTvList(tv) - .CreateChild(tv, canRequestOnBehalf ? tv.RequestOnBehalf : user.Id); + .CreateChild(tv, canRequestOnBehalf ? tv.RequestOnBehalf : user.Id, tv.Source); await tvBuilder.BuildEpisodes(tv); @@ -793,7 +793,7 @@ namespace Ombi.Core.Engine return await TvRepository.GetChild().AnyAsync(x => x.RequestedUserId == userId); } - public async Task MarkUnavailable(int modelId) + public async Task MarkUnavailable(int modelId, bool is4K) { var request = await TvRepository.GetChild().FirstOrDefaultAsync(x => x.Id == modelId); if (request == null) @@ -821,7 +821,7 @@ namespace Ombi.Core.Engine }; } - public async Task MarkAvailable(int modelId) + public async Task MarkAvailable(int modelId, bool is4K) { ChildRequests request = await TvRepository.GetChild().FirstOrDefaultAsync(x => x.Id == modelId); if (request == null) @@ -918,7 +918,7 @@ namespace Ombi.Core.Engine return await AfterRequest(model.ChildRequests.FirstOrDefault(), requestOnBehalf); } - public async Task ReProcessRequest(int requestId, CancellationToken cancellationToken) + public async Task ReProcessRequest(int requestId, bool is4K, CancellationToken cancellationToken) { var request = await TvRepository.GetChild().FirstOrDefaultAsync(x => x.Id == requestId, cancellationToken); if (request == null) diff --git a/src/Ombi.Core/Engine/TvSearchEngine.cs b/src/Ombi.Core/Engine/TvSearchEngine.cs index 518b97720..2747f262a 100644 --- a/src/Ombi.Core/Engine/TvSearchEngine.cs +++ b/src/Ombi.Core/Engine/TvSearchEngine.cs @@ -23,6 +23,7 @@ using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; using System.Threading; using TraktSharp.Entities; +using Ombi.Core.Helpers; namespace Ombi.Core.Engine { @@ -32,7 +33,7 @@ namespace Ombi.Core.Engine private readonly IImageService _imageService; private readonly IMovieDbApi _theMovieDbApi; - public TvSearchEngine(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, + public TvSearchEngine(ICurrentUser identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ISettingsService customizationSettings, ICacheService memCache, ISettingsService s, IRepository sub, IImageService imageService, IMovieDbApi theMovieDbApi) diff --git a/src/Ombi.Core/Engine/V2/CalendarEngine.cs b/src/Ombi.Core/Engine/V2/CalendarEngine.cs index b7ecc8ec6..8347141bb 100644 --- a/src/Ombi.Core/Engine/V2/CalendarEngine.cs +++ b/src/Ombi.Core/Engine/V2/CalendarEngine.cs @@ -5,6 +5,7 @@ using System.Security.Principal; using System.Threading.Tasks; using Ombi.Core.Authentication; using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Helpers; using Ombi.Core.Models.Search.V2; using Ombi.Core.Rule.Interfaces; using Ombi.Store.Entities; @@ -17,7 +18,7 @@ namespace Ombi.Core.Engine.V2 { public DateTime DaysAgo => DateTime.Now.AddDays(-90); public DateTime DaysAhead => DateTime.Now.AddDays(90); - public CalendarEngine(IPrincipal user, OmbiUserManager um, IRuleEvaluator rules, IMovieRequestRepository movieRepo, + public CalendarEngine(ICurrentUser user, OmbiUserManager um, IRuleEvaluator rules, IMovieRequestRepository movieRepo, ITvRequestRepository tvRequestRepo) : base(user, um, rules) { _movieRepo = movieRepo; diff --git a/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs b/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs index 1b78eaea5..7ad8c509a 100644 --- a/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs +++ b/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs @@ -4,10 +4,15 @@ using System.Threading.Tasks; using Ombi.Api.TheMovieDb.Models; using Ombi.Core.Models.Search.V2; +// Due to conflicting Genre models in +// Ombi.TheMovieDbApi.Models and Ombi.Api.TheMovieDb.Models +using Genre = Ombi.TheMovieDbApi.Models.Genre; + namespace Ombi.Core.Engine.V2 { public interface IMultiSearchEngine { Task> MultiSearch(string searchTerm, MultiSearchFilter filter, CancellationToken cancellationToken); + Task> GetGenres(string media, CancellationToken requestAborted); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/V2/IssuesEngine.cs b/src/Ombi.Core/Engine/V2/IssuesEngine.cs index 830dd4295..177ba599e 100644 --- a/src/Ombi.Core/Engine/V2/IssuesEngine.cs +++ b/src/Ombi.Core/Engine/V2/IssuesEngine.cs @@ -33,7 +33,7 @@ namespace Ombi.Core.Engine.V2 public async Task> GetIssues(int position, int take, IssueStatus status, CancellationToken token) { var issues = await _issues.GetAll().Where(x => x.Status == status && x.ProviderId != null).Skip(position).Take(take).OrderBy(x => x.Title).ToListAsync(token); - var grouped = issues.GroupBy(x => x.Title, (key, g) => new { Title = key, Issues = g }); + var grouped = issues.GroupBy(x => new { x.Title, x.ProviderId }, (key, g) => new { key = key, Issues = g }); var model = new List(); @@ -42,8 +42,8 @@ namespace Ombi.Core.Engine.V2 model.Add(new IssuesSummaryModel { Count = group.Issues.Count(), - Title = group.Title, - ProviderId = group.Issues.FirstOrDefault()?.ProviderId + Title = group.key.Title, + ProviderId = group.key.ProviderId }); } diff --git a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs index 7c69e4d5d..3acd7d1f0 100644 --- a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs @@ -5,6 +5,7 @@ using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; using Ombi.Core.Authentication; using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Helpers; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; using Ombi.Core.Models.Search.V2; @@ -28,7 +29,7 @@ namespace Ombi.Core.Engine.V2 { public class MovieSearchEngineV2 : BaseMediaEngine, IMovieEngineV2 { - public MovieSearchEngineV2(IPrincipal identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, + public MovieSearchEngineV2(ICurrentUser identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, ILogger logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService s, IRepository sub, ISettingsService customizationSettings, IMovieRequestEngine movieRequestEngine, IHttpClientFactory httpClientFactory) : base(identity, service, r, um, mem, s, sub) @@ -398,6 +399,8 @@ namespace Ombi.Core.Engine.V2 mapped.Available = viewMovie.Available; mapped.Approved = viewMovie.Approved; + mapped.Denied = viewMovie.Denied; + mapped.DeniedReason = viewMovie.DeniedReason; mapped.RequestId = viewMovie.RequestId; mapped.Requested = viewMovie.Requested; mapped.PlexUrl = viewMovie.PlexUrl; @@ -406,6 +409,13 @@ namespace Ombi.Core.Engine.V2 mapped.Subscribed = viewMovie.Subscribed; mapped.ShowSubscribe = viewMovie.ShowSubscribe; mapped.DigitalReleaseDate = viewMovie.DigitalReleaseDate; + mapped.RequestedDate4k = viewMovie.RequestedDate4k; + mapped.Approved4K = viewMovie.Approved4K; + mapped.Available4K = viewMovie.Available4K; + mapped.Denied4K = viewMovie.Denied4K; + mapped.DeniedReason4K = viewMovie.DeniedReason4K; + mapped.Has4KRequest = viewMovie.Has4KRequest; + return mapped; } diff --git a/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs b/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs index fc2595676..362a79e43 100644 --- a/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs +++ b/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs @@ -7,6 +7,7 @@ using Ombi.Api.MusicBrainz; using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; using Ombi.Core.Authentication; +using Ombi.Core.Helpers; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search.V2; using Ombi.Core.Rule.Interfaces; @@ -17,11 +18,15 @@ using Ombi.Settings.Settings.Models.External; using Ombi.Store.Entities; using Ombi.Store.Repository; +// Due to conflicting Genre models in +// Ombi.TheMovieDbApi.Models and Ombi.Api.TheMovieDb.Models +using Genre = Ombi.TheMovieDbApi.Models.Genre; + namespace Ombi.Core.Engine.V2 { public class MultiSearchEngine : BaseMediaEngine, IMultiSearchEngine { - public MultiSearchEngine(IPrincipal identity, IRequestServiceMain requestService, IRuleEvaluator rules, + public MultiSearchEngine(ICurrentUser identity, IRequestServiceMain requestService, IRuleEvaluator rules, OmbiUserManager um, ICacheService cache, ISettingsService ombiSettings, IRepository sub, IMovieDbApi movieDbApi, ISettingsService lidarrSettings, IMusicBrainzApi musicApi) : base(identity, requestService, rules, um, cache, ombiSettings, sub) @@ -113,5 +118,11 @@ namespace Ombi.Core.Engine.V2 return model; } + + public async Task> GetGenres(string media, CancellationToken cancellationToken) + { + var lang = await DefaultLanguageCode(null); + return await _movieDbApi.GetGenres(media, cancellationToken, lang); + } } } diff --git a/src/Ombi.Core/Engine/V2/MusicSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/MusicSearchEngineV2.cs index b7d9575db..fc3fcf40e 100644 --- a/src/Ombi.Core/Engine/V2/MusicSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/MusicSearchEngineV2.cs @@ -11,6 +11,7 @@ using Ombi.Api.Lidarr.Models; using Ombi.Api.MusicBrainz; using Ombi.Core.Authentication; using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Helpers; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search.V2.Music; using Ombi.Core.Rule.Interfaces; @@ -31,7 +32,7 @@ namespace Ombi.Core.Engine.V2 private readonly ISettingsService _lidarrSettings; private readonly ILidarrApi _lidarrApi; - public MusicSearchEngineV2(IPrincipal identity, IRequestServiceMain requestService, IRuleEvaluator rules, + public MusicSearchEngineV2(ICurrentUser identity, IRequestServiceMain requestService, IRuleEvaluator rules, OmbiUserManager um, ICacheService cache, ISettingsService ombiSettings, IRepository sub, IMusicBrainzApi musicBrainzApi, ISettingsService lidarrSettings, ILidarrApi lidarrApi) diff --git a/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs index 07f8ce981..344ced813 100644 --- a/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs @@ -25,6 +25,7 @@ using Ombi.Api.TheMovieDb.Models; using System.Diagnostics; using Ombi.Core.Engine.Interfaces; using Ombi.Core.Models.UI; +using Ombi.Core.Helpers; namespace Ombi.Core.Engine.V2 { @@ -37,7 +38,7 @@ namespace Ombi.Core.Engine.V2 private readonly ISettingsService _customization; private readonly ITvRequestEngine _requestEngine; - public TvSearchEngineV2(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, + public TvSearchEngineV2(ICurrentUser identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ICacheService memCache, ISettingsService s, IRepository sub, IMovieDbApi movieApi, ISettingsService customization, ITvRequestEngine requestEngine) : base(identity, service, r, um, memCache, s, sub) @@ -307,6 +308,8 @@ namespace Ombi.Core.Engine.V2 item.PartlyAvailable = oldModel.PartlyAvailable; item.Requested = oldModel.Requested; item.Available = oldModel.Available; + item.Denied = oldModel.Denied; + item.DeniedReason = oldModel.DeniedReason; item.Approved = oldModel.Approved; item.SeasonRequests = oldModel.SeasonRequests; item.RequestId = oldModel.RequestId; diff --git a/src/Ombi.Core/Engine/VoteEngine.cs b/src/Ombi.Core/Engine/VoteEngine.cs index 5c73e03d9..3e7f6f542 100644 --- a/src/Ombi.Core/Engine/VoteEngine.cs +++ b/src/Ombi.Core/Engine/VoteEngine.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Ombi.Core.Authentication; using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Helpers; using Ombi.Core.Models; using Ombi.Core.Models.UI; using Ombi.Core.Rule.Interfaces; @@ -20,7 +21,7 @@ namespace Ombi.Core.Engine { public class VoteEngine : BaseEngine, IVoteEngine { - public VoteEngine(IRepository votes, IPrincipal user, OmbiUserManager um, IRuleEvaluator r, ISettingsService voteSettings, + public VoteEngine(IRepository votes, ICurrentUser user, OmbiUserManager um, IRuleEvaluator r, ISettingsService voteSettings, IMusicRequestEngine musicRequestEngine, ITvRequestEngine tvRequestEngine, IMovieRequestEngine movieRequestEngine) : base(user, um, r) { _voteRepository = votes; @@ -193,7 +194,7 @@ namespace Ombi.Core.Engine case RequestType.Movie: if (totalVotes >= voteSettings.MovieVoteMax) { - result = await _movieRequestEngine.ApproveMovieById(requestId); + result = await _movieRequestEngine.ApproveMovieById(requestId, false); } break; case RequestType.Album: diff --git a/src/Ombi.Core/Helpers/CurrentUser.cs b/src/Ombi.Core/Helpers/CurrentUser.cs new file mode 100644 index 000000000..974d59cd6 --- /dev/null +++ b/src/Ombi.Core/Helpers/CurrentUser.cs @@ -0,0 +1,47 @@ +using Microsoft.EntityFrameworkCore; +using Ombi.Core.Authentication; +using Ombi.Helpers; +using Ombi.Store.Entities; +using System.Security.Principal; +using System.Threading.Tasks; + +namespace Ombi.Core.Helpers +{ + public class CurrentUser : ICurrentUser + { + private readonly IPrincipal _principle; + private readonly OmbiUserManager _userManager; + private OmbiUser _user; + public IIdentity Identity { get; set; } + + public CurrentUser(IPrincipal principle, OmbiUserManager userManager) + { + _principle = principle; + _userManager = userManager; + Identity = _principle?.Identity ?? null; + } + + public void SetUser(OmbiUser user) + { + _user = user; + } + + public string Username => Identity?.Name ?? _user?.UserName; + public async Task GetUser() + { + if (!Username.HasValue() && _user == null) + { + return null; + } + + if (_user != null) + { + return _user; + } + + var username = Username.ToUpper(); + return _user ??= await _userManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); + } + + } +} diff --git a/src/Ombi.Core/Helpers/ICurrentUser.cs b/src/Ombi.Core/Helpers/ICurrentUser.cs new file mode 100644 index 000000000..1cce973f3 --- /dev/null +++ b/src/Ombi.Core/Helpers/ICurrentUser.cs @@ -0,0 +1,15 @@ +using Ombi.Store.Entities; +using System.Security.Principal; +using System.Threading.Tasks; + +namespace Ombi.Core.Helpers +{ + public interface ICurrentUser + { + string Username { get; } + + Task GetUser(); + void SetUser(OmbiUser user); + IIdentity Identity { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Core/Helpers/TvShowRequestBuilderV2.cs b/src/Ombi.Core/Helpers/TvShowRequestBuilderV2.cs index 6843332c0..4053109da 100644 --- a/src/Ombi.Core/Helpers/TvShowRequestBuilderV2.cs +++ b/src/Ombi.Core/Helpers/TvShowRequestBuilderV2.cs @@ -53,7 +53,7 @@ namespace Ombi.Core.Helpers return this; } - public TvShowRequestBuilderV2 CreateChild(TvRequestViewModelV2 model, string userId) + public TvShowRequestBuilderV2 CreateChild(TvRequestViewModelV2 model, string userId, RequestSource source) { var animationGenre = TheMovieDbRecord.genres?.Any(s => s.name.Equals("Animation", StringComparison.InvariantCultureIgnoreCase)) ?? false; var animeKeyword = TheMovieDbRecord.Keywords?.KeywordsValue?.Any(s => s.Name.Equals("Anime", StringComparison.InvariantCultureIgnoreCase)) ?? false; @@ -68,7 +68,8 @@ namespace Ombi.Core.Helpers Title = TheMovieDbRecord.name, ReleaseYear = FirstAir, RequestedByAlias = model.RequestedByAlias, - SeriesType = animationGenre && animeKeyword ? SeriesType.Anime : SeriesType.Standard + SeriesType = animationGenre && animeKeyword ? SeriesType.Anime : SeriesType.Standard, + Source = source }; return this; diff --git a/src/Ombi.Core/Models/Requests/MovieRequestViewModel.cs b/src/Ombi.Core/Models/Requests/MovieRequestViewModel.cs index 05eec3e3f..18125ed71 100644 --- a/src/Ombi.Core/Models/Requests/MovieRequestViewModel.cs +++ b/src/Ombi.Core/Models/Requests/MovieRequestViewModel.cs @@ -1,31 +1,5 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2018 Jamie Rees -// File: MovieRequestViewModel.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion - -using Newtonsoft.Json; +using Newtonsoft.Json; +using Ombi.Store.Entities.Requests; namespace Ombi.Core.Models.Requests { @@ -34,10 +8,18 @@ namespace Ombi.Core.Models.Requests public int TheMovieDbId { get; set; } public string LanguageCode { get; set; } = "en"; + public bool Is4kRequest { get; set; } + /// /// This is only set from a HTTP Header /// [JsonIgnore] public string RequestedByAlias { get; set; } + + /// + /// Only set via list imports + /// + [JsonIgnore] + public RequestSource Source { get; set; } = RequestSource.Ombi; } } \ No newline at end of file diff --git a/src/Ombi.Core/Models/Requests/TvRequestViewModelV2.cs b/src/Ombi.Core/Models/Requests/TvRequestViewModelV2.cs index a9742fb32..e1df9553f 100644 --- a/src/Ombi.Core/Models/Requests/TvRequestViewModelV2.cs +++ b/src/Ombi.Core/Models/Requests/TvRequestViewModelV2.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Newtonsoft.Json; +using Ombi.Store.Entities.Requests; namespace Ombi.Core.Models.Requests { @@ -7,5 +8,6 @@ namespace Ombi.Core.Models.Requests { public int TheMovieDbId { get; set; } public string languageCode { get; set; } = "en"; + public RequestSource Source { get; set; } = RequestSource.Ombi; } } \ No newline at end of file diff --git a/src/Ombi.Core/Models/Search/SearchMovieViewModel.cs b/src/Ombi.Core/Models/Search/SearchMovieViewModel.cs index 4d0d05a49..10cc76404 100644 --- a/src/Ombi.Core/Models/Search/SearchMovieViewModel.cs +++ b/src/Ombi.Core/Models/Search/SearchMovieViewModel.cs @@ -28,5 +28,14 @@ namespace Ombi.Core.Models.Search public override RequestType Type => RequestType.Movie; public ReleaseDatesDto ReleaseDates { get; set; } public DateTime? DigitalReleaseDate { get; set; } + public bool Has4KRequest { get; set; } + public bool Approved4K { get; set; } + public DateTime MarkedAsApproved4K { get; set; } + public DateTime RequestedDate4k { get; set; } + public bool Available4K { get; set; } + public DateTime? MarkedAsAvailable4K { get; set; } + public bool? Denied4K { get; set; } + public DateTime MarkedAsDenied4K { get; set; } + public string DeniedReason4K { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Core/Models/Search/SearchViewModel.cs b/src/Ombi.Core/Models/Search/SearchViewModel.cs index 4cf812982..e1a2f2850 100644 --- a/src/Ombi.Core/Models/Search/SearchViewModel.cs +++ b/src/Ombi.Core/Models/Search/SearchViewModel.cs @@ -1,4 +1,5 @@ -using System.ComponentModel.DataAnnotations.Schema; +using System; +using System.ComponentModel.DataAnnotations.Schema; using Ombi.Store.Entities; namespace Ombi.Core.Models.Search @@ -32,6 +33,7 @@ namespace Ombi.Core.Models.Search public string TheMovieDbId { get; set; } [NotMapped] + [Obsolete("Use request service instead")] public bool Subscribed { get; set; } [NotMapped] public bool ShowSubscribe { get; set; } diff --git a/src/Ombi.Core/Models/Search/V2/MovieFullInfoViewModel.cs b/src/Ombi.Core/Models/Search/V2/MovieFullInfoViewModel.cs index 8e8dac9b1..847780e57 100644 --- a/src/Ombi.Core/Models/Search/V2/MovieFullInfoViewModel.cs +++ b/src/Ombi.Core/Models/Search/V2/MovieFullInfoViewModel.cs @@ -41,6 +41,15 @@ namespace Ombi.Core.Models.Search.V2 public Recommendations Recommendations { get; set; } public ExternalIds ExternalIds { get; set; } public Keywords Keywords { get; set; } + public bool Has4KRequest { get; set; } + public bool Approved4K { get; set; } + public DateTime MarkedAsApproved4K { get; set; } + public DateTime RequestedDate4k { get; set; } + public bool Available4K { get; set; } + public DateTime? MarkedAsAvailable4K { get; set; } + public bool? Denied4K { get; set; } + public DateTime MarkedAsDenied4K { get; set; } + public string DeniedReason4K { get; set; } } public class Keywords { diff --git a/src/Ombi.Core/Ombi.Core.csproj b/src/Ombi.Core/Ombi.Core.csproj index 359792e0d..67ecdbe13 100644 --- a/src/Ombi.Core/Ombi.Core.csproj +++ b/src/Ombi.Core/Ombi.Core.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild @@ -36,6 +36,7 @@ + diff --git a/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs b/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs index f427434f0..23d26625b 100644 --- a/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs @@ -3,9 +3,12 @@ using System.Security.Principal; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Ombi.Core.Authentication; +using Ombi.Core.Helpers; using Ombi.Core.Models.Requests; using Ombi.Core.Rule.Interfaces; +using Ombi.Core.Services; using Ombi.Helpers; +using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; @@ -13,32 +16,58 @@ namespace Ombi.Core.Rule.Rules.Request { public class AutoApproveRule : BaseRequestRule, IRules { - public AutoApproveRule(IPrincipal principal, OmbiUserManager um) + public AutoApproveRule(ICurrentUser principal, OmbiUserManager um, IFeatureService featureService) { User = principal; _manager = um; + _featureService = featureService; } - private IPrincipal User { get; } + private ICurrentUser User { get; } private readonly OmbiUserManager _manager; + private readonly IFeatureService _featureService; public async Task Execute(BaseRequest obj) { - var username = User.Identity.Name.ToUpper(); + var currentUser = await User.GetUser(); + var username = currentUser.UserName.ToUpper(); var user = await _manager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); if (await _manager.IsInRoleAsync(user, OmbiRoles.Admin) || user.IsSystemUser) { - obj.Approved = true; + if (obj is MovieRequests movie) + { + await Check4K(movie); + } + else + { + obj.Approved = true; + } return Success(); } if (obj.RequestType == RequestType.Movie && await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveMovie)) - obj.Approved = true; + { + var movie = (MovieRequests)obj; + await Check4K(movie); + } if (obj.RequestType == RequestType.TvShow && await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveTv)) obj.Approved = true; if (obj.RequestType == RequestType.Album && await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveMusic)) obj.Approved = true; return Success(); // We don't really care, we just don't set the obj to approve } + + private async Task Check4K(MovieRequests movie) + { + var featureEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests); + if (movie.Is4kRequest && featureEnabled) + { + movie.Approved4K = true; + } + else + { + movie.Approved = true; + } + } } } \ No newline at end of file diff --git a/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs b/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs index 1c720a385..e2e81e612 100644 --- a/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs @@ -10,31 +10,48 @@ using Ombi.Core.Engine; using Ombi.Core.Rule.Interfaces; using Ombi.Helpers; using Ombi.Store.Entities.Requests; +using Ombi.Core.Helpers; namespace Ombi.Core.Rule.Rules.Request { public class CanRequestRule : BaseRequestRule, IRules { - public CanRequestRule(IPrincipal principal, OmbiUserManager manager) + public CanRequestRule(ICurrentUser principal, OmbiUserManager manager) { User = principal; _manager = manager; } - private IPrincipal User { get; } + private ICurrentUser User { get; } private readonly OmbiUserManager _manager; public async Task Execute(BaseRequest obj) { - var username = User.Identity.Name.ToUpper(); + var currentUser = await User.GetUser(); + var username = currentUser.UserName.ToUpper(); var user = await _manager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); if (await _manager.IsInRoleAsync(user, OmbiRoles.Admin) || user.IsSystemUser) return Success(); if (obj.RequestType == RequestType.Movie) { - if (await _manager.IsInRoleAsync(user, OmbiRoles.RequestMovie) || await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveMovie)) - return Success(); + var movie = (MovieRequests)obj; + var hasAutoApprove = await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveMovie); + if (await _manager.IsInRoleAsync(user, OmbiRoles.RequestMovie) || hasAutoApprove) + { + if (movie.Is4kRequest && !hasAutoApprove) + { + var has4kPermission = await _manager.IsInRoleAsync(user, OmbiRoles.Request4KMovie); + if (has4kPermission) + { + return Success(); + } + } + else + { + return Success(); + } + } return Fail(ErrorCode.NoPermissionsRequestMovie, "You do not have permissions to Request a Movie"); } diff --git a/src/Ombi.Core/Rule/Rules/Request/ExistingMovieRequestRule.cs b/src/Ombi.Core/Rule/Rules/Request/ExistingMovieRequestRule.cs index c837c42d1..17533a570 100644 --- a/src/Ombi.Core/Rule/Rules/Request/ExistingMovieRequestRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/ExistingMovieRequestRule.cs @@ -1,21 +1,24 @@ -using System; -using System.Threading.Tasks; +using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Ombi.Core.Rule.Interfaces; using Ombi.Helpers; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; -using Ombi.Store.Repository; using Ombi.Core.Engine; using Ombi.Store.Repository.Requests; +using Ombi.Core.Services; +using Ombi.Settings.Settings.Models; namespace Ombi.Core.Rule.Rules.Request { public class ExistingMovieRequestRule : BaseRequestRule, IRules { - public ExistingMovieRequestRule(IMovieRequestRepository movie) + private readonly IFeatureService _featureService; + + public ExistingMovieRequestRule(IMovieRequestRepository movie, IFeatureService featureService) { Movie = movie; + _featureService = featureService; } private IMovieRequestRepository Movie { get; } @@ -35,7 +38,7 @@ namespace Ombi.Core.Rule.Rules.Request var existing = await movieRequests.FirstOrDefaultAsync(x => x.TheMovieDbId == movie.TheMovieDbId); if (existing != null) // Do we already have a request for this? { - found = true; + found = await Check4KRequests(movie, existing); } if (!found && movie.ImdbId.HasValue()) @@ -45,15 +48,30 @@ namespace Ombi.Core.Rule.Rules.Request x.ImdbId == movie.ImdbId); if (existing != null) { - found = true; + found = await Check4KRequests(movie, existing); } } - if(found) + if (found) { return Fail(ErrorCode.AlreadyRequested, $"\"{obj.Title}\" has already been requested"); } } return Success(); } + + private async Task Check4KRequests(MovieRequests movie, MovieRequests existing) + { + var featureEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests); + if (movie.Is4kRequest && existing.Has4KRequest && featureEnabled) + { + return true; + } + if (!movie.Is4kRequest && !existing.Has4KRequest || !featureEnabled) + { + return true; + } + + return false; + } } } \ No newline at end of file diff --git a/src/Ombi.Core/Rule/Rules/Request/ExistingPlexRequestRule.cs b/src/Ombi.Core/Rule/Rules/Request/ExistingPlexRequestRule.cs index ef38fb973..4f32c2eb8 100644 --- a/src/Ombi.Core/Rule/Rules/Request/ExistingPlexRequestRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/ExistingPlexRequestRule.cs @@ -32,7 +32,7 @@ namespace Ombi.Core.Rule.Rules.Request { var tvRequest = (ChildRequests) obj; - var tvContent = _plexContent.GetAll().Include(x => x.Episodes).Where(x => x.Type == PlexMediaTypeEntity.Show); + var tvContent = _plexContent.GetAll().Include(x => x.Episodes).Where(x => x.Type == MediaType.Series); // We need to do a check on the TVDBId var anyMovieDbMatches = await tvContent.FirstOrDefaultAsync(x => x.TheMovieDbId.Length > 0 && x.TheMovieDbId == tvRequest.Id.ToString()); if (anyMovieDbMatches == null) @@ -54,6 +54,15 @@ namespace Ombi.Core.Rule.Rules.Request // looks like we have a match on the TVDbID return CheckExistingContent(tvRequest, anyMovieDbMatches); } + if (obj.RequestType == RequestType.Movie) + { + var movie = (MovieRequests)obj; + var exists = _plexContent.GetAll().Where(x => x.Type == MediaType.Movie).Any(x => x.TheMovieDbId == movie.Id.ToString() || x.TheMovieDbId == movie.TheMovieDbId.ToString()); + if (exists) + { + return Fail(ErrorCode.AlreadyRequested, "This movie is already available." ); + } + } return Success(); } diff --git a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs index fe062e851..630e4ac81 100644 --- a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs +++ b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs @@ -46,10 +46,10 @@ namespace Ombi.Core.Rule.Rules.Search } } - public static async Task SingleEpisodeCheck(bool useImdb, IQueryable allEpisodes, EpisodeRequests episode, - SeasonRequests season, PlexServerContent item, bool useTheMovieDb, bool useTvDb, ILogger log) + public static async Task SingleEpisodeCheck(bool useImdb, IQueryable allEpisodes, EpisodeRequests episode, + SeasonRequests season, IMediaServerContent item, bool useTheMovieDb, bool useTvDb, ILogger log) { - PlexEpisode epExists = null; + IMediaServerEpisode epExists = null; try { @@ -79,66 +79,6 @@ namespace Ombi.Core.Rule.Rules.Search log.LogError(e, "Exception thrown when attempting to check if something is available"); } - if (epExists != null) - { - episode.Available = true; - } - } - public static async Task SingleEpisodeCheck(bool useImdb, IQueryable allEpisodes, EpisodeRequests episode, - SeasonRequests season, EmbyContent item, bool useTheMovieDb, bool useTvDb) - { - EmbyEpisode epExists = null; - if (useImdb) - { - epExists = await allEpisodes.FirstOrDefaultAsync(x => - x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.ImdbId == item.ImdbId); - } - - if (useTheMovieDb) - { - epExists = await allEpisodes.FirstOrDefaultAsync(x => - x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.TheMovieDbId == item.TheMovieDbId); - } - - if (useTvDb) - { - epExists = await allEpisodes.FirstOrDefaultAsync(x => - x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.TvDbId == item.TvDbId); - } - - if (epExists != null) - { - episode.Available = true; - } - } - public static async Task SingleEpisodeCheck(bool useImdb, IQueryable allEpisodes, EpisodeRequests episode, - SeasonRequests season, JellyfinContent item, bool useTheMovieDb, bool useTvDb) - { - JellyfinEpisode epExists = null; - if (useImdb) - { - epExists = await allEpisodes.FirstOrDefaultAsync(x => - x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.ImdbId == item.ImdbId); - } - - if (useTheMovieDb) - { - epExists = await allEpisodes.FirstOrDefaultAsync(x => - x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.TheMovieDbId == item.TheMovieDbId); - } - - if (useTvDb) - { - epExists = await allEpisodes.FirstOrDefaultAsync(x => - x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.TvDbId == item.TvDbId); - } - if (epExists != null) { episode.Available = true; diff --git a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs index 7f6718a6b..d28f50cc0 100644 --- a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs @@ -1,11 +1,12 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; -using Ombi.Core.Settings; -using Ombi.Core.Settings.Models.External; +using Ombi.Core.Services; using Ombi.Helpers; +using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; using Ombi.Store.Repository; @@ -13,14 +14,17 @@ namespace Ombi.Core.Rule.Rules.Search { public class EmbyAvailabilityRule : BaseSearchRule, IRules { - public EmbyAvailabilityRule(IEmbyContentRepository repo, ISettingsService s) + private readonly IFeatureService _featureService; + + public EmbyAvailabilityRule(IEmbyContentRepository repo, ILogger log, IFeatureService featureService) { EmbyContentRepository = repo; - EmbySettings = s; + Log = log; + _featureService = featureService; } private IEmbyContentRepository EmbyContentRepository { get; } - private ISettingsService EmbySettings { get; } + private ILogger Log { get; } public async Task Execute(SearchViewModel obj) { @@ -60,22 +64,36 @@ namespace Ombi.Core.Rule.Rules.Search } } } - + if (item != null) { - obj.Available = true; - var s = await EmbySettings.GetSettingsAsync(); - if (s.Enable) + if (obj is SearchMovieViewModel movie) { - var server = s.Servers.FirstOrDefault(); - if ((server?.ServerHostname ?? string.Empty).HasValue()) + var is4kEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests); + + if (item.Has4K && is4kEnabled) { - obj.EmbyUrl = EmbyHelper.GetEmbyMediaUrl(item.EmbyId, server?.ServerId, server?.ServerHostname); + movie.Available4K = true; + obj.EmbyUrl = item.Url; } else { - obj.EmbyUrl = EmbyHelper.GetEmbyMediaUrl(item.EmbyId, server?.ServerId, null); + obj.Available = true; + obj.EmbyUrl = item.Url; + obj.Quality = item.Quality; } + + if (item.Quality.HasValue()) + { + obj.Available = true; + obj.EmbyUrl = item.Url; + obj.Quality = item.Quality; + } + } + else + { + obj.Available = true; + obj.EmbyUrl = item.Url; } if (obj.Type == RequestType.TvShow) @@ -89,7 +107,7 @@ namespace Ombi.Core.Rule.Rules.Search { foreach (var episode in season.Episodes) { - await AvailabilityRuleHelper.SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb); + await AvailabilityRuleHelper.SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb, Log); } } } diff --git a/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs b/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs index 58c2508a6..9c98b7708 100644 --- a/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs @@ -26,17 +26,27 @@ namespace Ombi.Core.Rule.Rules.Search public async Task Execute(SearchViewModel obj) { - if (obj.Type == RequestType.Movie) + if (obj is SearchMovieViewModel movie) { var movieRequests = await Movie.GetRequestAsync(obj.Id); if (movieRequests != null) // Do we already have a request for this? { - obj.Requested = true; - obj.RequestId = movieRequests.Id; - obj.Approved = movieRequests.Approved; - obj.Denied = movieRequests.Denied ?? false; - obj.DeniedReason = movieRequests.DeniedReason; - obj.Available = movieRequests.Available; + // If the RequestDate is a min value, that means there's only a 4k request + movie.Requested = movieRequests.RequestedDate != DateTime.MinValue; + movie.RequestId = movieRequests.Id; + movie.Approved = movieRequests.Approved; + movie.Denied = movieRequests.Denied ?? false; + movie.DeniedReason = movieRequests.DeniedReason; + movie.Available = movieRequests.Available; + movie.Has4KRequest = movieRequests.Has4KRequest; + movie.RequestedDate4k = movieRequests.RequestedDate4k; + movie.Approved4K = movieRequests.Approved4K; + movie.Available4K = movieRequests.Available4K; + movie.Denied4K = movieRequests.Denied4K; + movie.DeniedReason4K = movieRequests.DeniedReason4K; + movie.MarkedAsApproved4K = movieRequests.MarkedAsApproved4K; + movie.MarkedAsAvailable4K = movieRequests.MarkedAsAvailable4K; + movie.MarkedAsDenied4K = movieRequests.MarkedAsDenied4K; return Success(); } @@ -51,7 +61,6 @@ namespace Ombi.Core.Rule.Rules.Search request.RequestId = tvRequests.Id; request.Requested = true; request.Approved = tvRequests.ChildRequests.Any(x => x.Approved); - request.Denied = tvRequests.ChildRequests.Any(x => x.Denied ?? false); // Let's modify the seasonsrequested to reflect what we have requested... foreach (var season in request.SeasonRequests) @@ -75,7 +84,8 @@ namespace Ombi.Core.Rule.Rules.Search episodeSearching.Requested = true; episodeSearching.Available = ep.Available; episodeSearching.Approved = ep.Season.ChildRequest.Approved; - episodeSearching.Denied = request.Denied; + episodeSearching.Denied = ep.Season.ChildRequest.Denied; + episodeSearching.DeniedReason = ep.Season.ChildRequest.DeniedReason; } } } @@ -90,6 +100,12 @@ namespace Ombi.Core.Rule.Rules.Search request.PartlyAvailable = true; } + if (request.SeasonRequests.Any() && request.SeasonRequests.All(x => x.Episodes.All(e => e.Denied ?? false))) + { + request.Denied = true; + request.DeniedReason = tvRequests.ChildRequests.FirstOrDefault(x => x.Denied ?? false)?.DeniedReason; + } + var hasUnairedRequests = request.SeasonRequests.Any() && request.SeasonRequests.All(x => x.Episodes.Any(e => e.AirDate >= DateTime.UtcNow)); if (request.FullyAvailable) @@ -107,7 +123,7 @@ namespace Ombi.Core.Rule.Rules.Search if (albumRequest != null) // Do we already have a request for this? { obj.Requested = true; - obj.RequestId = albumRequest.Id; + obj.RequestId = albumRequest.Id; obj.Denied = albumRequest.Denied; obj.DeniedReason = albumRequest.DeniedReason; obj.Approved = albumRequest.Approved; diff --git a/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs index c51645112..514731740 100644 --- a/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs @@ -1,11 +1,12 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; -using Ombi.Core.Settings; -using Ombi.Core.Settings.Models.External; +using Ombi.Core.Services; using Ombi.Helpers; +using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; using Ombi.Store.Repository; @@ -13,14 +14,17 @@ namespace Ombi.Core.Rule.Rules.Search { public class JellyfinAvailabilityRule : BaseSearchRule, IRules { - public JellyfinAvailabilityRule(IJellyfinContentRepository repo, ISettingsService s) + private readonly IFeatureService _featureService; + + public JellyfinAvailabilityRule(IJellyfinContentRepository repo, ILogger log, IFeatureService featureService) { JellyfinContentRepository = repo; - JellyfinSettings = s; + Log = log; + _featureService = featureService; } private IJellyfinContentRepository JellyfinContentRepository { get; } - private ISettingsService JellyfinSettings { get; } + private ILogger Log { get; } public async Task Execute(SearchViewModel obj) { @@ -77,20 +81,32 @@ namespace Ombi.Core.Rule.Rules.Search obj.TheMovieDbId = obj.Id.ToString(); useTheMovieDb = true; } - obj.Available = true; - var s = await JellyfinSettings.GetSettingsAsync(); - if (s.Enable) + if (obj is SearchMovieViewModel movie) { - var server = s.Servers.FirstOrDefault(x => x.ServerHostname != null); - if ((server?.ServerHostname ?? string.Empty).HasValue()) + var is4kEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests); + if (item.Has4K && is4kEnabled) { - obj.JellyfinUrl = JellyfinHelper.GetJellyfinMediaUrl(item.JellyfinId, server?.ServerId, server?.ServerHostname); - } + movie.Available4K = true; + obj.JellyfinUrl = item.Url; + } else { - var firstServer = s.Servers?.FirstOrDefault(); - obj.JellyfinUrl = JellyfinHelper.GetJellyfinMediaUrl(item.JellyfinId, firstServer.ServerId, firstServer.FullUri); + obj.Available = true; + obj.JellyfinUrl = item.Url; + obj.Quality = item.Quality; } + + if (item.Quality.HasValue()) + { + obj.Available = true; + obj.JellyfinUrl = item.Url; + obj.Quality = item.Quality; + } + } + else + { + obj.Available = true; + obj.JellyfinUrl = item.Url; } if (obj.Type == RequestType.TvShow) @@ -104,7 +120,7 @@ namespace Ombi.Core.Rule.Rules.Search { foreach (var episode in season.Episodes) { - await AvailabilityRuleHelper.SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb); + await AvailabilityRuleHelper.SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb, Log); } } } diff --git a/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs index 42e97f5f7..ab5b3a6c6 100644 --- a/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs @@ -3,9 +3,11 @@ using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; +using Ombi.Core.Services; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Helpers; +using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; using Ombi.Store.Repository; @@ -14,12 +16,15 @@ namespace Ombi.Core.Rule.Rules.Search public class PlexAvailabilityRule : BaseSearchRule, IRules { private readonly ISettingsService _plexSettings; + private readonly IFeatureService _featureService; - public PlexAvailabilityRule(IPlexContentRepository repo, ILogger log, ISettingsService plexSettings) + public PlexAvailabilityRule(IPlexContentRepository repo, ILogger log, ISettingsService plexSettings, + IFeatureService featureService) { PlexContentRepository = repo; Log = log; _plexSettings = plexSettings; + _featureService = featureService; } private IPlexContentRepository PlexContentRepository { get; } @@ -33,7 +38,7 @@ namespace Ombi.Core.Rule.Rules.Search var useId = false; var useTvDb = false; - PlexMediaTypeEntity type = ConvertType(obj.Type); + MediaType type = ConvertType(obj.Type); if (obj.ImdbId.HasValue()) { @@ -89,13 +94,44 @@ namespace Ombi.Core.Rule.Rules.Search obj.TheMovieDbId = obj.Id.ToString(); useTheMovieDb = true; } - obj.Available = true; - obj.PlexUrl = PlexHelper.BuildPlexMediaUrl(item.Url, host); - obj.Quality = item.Quality; - - if (obj.Type == RequestType.TvShow) + + if (obj is SearchMovieViewModel movie) + { + var is4kEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests); + + if (item.Has4K && is4kEnabled) + { + movie.Available4K = true; + } + else + { + obj.Available = true; + obj.Quality = item.Quality; + } + + if (item.Quality.HasValue()) + { + obj.Available = true; + obj.Quality = item.Quality; + } + } + else + { + obj.Available = true; + } + + if (item.Url.StartsWith("http")) + { + obj.PlexUrl = item.Url; + } + else + { + // legacy content + obj.PlexUrl = PlexHelper.BuildPlexMediaUrl(item.Url, host); + } + + if (obj is SearchTvShowViewModel search) { - var search = (SearchTvShowViewModel)obj; // Let's go through the episodes now if (search.SeasonRequests.Any()) { @@ -115,12 +151,12 @@ namespace Ombi.Core.Rule.Rules.Search return Success(); } - private PlexMediaTypeEntity ConvertType(RequestType type) => + private MediaType ConvertType(RequestType type) => type switch { - RequestType.Movie => PlexMediaTypeEntity.Movie, - RequestType.TvShow => PlexMediaTypeEntity.Show, - _ => PlexMediaTypeEntity.Movie, + RequestType.Movie => MediaType.Movie, + RequestType.TvShow => MediaType.Series, + _ => MediaType.Movie, }; } } \ No newline at end of file diff --git a/src/Ombi.Core/Rule/Rules/Search/RadarrCacheRule.cs b/src/Ombi.Core/Rule/Rules/Search/RadarrCacheRule.cs index 105681c82..63546f8c8 100644 --- a/src/Ombi.Core/Rule/Rules/Search/RadarrCacheRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/RadarrCacheRule.cs @@ -18,16 +18,23 @@ namespace Ombi.Core.Rule.Rules.Search public Task Execute(SearchViewModel obj) { - if (obj.Type == RequestType.Movie) + if (obj is SearchMovieViewModel movie) { // Check if it's in Radarr var result = _db.GetAll().FirstOrDefault(x => x.TheMovieDbId == obj.Id); if (result != null) { - obj.Approved = true; // It's in radarr so it's approved... Maybe have a new property called "Processing" or something? + movie.Approved = true; // It's in radarr so it's approved... Maybe have a new property called "Processing" or something? if (result.HasFile) { - obj.Available = true; + if (result.Has4K) + { + movie.Available4K = true; + } + if (result.HasRegular) + { + movie.Available = true; + } } } } diff --git a/src/Ombi.Core/Senders/IMovieSender.cs b/src/Ombi.Core/Senders/IMovieSender.cs index cf8ddf33b..dcf3f766f 100644 --- a/src/Ombi.Core/Senders/IMovieSender.cs +++ b/src/Ombi.Core/Senders/IMovieSender.cs @@ -6,6 +6,6 @@ namespace Ombi.Core { public interface IMovieSender { - Task Send(MovieRequests model); + Task Send(MovieRequests model, bool is4K); } } \ No newline at end of file diff --git a/src/Ombi.Core/Senders/MovieSender.cs b/src/Ombi.Core/Senders/MovieSender.cs index 87d686d35..36d40bdad 100644 --- a/src/Ombi.Core/Senders/MovieSender.cs +++ b/src/Ombi.Core/Senders/MovieSender.cs @@ -20,13 +20,12 @@ namespace Ombi.Core.Senders { public class MovieSender : IMovieSender { - public MovieSender(ISettingsService radarrSettings, IRadarrApi api, ILogger log, + public MovieSender(ISettingsService radarrSettings, ISettingsService radarr4kSettings, ILogger log, ISettingsService dogSettings, IDogNzbApi dogApi, ISettingsService cpSettings, ICouchPotatoApi cpApi, IRepository userProfiles, IRepository requestQueue, INotificationHelper notify, IRadarrV3Api radarrV3Api) { _radarrSettings = radarrSettings; - _radarrV2Api = api; _log = log; _dogNzbSettings = dogSettings; _dogNzbApi = dogApi; @@ -36,10 +35,11 @@ namespace Ombi.Core.Senders _requestQueuRepository = requestQueue; _notificationHelper = notify; _radarrV3Api = radarrV3Api; + _radarr4KSettings = radarr4kSettings; } private readonly ISettingsService _radarrSettings; - private readonly IRadarrApi _radarrV2Api; + private readonly ISettingsService _radarr4KSettings; private readonly ILogger _log; private readonly IDogNzbApi _dogNzbApi; private readonly ISettingsService _dogNzbSettings; @@ -50,16 +50,24 @@ namespace Ombi.Core.Senders private readonly INotificationHelper _notificationHelper; private readonly IRadarrV3Api _radarrV3Api; - public async Task Send(MovieRequests model) + public async Task Send(MovieRequests model, bool is4K) { try { var cpSettings = await _couchPotatoSettings.GetSettingsAsync(); - //var watcherSettings = await WatcherSettings.GetSettingsAsync(); - var radarrSettings = await _radarrSettings.GetSettingsAsync(); + + RadarrSettings radarrSettings; + if (is4K) + { + radarrSettings = await _radarr4KSettings.GetSettingsAsync(); + } + else + { + radarrSettings = await _radarrSettings.GetSettingsAsync(); + } if (radarrSettings.Enabled) { - return await SendToRadarr(model, radarrSettings); + return await SendToRadarr(model, is4K, radarrSettings); } var dogSettings = await _dogNzbSettings.GetSettingsAsync(); @@ -123,7 +131,7 @@ namespace Ombi.Core.Senders return await _dogNzbApi.AddMovie(settings.ApiKey, id); } - private async Task SendToRadarr(MovieRequests model, RadarrSettings settings) + private async Task SendToRadarr(MovieRequests model, bool is4K, RadarrSettings settings) { var qualityToUse = int.Parse(settings.DefaultQualityProfile); diff --git a/src/Ombi.Core/Senders/TvSender.cs b/src/Ombi.Core/Senders/TvSender.cs index 9f60d2ba0..3676d05ee 100644 --- a/src/Ombi.Core/Senders/TvSender.cs +++ b/src/Ombi.Core/Senders/TvSender.cs @@ -239,7 +239,7 @@ namespace Ombi.Core.Senders languageProfileId = languageProfile; } } - + try { // Does the series actually exist? @@ -357,8 +357,10 @@ namespace Ombi.Core.Senders episodesToUpdate.Add(sonarrEp); } } + + existingSeason = result.seasons.FirstOrDefault(x => x.seasonNumber == season.SeasonNumber); var sonarrEpisodeList = sonarrEpList.Where(x => x.seasonNumber == season.SeasonNumber).ToList(); - var sonarrEpCount = sonarrEpisodeList.Count; + var sonarrEpCount = sonarrEpisodeList.Count; var ourRequestCount = season.Episodes.Count; var ourEpisodes = season.Episodes.Select(x => x.EpisodeNumber).ToList(); @@ -374,17 +376,12 @@ namespace Ombi.Core.Senders if (sonarrEpCount == ourRequestCount /*|| !missingEpisodes.Any()*/) { // We have the same amount of requests as all of the episodes in the season. + existingSeason.monitored = true; + seriesChanges = true; - if (!existingSeason.monitored) - { - existingSeason.monitored = true; - seriesChanges = true; - } - // Now update the episodes that need updating - foreach (var epToUpdate in episodesToUpdate.Where(x => x.seasonNumber == season.SeasonNumber)) - { - await SonarrApi.UpdateEpisode(epToUpdate, s.ApiKey, s.FullUri); - } + // We do not need to update the episodes as marking the season as monitored will mark the episodes as monitored. + var seasonToUpdate = result.seasons.FirstOrDefault(x => x.seasonNumber == season.SeasonNumber); + seasonToUpdate.monitored = true; // Update by ref } else { @@ -442,7 +439,6 @@ namespace Ombi.Core.Senders var seasonsToUpdate = new List(); for (var i = 0; i < model.ParentRequest.TotalSeasons + 1; i++) { - var index = i; var sea = new Season { seasonNumber = i, diff --git a/src/Ombi.Core/Services/FeatureService.cs b/src/Ombi.Core/Services/FeatureService.cs new file mode 100644 index 000000000..279c5c2c5 --- /dev/null +++ b/src/Ombi.Core/Services/FeatureService.cs @@ -0,0 +1,28 @@ +using Ombi.Core.Settings; +using Ombi.Settings.Settings.Models; +using System.Linq; +using System.Threading.Tasks; + +namespace Ombi.Core.Services +{ + public interface IFeatureService + { + Task FeatureEnabled(string featureName); + } + + public class FeatureService : IFeatureService + { + private readonly ISettingsService _featureSettings; + + public FeatureService(ISettingsService featureSettings) + { + _featureSettings = featureSettings; + } + + public async Task FeatureEnabled(string featureName) + { + var settings = await _featureSettings.GetSettingsAsync(); + return settings.Features?.Where(x => x.Name.Equals(featureName, System.StringComparison.InvariantCultureIgnoreCase)).Select(x => x.Enabled)?.FirstOrDefault() ?? false; + } + } +} diff --git a/src/Ombi.Core/Services/RequestLimitService.cs b/src/Ombi.Core/Services/RequestLimitService.cs index 7a8ecd8f0..d90e0d77c 100644 --- a/src/Ombi.Core/Services/RequestLimitService.cs +++ b/src/Ombi.Core/Services/RequestLimitService.cs @@ -1,5 +1,6 @@ using Microsoft.EntityFrameworkCore; using Ombi.Core.Authentication; +using Ombi.Core.Helpers; using Ombi.Core.Models; using Ombi.Helpers; using Ombi.Store.Entities; @@ -20,11 +21,11 @@ namespace Ombi.Core.Services } public class RequestLimitService : IRequestLimitService { - private readonly IPrincipal _user; + private readonly ICurrentUser _user; private readonly OmbiUserManager _userManager; private readonly IRepository _requestLog; - public RequestLimitService(IPrincipal user, OmbiUserManager userManager, IRepository rl) + public RequestLimitService(ICurrentUser user, OmbiUserManager userManager, IRepository rl) { _user = user; _userManager = userManager; @@ -82,7 +83,7 @@ namespace Ombi.Core.Services } - return await CalculateBasicRemaingRequests(user, limit, user.MovieRequestLimitType ?? RequestLimitType.Day, log, now); + return await CalculateBasicRemaingRequests(limit, user.MovieRequestLimitType ?? RequestLimitType.Day, log, now); } public async Task GetRemainingMusicRequests(OmbiUser user, DateTime now = default) @@ -136,16 +137,17 @@ namespace Ombi.Core.Services }; } - return await CalculateBasicRemaingRequests(user, limit, user.MusicRequestLimitType ?? RequestLimitType.Day, log, now); + return await CalculateBasicRemaingRequests(limit, user.MusicRequestLimitType ?? RequestLimitType.Day, log, now); } private async Task GetUser() { - var username = _user.Identity.Name.ToUpper(); + var currentUser = await _user.GetUser(); + var username = currentUser.UserName.ToUpper(); return await _userManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); } - private static async Task CalculateBasicRemaingRequests(OmbiUser user, int limit, RequestLimitType type, IQueryable log, DateTime now) + private static async Task CalculateBasicRemaingRequests(int limit, RequestLimitType type, IQueryable log, DateTime now) { int count = 0; DateTime oldestRequestedAt = DateTime.Now; diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index f81cd05da..691aca237 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -70,6 +70,7 @@ using Ombi.Api.RottenTomatoes; using System.Net.Http; using Microsoft.Extensions.Logging; using Ombi.Core.Services; +using Ombi.Core.Helpers; namespace Ombi.DependencyInjection { @@ -124,6 +125,8 @@ namespace Ombi.DependencyInjection var runtimeVersion = AssemblyHelper.GetRuntimeVersion(); services.AddSingleton(); services.AddScoped(sp => sp.GetService().HttpContext.User); + // HttpContext User is null for background jobs + services.AddScoped(sp => new CurrentUser(sp.GetService()?.HttpContext?.User ?? null, sp.GetService())); services.AddHttpClient("OmbiClient", client => { client.DefaultRequestHeaders.Add("User-Agent", $"Ombi/{runtimeVersion} (https://ombi.io/)"); @@ -224,6 +227,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddScoped(); } public static void RegisterJobs(this IServiceCollection services) @@ -232,6 +236,7 @@ namespace Ombi.DependencyInjection services.AddSingleton(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj index e65f2d5a2..93b839c07 100644 --- a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj +++ b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Helpers/Ombi.Helpers.csproj b/src/Ombi.Helpers/Ombi.Helpers.csproj index afc881d94..2098fa51f 100644 --- a/src/Ombi.Helpers/Ombi.Helpers.csproj +++ b/src/Ombi.Helpers/Ombi.Helpers.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Helpers/OmbiRoles.cs b/src/Ombi.Helpers/OmbiRoles.cs index 02a480fdf..3174419c4 100644 --- a/src/Ombi.Helpers/OmbiRoles.cs +++ b/src/Ombi.Helpers/OmbiRoles.cs @@ -16,5 +16,6 @@ public const string ReceivesNewsletter = nameof(ReceivesNewsletter); public const string ManageOwnRequests = nameof(ManageOwnRequests); public const string EditCustomPage = nameof(EditCustomPage); + public const string Request4KMovie = nameof(Request4KMovie); } } \ No newline at end of file diff --git a/src/Ombi.Helpers/PlexHelper.cs b/src/Ombi.Helpers/PlexHelper.cs index 3e5aeff70..4ae39f6ce 100644 --- a/src/Ombi.Helpers/PlexHelper.cs +++ b/src/Ombi.Helpers/PlexHelper.cs @@ -104,11 +104,11 @@ namespace Ombi.Helpers return new ProviderId(); } - public static string GetPlexMediaUrl(string machineId, int mediaId) + public static string GetPlexMediaUrl(string machineId, string mediaId, string plexHost) { var url = $"web/#!/server/{machineId}/details?key=%2flibrary%2Fmetadata%2F{mediaId}"; - return url; + return BuildPlexMediaUrl(url, plexHost); } public static string BuildPlexMediaUrl(string savedUrl, string plexHost) @@ -180,6 +180,8 @@ namespace Ombi.Helpers public string ImdbId { get; set; } public bool Plex { get; set; } + public bool Any() => TheTvDb.HasValue() || TheMovieDb.HasValue() || ImdbId.HasValue(); + public ProviderType Type { get diff --git a/src/Ombi.Hubs/Ombi.Hubs.csproj b/src/Ombi.Hubs/Ombi.Hubs.csproj index fc65e2dc2..f6bee2eb1 100644 --- a/src/Ombi.Hubs/Ombi.Hubs.csproj +++ b/src/Ombi.Hubs/Ombi.Hubs.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.I18n/Ombi.I18n.csproj b/src/Ombi.I18n/Ombi.I18n.csproj new file mode 100644 index 000000000..a3387cdea --- /dev/null +++ b/src/Ombi.I18n/Ombi.I18n.csproj @@ -0,0 +1,30 @@ + + + + net6.0 + 3.0.0.0 + 3.0.0.0 + + + latest + Debug;Release;NonUiBuild + + + + Always + + + + + True + True + Texts.resx + + + + + PublicResXFileCodeGenerator + Texts.Designer.cs + + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.Designer.cs b/src/Ombi.I18n/Resources/Texts.Designer.cs new file mode 100644 index 000000000..22991cf96 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.Designer.cs @@ -0,0 +1,171 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Ombi.I18n.Resources { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class Texts { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Texts() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Ombi.I18n.Resources.Texts", typeof(Texts).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Album. + /// + public static string Album { + get { + return ResourceManager.GetString("Album", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Type:. + /// + public static string AlbumTypeLabel { + get { + return ResourceManager.GetString("AlbumTypeLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Episodes:. + /// + public static string EpisodesLabel { + get { + return ResourceManager.GetString("EpisodesLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Genres:. + /// + public static string GenresLabel { + get { + return ResourceManager.GetString("GenresLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Movie. + /// + public static string Movie { + get { + return ResourceManager.GetString("Movie", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New Albums. + /// + public static string NewAlbums { + get { + return ResourceManager.GetString("NewAlbums", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New Movies. + /// + public static string NewMovies { + get { + return ResourceManager.GetString("NewMovies", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New TV. + /// + public static string NewTV { + get { + return ResourceManager.GetString("NewTV", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Powered by. + /// + public static string PoweredBy { + get { + return ResourceManager.GetString("PoweredBy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Season:. + /// + public static string SeasonLabel { + get { + return ResourceManager.GetString("SeasonLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to TV Show. + /// + public static string TvShow { + get { + return ResourceManager.GetString("TvShow", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unsubscribe. + /// + public static string Unsubscribe { + get { + return ResourceManager.GetString("Unsubscribe", resourceCulture); + } + } + } +} diff --git a/src/Ombi.I18n/Resources/Texts.bg.resx b/src/Ombi.I18n/Resources/Texts.bg.resx new file mode 100644 index 000000000..81fa9fc9c --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.bg.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + Жанрове: + + + Type: + + + Сезон: + + + Episodes: + + + Powered by + + + Unsubscribe + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.cs.resx b/src/Ombi.I18n/Resources/Texts.cs.resx new file mode 100644 index 000000000..80d3b2d95 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.cs.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Nová alba + + + Nové filmy + + + Nové TV Pořady + + + Žánry: + + + Typ: + + + Série: + + + Epizody: + + + Powered by + + + Odhlásit odběr + + + Album + + + Film + + + TV Pořad + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.da.resx b/src/Ombi.I18n/Resources/Texts.da.resx new file mode 100644 index 000000000..2f217736e --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.da.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Nye Album + + + Nye Film + + + Nye TV-Serier + + + Genre: + + + Type: + + + Sæson: + + + Episoder: + + + Drevet af + + + Afmeld + + + Album + + + Film + + + TV-Serier + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.de.resx b/src/Ombi.I18n/Resources/Texts.de.resx new file mode 100644 index 000000000..a222d02b0 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.de.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Neue Alben + + + Neue Filme + + + Neue Serien + + + Genres: + + + Typ: + + + Staffel: + + + Episoden: + + + Powered by + + + Abbestellen + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.es.resx b/src/Ombi.I18n/Resources/Texts.es.resx new file mode 100644 index 000000000..2268cc561 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.es.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Nuevos Álbumes + + + Nuevas Películas + + + Series Nuevas + + + Géneros: + + + Tipo: + + + Temporada: + + + Episodios: + + + Desarrollado por + + + Anular Suscripción + + + Álbum + + + Película + + + Serie TV + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.fr.resx b/src/Ombi.I18n/Resources/Texts.fr.resx new file mode 100644 index 000000000..9b9d96e48 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.fr.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Nouveaux Albums + + + Nouveaux films + + + Nouvelles séries + + + Genres : + + + Type : + + + Saison : + + + Épisodes : + + + Propulsé par + + + Se désinscrire + + + Album + + + Film + + + Série + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.hu.resx b/src/Ombi.I18n/Resources/Texts.hu.resx new file mode 100644 index 000000000..4e7cebcfd --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.hu.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + Műfaj: + + + Típus: + + + Évad: + + + Epizódok: + + + Powered by + + + Unsubscribe + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.it.resx b/src/Ombi.I18n/Resources/Texts.it.resx new file mode 100644 index 000000000..9d27090b7 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.it.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Nuovi Album + + + Nuovi Film + + + Nuove Serie + + + Generi: + + + Tipo: + + + Stagione: + + + Episodi: + + + Offerto da + + + Disiscriviti + + + Album + + + Film + + + Serie TV + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.nl.resx b/src/Ombi.I18n/Resources/Texts.nl.resx new file mode 100644 index 000000000..e785eb494 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.nl.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Nieuwe albums + + + Nieuwe films + + + Nieuwe TV Series + + + Genres: + + + Type: + + + Seizoen: + + + Afleveringen: + + + Mogelijk gemaakt door + + + Uitschrijven + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.no.resx b/src/Ombi.I18n/Resources/Texts.no.resx new file mode 100644 index 000000000..bf0daa456 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.no.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + Genres: + + + Type: + + + Sesong: + + + Episodes: + + + Powered by + + + Unsubscribe + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.pl.resx b/src/Ombi.I18n/Resources/Texts.pl.resx new file mode 100644 index 000000000..c8e5e5ee1 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.pl.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Nowy Album + + + Nowy film + + + Nowy telewizor + + + Gatunki: + + + Typ: + + + Sezon: + + + Odcinków: + + + Wspierane przez + + + Wypisać się + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.pt-BR.resx b/src/Ombi.I18n/Resources/Texts.pt-BR.resx new file mode 100644 index 000000000..1dcd24317 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.pt-BR.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + Gêneros: + + + Type: + + + Temporada: + + + Episodes: + + + Powered by + + + Unsubscribe + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.pt.resx b/src/Ombi.I18n/Resources/Texts.pt.resx new file mode 100644 index 000000000..f619ffb16 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.pt.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + Genres: + + + Type: + + + Season: + + + Episodes: + + + Powered by + + + Unsubscribe + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.resx b/src/Ombi.I18n/Resources/Texts.resx new file mode 100644 index 000000000..fcfcebfff --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + Genres: + + + Type: + + + Season: + + + Episodes: + + + Powered by + + + Unsubscribe + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.ru.resx b/src/Ombi.I18n/Resources/Texts.ru.resx new file mode 100644 index 000000000..357d1156c --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.ru.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + Genres: + + + Type: + + + Сезон: + + + Episodes: + + + Powered by + + + Unsubscribe + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.sk.resx b/src/Ombi.I18n/Resources/Texts.sk.resx new file mode 100644 index 000000000..8fb4b7157 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.sk.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + Žánre: + + + Typ: + + + Séria: + + + Epizódy: + + + Powered by + + + Unsubscribe + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.sv.resx b/src/Ombi.I18n/Resources/Texts.sv.resx new file mode 100644 index 000000000..779be9937 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.sv.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + Genrer: + + + Type: + + + Säsong: + + + Episodes: + + + Powered by + + + Unsubscribe + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.zh-TW.resx b/src/Ombi.I18n/Resources/Texts.zh-TW.resx new file mode 100644 index 000000000..ca17c4bf6 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.zh-TW.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + 流派 + + + 类型: + + + 季: + + + 集: + + + Powered by + + + Unsubscribe + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.zh.resx b/src/Ombi.I18n/Resources/Texts.zh.resx new file mode 100644 index 000000000..03f696076 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.zh.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 新专辑 + + + 新电影 + + + 新电视节目 + + + 流派 + + + 类型: + + + 季: + + + 集: + + + 技术支持: + + + 取消订阅 + + + 专辑 + + + 电影 + + + 电视节目 + + \ No newline at end of file diff --git a/src/Ombi.Mapping/Ombi.Mapping.csproj b/src/Ombi.Mapping/Ombi.Mapping.csproj index 9ad1f1135..322942cf2 100644 --- a/src/Ombi.Mapping/Ombi.Mapping.csproj +++ b/src/Ombi.Mapping/Ombi.Mapping.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Notifications.Templates/EmailBasicTemplate.cs b/src/Ombi.Notifications.Templates/EmailBasicTemplate.cs index 455c2d182..4bac4b3d8 100644 --- a/src/Ombi.Notifications.Templates/EmailBasicTemplate.cs +++ b/src/Ombi.Notifications.Templates/EmailBasicTemplate.cs @@ -31,16 +31,35 @@ namespace Ombi.Notifications.Templates private const string DateKey = "{@DATENOW}"; private const string Logo = "{@LOGO}"; - public string LoadTemplate(string subject, string body, string imgsrc = default(string), string logo = default(string)) + public string LoadTemplate(string subject, string body, string imgsrc = default(string), string logo = default(string), string url = default(string)) { var sb = new StringBuilder(File.ReadAllText(TemplateLocation)); sb.Replace(SubjectKey, subject); sb.Replace(BodyKey, body); sb.Replace(DateKey, DateTime.Now.ToString("f")); - sb.Replace(Poster, string.IsNullOrEmpty(imgsrc) ? string.Empty : $"\"Poster\""); + sb.Replace(Poster, GetPosterContent(imgsrc, url)); sb.Replace(Logo, string.IsNullOrEmpty(logo) ? OmbiLogo : logo); return sb.ToString(); } + + private string GetPosterContent(string imgsrc, string url) { + string posterContent; + + if (string.IsNullOrEmpty(imgsrc)) + { + posterContent = string.Empty; + } + else + { + posterContent = $"\"Poster\""; + if (!string.IsNullOrEmpty(url)) + { + posterContent = $"{posterContent}"; + } + posterContent = $"{posterContent}"; + } + return posterContent; + } } } diff --git a/src/Ombi.Notifications.Templates/IEmailBasicTemplate.cs b/src/Ombi.Notifications.Templates/IEmailBasicTemplate.cs index 99d7c881a..0a68c0e6b 100644 --- a/src/Ombi.Notifications.Templates/IEmailBasicTemplate.cs +++ b/src/Ombi.Notifications.Templates/IEmailBasicTemplate.cs @@ -2,7 +2,7 @@ { public interface IEmailBasicTemplate { - string LoadTemplate(string subject, string body, string img = default(string), string logo = default(string)); + string LoadTemplate(string subject, string body, string img = default(string), string logo = default(string), string url = default(string)); string TemplateLocation { get; } } } \ No newline at end of file diff --git a/src/Ombi.Notifications.Templates/NewsletterTemplate.cs b/src/Ombi.Notifications.Templates/NewsletterTemplate.cs index ef31dfc4c..9d3b1632a 100644 --- a/src/Ombi.Notifications.Templates/NewsletterTemplate.cs +++ b/src/Ombi.Notifications.Templates/NewsletterTemplate.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Text; +using Ombi.I18n.Resources; namespace Ombi.Notifications.Templates { @@ -30,6 +31,8 @@ namespace Ombi.Notifications.Templates private const string TableLocation = "{@RECENTLYADDED}"; private const string IntroText = "{@INTRO}"; private const string Unsubscribe = "{@UNSUBSCRIBE}"; + private const string UnsubscribeText = "{@UNSUBSCRIBETEXT}"; + private const string PoweredByText = "{@POWEREDBYTEXT}"; public string LoadTemplate(string subject, string intro, string tableHtml, string logo, string unsubscribeLink) @@ -41,6 +44,8 @@ namespace Ombi.Notifications.Templates sb.Replace(DateKey, DateTime.Now.ToString("f")); sb.Replace(Logo, string.IsNullOrEmpty(logo) ? OmbiLogo : logo); sb.Replace(Unsubscribe, string.IsNullOrEmpty(unsubscribeLink) ? string.Empty : unsubscribeLink); + sb.Replace(UnsubscribeText, string.IsNullOrEmpty(unsubscribeLink) ? string.Empty : Texts.Unsubscribe); + sb.Replace(PoweredByText, Texts.PoweredBy); return sb.ToString(); } diff --git a/src/Ombi.Notifications.Templates/Ombi.Notifications.Templates.csproj b/src/Ombi.Notifications.Templates/Ombi.Notifications.Templates.csproj index 33088a591..99e7509b4 100644 --- a/src/Ombi.Notifications.Templates/Ombi.Notifications.Templates.csproj +++ b/src/Ombi.Notifications.Templates/Ombi.Notifications.Templates.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild @@ -17,6 +17,7 @@ Always + \ No newline at end of file diff --git a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html index 71666ba67..fdafdb609 100644 --- a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html +++ b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html @@ -453,12 +453,12 @@ - Unsubscribe + {@UNSUBSCRIBETEXT} - Powered by Ombi + {@POWEREDBYTEXT} Ombi diff --git a/src/Ombi.Notifications.Tests/NotificationServiceTests.cs b/src/Ombi.Notifications.Tests/NotificationServiceTests.cs new file mode 100644 index 000000000..fedd7707e --- /dev/null +++ b/src/Ombi.Notifications.Tests/NotificationServiceTests.cs @@ -0,0 +1,42 @@ +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Moq.AutoMock; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Ombi.Notifications.Tests +{ + [TestFixture] + public class NotificationServiceTests + { + + private NotitficationServiceTestFacade _subject; + + [SetUp] + public void Setup() + { + var mocker = new AutoMocker(); + mocker.Use(NullLogger.Instance); + _subject = mocker.CreateInstance(); + } + + [Test] + public void PopulateAgentsTests() + { + Assert.That(_subject.Agents, Has.Count.EqualTo(12)); + Assert.That(_subject.Agents.DistinctBy(x => x.NotificationName).ToList(), Has.Count.EqualTo(12)); + } + } + + + public class NotitficationServiceTestFacade : NotificationService + { + public NotitficationServiceTestFacade(IServiceProvider provider, ILogger log) : base(provider, log) + { + } + + public List Agents => base.NotificationAgents; + } +} diff --git a/src/Ombi.Notifications.Tests/Ombi.Notifications.Tests.csproj b/src/Ombi.Notifications.Tests/Ombi.Notifications.Tests.csproj index b3edbcf6d..e936c9072 100644 --- a/src/Ombi.Notifications.Tests/Ombi.Notifications.Tests.csproj +++ b/src/Ombi.Notifications.Tests/Ombi.Notifications.Tests.csproj @@ -13,6 +13,7 @@ + diff --git a/src/Ombi.Notifications/Agents/EmailNotification.cs b/src/Ombi.Notifications/Agents/EmailNotification.cs index cb96fcdb6..8f6de1aa3 100644 --- a/src/Ombi.Notifications/Agents/EmailNotification.cs +++ b/src/Ombi.Notifications/Agents/EmailNotification.cs @@ -47,7 +47,7 @@ namespace Ombi.Notifications.Agents return false; } } - if (string.IsNullOrEmpty(settings.Host) || string.IsNullOrEmpty(settings.AdminEmail) || string.IsNullOrEmpty(settings.Port.ToString())) + if (string.IsNullOrEmpty(settings.Host) || string.IsNullOrEmpty(settings.Port.ToString())) { return false; } @@ -64,7 +64,7 @@ namespace Ombi.Notifications.Agents return null; } var email = new EmailBasicTemplate(); - var html = email.LoadTemplate(parsed.Subject, parsed.Message, parsed.Image, Customization.Logo); + var html = email.LoadTemplate(parsed.Subject, parsed.Message, parsed.Image, Customization.Logo, parsed.DetailsUrl); var message = new NotificationMessage @@ -73,26 +73,6 @@ namespace Ombi.Notifications.Agents Subject = parsed.Subject, }; - if (model.Substitutes.TryGetValue("AdminComment", out var isAdminString)) - { - var isAdmin = bool.Parse(isAdminString); - if (isAdmin) - { - var user = _userManager.Users.FirstOrDefault(x => x.Id == model.UserId); - // Send to user - message.To = user.Email; - } - else - { - // Send to admin - message.To = settings.AdminEmail; - } - } - else - { - // Send to admin - message.To = settings.AdminEmail; - } return message; } @@ -138,9 +118,7 @@ namespace Ombi.Notifications.Agents message.Other.Add("PlainTextBody", plaintext); // Issues should be sent to admin - message.To = settings.AdminEmail; - - await Send(message, settings); + await SendToAdmins(message, settings); } protected override async Task IssueComment(NotificationOptions model, EmailNotificationSettings settings) @@ -154,18 +132,16 @@ namespace Ombi.Notifications.Agents var plaintext = await LoadPlainTextMessage(NotificationType.IssueComment, model, settings); message.Other.Add("PlainTextBody", plaintext); - if (model.Substitutes.TryGetValue("AdminComment", out var isAdminString)) + if (model.Substitutes.TryGetValue("AdminComment", out var isAdminString) && !bool.Parse(isAdminString)) { - var isAdmin = bool.Parse(isAdminString); - message.To = isAdmin ? model.Recipient : settings.AdminEmail; + await SendToAdmins(message, settings); } else { message.To = model.Recipient; + await Send(message, settings); } - - await Send(message, settings); } protected override async Task IssueResolved(NotificationOptions model, EmailNotificationSettings settings) @@ -204,9 +180,7 @@ namespace Ombi.Notifications.Agents var plaintext = await LoadPlainTextMessage(NotificationType.ItemAddedToFaultQueue, model, settings); message.Other.Add("PlainTextBody", plaintext); - // Issues resolved should be sent to the user - message.To = settings.AdminEmail; - await Send(message, settings); + await SendToAdmins(message, settings); } protected override async Task RequestDeclined(NotificationOptions model, EmailNotificationSettings settings) @@ -305,6 +279,19 @@ namespace Ombi.Notifications.Agents { await EmailProvider.Send(model, settings); } + + protected async Task SendToAdmins(NotificationMessage message, EmailNotificationSettings settings) + { + foreach (var recipient in (await GetAdminUsers()).DistinctBy(x => x.Email)) + { + if (recipient.Email.IsNullOrEmpty()) + { + continue; + } + message.To = recipient.Email; + await Send(message, settings); + } + } protected override async Task Test(NotificationOptions model, EmailNotificationSettings settings) { @@ -316,12 +303,11 @@ namespace Ombi.Notifications.Agents { Message = html, Subject = $"Ombi: Test", - To = settings.AdminEmail, }; message.Other.Add("PlainTextBody", "This is just a test! Success!"); - await Send(message, settings); + await SendToAdmins(message, settings); } } } diff --git a/src/Ombi.Notifications/BaseNotification.cs b/src/Ombi.Notifications/BaseNotification.cs index 9397767bf..97e2a676d 100644 --- a/src/Ombi.Notifications/BaseNotification.cs +++ b/src/Ombi.Notifications/BaseNotification.cs @@ -33,7 +33,7 @@ namespace Ombi.Notifications AlbumRepository = album; UserNotificationPreferences = notificationUserPreferences; _userManager = um; - Settings.ClearCache(); + Settings?.ClearCache(); } protected ISettingsService Settings { get; } @@ -64,7 +64,11 @@ namespace Ombi.Notifications public async Task NotifyAsync(NotificationOptions model, Settings.Settings.Models.Settings settings) { - if (settings == null) await NotifyAsync(model); + if (settings == null) + { + await NotifyAsync(model); + return; + } var notificationSettings = (T)settings; @@ -114,15 +118,13 @@ namespace Ombi.Notifications case NotificationType.IssueComment: await IssueComment(model, notificationSettings); break; - case NotificationType.AdminNote: - break; - case NotificationType.WelcomeEmail: - break; - case NotificationType.Newsletter: - break; case NotificationType.PartiallyAvailable: await PartiallyAvailable(model, notificationSettings); break; + case NotificationType.AdminNote: + case NotificationType.WelcomeEmail: + case NotificationType.Newsletter: + break; default: throw new ArgumentOutOfRangeException(); } @@ -214,9 +216,14 @@ namespace Ombi.Notifications .FirstOrDefault(x => x.Agent == agent && x.UserId == userId); } - protected async Task> GetPrivilegedUsers() + protected async Task> GetAdminUsers() { IEnumerable recipients = await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin); + return recipients; + } + protected async Task> GetPrivilegedUsers() + { + IEnumerable recipients = await GetAdminUsers(); recipients = recipients.Concat(await _userManager.GetUsersInRoleAsync(OmbiRoles.PowerUser)); return recipients; } diff --git a/src/Ombi.Notifications/NotificationMessageContent.cs b/src/Ombi.Notifications/NotificationMessageContent.cs index 901b3bcb2..7141bbedd 100644 --- a/src/Ombi.Notifications/NotificationMessageContent.cs +++ b/src/Ombi.Notifications/NotificationMessageContent.cs @@ -7,6 +7,7 @@ namespace Ombi.Notifications public bool Disabled { get; set; } public string Subject { get; set; } public string Message { get; set; } + public string DetailsUrl { get; set; } public string Image { get; set; } public IReadOnlyDictionary Data { get; set; } } diff --git a/src/Ombi.Notifications/NotificationMessageCurlys.cs b/src/Ombi.Notifications/NotificationMessageCurlys.cs index 924864c62..7696c9c16 100644 --- a/src/Ombi.Notifications/NotificationMessageCurlys.cs +++ b/src/Ombi.Notifications/NotificationMessageCurlys.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using Humanizer; using Ombi.Helpers; +using Ombi.I18n.Resources; using Ombi.Notifications.Models; using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; @@ -151,6 +152,7 @@ namespace Ombi.Notifications RequestId = req?.Id.ToString(); RequestedUser = req?.RequestedUser?.UserName; RequestedDate = req?.RequestedDate.ToString("D"); + DetailsUrl = GetDetailsUrl(s, req); if (Type.IsNullOrEmpty()) { @@ -192,7 +194,9 @@ namespace Ombi.Notifications return requestType switch { null => string.Empty, - RequestType.TvShow => "TV Show", + RequestType.TvShow => Texts.TvShow, + RequestType.Album => Texts.Album, + RequestType.Movie => Texts.Movie, _ => requestType.Humanize() }; } @@ -214,6 +218,26 @@ namespace Ombi.Notifications } } + private string GetDetailsUrl(CustomizationSettings s, BaseRequest req) + { + if (string.IsNullOrEmpty(s.ApplicationUrl)) + { + return string.Empty; + } + + switch (req) + { + case MovieRequests movieRequest: + return $"{s.ApplicationUrl}/details/movie/{movieRequest.TheMovieDbId}"; + case ChildRequests tvRequest: + return $"{s.ApplicationUrl}/details/tv/{tvRequest.ParentRequest.ExternalProviderId}"; + case AlbumRequest albumRequest: + return $"{s.ApplicationUrl}/details/artist/{albumRequest.ForeignArtistId}"; + default: + return string.Empty; + } + } + private void CalculateRequestStatus(BaseRequest req) { RequestStatus = string.Empty; @@ -255,6 +279,7 @@ namespace Ombi.Notifications public string Year { get; set; } public string EpisodesList { get; set; } public string SeasonsList { get; set; } + public string DetailsUrl { get; set; } public string PosterImage { get; set; } public string ApplicationName { get; set; } public string ApplicationUrl { get; set; } diff --git a/src/Ombi.Notifications/NotificationMessageResolver.cs b/src/Ombi.Notifications/NotificationMessageResolver.cs index fe6102eda..5475f1a97 100644 --- a/src/Ombi.Notifications/NotificationMessageResolver.cs +++ b/src/Ombi.Notifications/NotificationMessageResolver.cs @@ -26,6 +26,7 @@ namespace Ombi.Notifications { var content = Resolve(notification.Message, notification.Subject, c.Curlys); content.Image = c.PosterImage; + content.DetailsUrl = c.DetailsUrl; return content; } diff --git a/src/Ombi.Notifications/NotificationService.cs b/src/Ombi.Notifications/NotificationService.cs index 8a24382aa..f22800cdc 100644 --- a/src/Ombi.Notifications/NotificationService.cs +++ b/src/Ombi.Notifications/NotificationService.cs @@ -23,7 +23,7 @@ namespace Ombi.Notifications PopulateAgents(); } - private List NotificationAgents { get; } + protected List NotificationAgents { get; } private ILogger Log { get; } /// @@ -55,7 +55,7 @@ namespace Ombi.Notifications } - private void PopulateAgents() + protected void PopulateAgents() { var baseSearchType = typeof(BaseNotification<>).Name; diff --git a/src/Ombi.Notifications/Ombi.Notifications.csproj b/src/Ombi.Notifications/Ombi.Notifications.csproj index 6b497c23e..41fd3ae17 100644 --- a/src/Ombi.Notifications/Ombi.Notifications.csproj +++ b/src/Ombi.Notifications/Ombi.Notifications.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj b/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj index fd23ee60b..d8e698d0e 100644 --- a/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj +++ b/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj @@ -19,6 +19,7 @@ + diff --git a/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs b/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs index a86afcad0..6a549458b 100644 --- a/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs +++ b/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs @@ -18,6 +18,7 @@ using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; using Ombi.Store.Repository.Requests; using Ombi.Helpers; +using Ombi.Core.Services; namespace Ombi.Schedule.Tests { @@ -36,7 +37,7 @@ namespace Ombi.Schedule.Tests hub.Setup(x => x.Clients.Clients(It.IsAny>()).SendCoreAsync(It.IsAny(), It.IsAny(), It.IsAny())); NotificationHub.UsersOnline.TryAdd("A", new HubUsers()); - Checker = new PlexAvailabilityChecker(_repo.Object, _tv.Object, _movie.Object, _notify.Object, null, hub.Object); + Checker = new PlexAvailabilityChecker(_repo.Object, _tv.Object, _movie.Object, _notify.Object, null, hub.Object, Mock.Of()); } diff --git a/src/Ombi.Schedule.Tests/PlexContentSyncTests.cs b/src/Ombi.Schedule.Tests/PlexContentSyncTests.cs index 3b9fa33b0..8540f0037 100644 --- a/src/Ombi.Schedule.Tests/PlexContentSyncTests.cs +++ b/src/Ombi.Schedule.Tests/PlexContentSyncTests.cs @@ -47,7 +47,7 @@ namespace Ombi.Schedule.Tests } }; var contentToAdd = new HashSet(); - var contentProcessed = new Dictionary(); + var contentProcessed = new Dictionary(); _mocker.Setup(x => x.GetFirstContentByCustom(It.IsAny>>())) .Returns(Task.FromResult(new PlexServerContent())); @@ -76,18 +76,18 @@ namespace Ombi.Schedule.Tests Id = "imdb://tt0322259" } }, - ratingKey = 1 + ratingKey = "1" }, } }; var contentToAdd = new HashSet(); - var contentProcessed = new Dictionary(); + var contentProcessed = new Dictionary(); await _subject.MovieLoop(new PlexServers(), content, contentToAdd, contentProcessed); var first = contentToAdd.First(); Assert.That(first.ImdbId, Is.EqualTo("tt0322259")); - _mocker.Verify(x => x.GetMetadata(It.IsAny(), It.IsAny(),It.IsAny()), Times.Never); + _mocker.Verify(x => x.GetMetadata(It.IsAny(), It.IsAny(),It.IsAny()), Times.Never); } [Test] @@ -99,7 +99,7 @@ namespace Ombi.Schedule.Tests { new Metadata { - ratingKey = 11, + ratingKey = "11", title = "test1", year = 2021, type = "movie", @@ -107,8 +107,8 @@ namespace Ombi.Schedule.Tests } }; var contentToAdd = new HashSet(); - var contentProcessed = new Dictionary(); - _mocker.Setup(x => x.GetMetadata(It.IsAny(), It.IsAny(), It.IsAny())) + var contentProcessed = new Dictionary(); + _mocker.Setup(x => x.GetMetadata(It.IsAny(), It.IsAny(), It.IsAny())) .Returns(Task.FromResult(new PlexMetadata { MediaContainer = new Mediacontainer @@ -117,7 +117,7 @@ namespace Ombi.Schedule.Tests { new Metadata { - ratingKey = 11, + ratingKey = "11", title = "test1", year = 2021, type = "movie", @@ -133,12 +133,88 @@ namespace Ombi.Schedule.Tests } })); - await _subject.MovieLoop(new PlexServers { Ip = "http://test.com/", Port = 80}, content, contentToAdd, contentProcessed); + await _subject.MovieLoop(new PlexServers { Ip = "http://test.com/", Port = 80 }, content, contentToAdd, contentProcessed); var first = contentToAdd.First(); Assert.That(first.ImdbId, Is.EqualTo("tt0322259")); - _mocker.Verify(x => x.GetMetadata(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + _mocker.Verify(x => x.GetMetadata(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task UpdatesExistingMovieWhen_WeFindAnotherQuality() + { + var content = new Mediacontainer + { + Metadata = new[] + { + new Metadata + { + ratingKey = "11", + title = "test1", + year = 2021, + type = "movie", + Media = new Medium[1] + { + new Medium + { + videoResolution = "4k" + } + } + }, + } + }; + var contentToAdd = new HashSet(); + var contentProcessed = new Dictionary(); + _mocker.Setup(x => + x.GetFirstContentByCustom(It.IsAny>>())) + .Returns(Task.FromResult(new PlexServerContent + { + Quality = "1080" + })); + + await _subject.MovieLoop(new PlexServers(), content, contentToAdd, contentProcessed); + + Assert.That(contentToAdd, Is.Empty); + _mocker.Verify(x => x.Update(It.Is(x => x.Quality == "1080" && x.Has4K)), Times.Once); + } + + [Test] + public async Task DoesNotUpdatesExistingMovieWhen_WeFindSameQuality() + { + var content = new Mediacontainer + { + Metadata = new[] + { + new Metadata + { + ratingKey = "11", + title = "test1", + year = 2021, + type = "movie", + Media = new Medium[1] + { + new Medium + { + videoResolution = "1080" + } + } + }, + } + }; + var contentToAdd = new HashSet(); + var contentProcessed = new Dictionary(); + _mocker.Setup(x => + x.GetFirstContentByCustom(It.IsAny>>())) + .Returns(Task.FromResult(new PlexServerContent + { + Quality = "1080" + })); + + await _subject.MovieLoop(new PlexServers(), content, contentToAdd, contentProcessed); + + Assert.That(contentToAdd, Is.Empty); + _mocker.Verify(x => x.Update(It.IsAny()), Times.Never); } } } diff --git a/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs b/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs new file mode 100644 index 000000000..950f6f431 --- /dev/null +++ b/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs @@ -0,0 +1,468 @@ +using Moq; +using Moq.AutoMock; +using NUnit.Framework; +using Ombi.Api.Plex; +using Ombi.Api.Plex.Models; +using Ombi.Core.Engine; +using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Models.Requests; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; +using Ombi.Schedule.Jobs.Plex; +using Ombi.Store.Entities; +using Ombi.Store.Repository; +using Ombi.Test.Common; +using Quartz; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Ombi.Schedule.Tests +{ + [TestFixture] + public class PlexWatchlistImportTests + { + + private PlexWatchlistImport _subject; + private AutoMocker _mocker; + private Mock _context; + + [SetUp] + public void Setup() + { + _mocker = new AutoMocker(); + var um = MockHelper.MockUserManager(new List { new OmbiUser { Id = "abc", UserType = UserType.PlexUser, MediaServerToken = "abc", UserName = "abc", NormalizedUserName = "ABC" } }); + _mocker.Use(um); + _context = _mocker.GetMock(); + _context.Setup(x => x.CancellationToken).Returns(CancellationToken.None); + _subject = _mocker.CreateInstance(); + } + + [Test] + public async Task TerminatesWhenPlexIsNotEnabled() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = false, EnableWatchlistImport = true }); + await _subject.Execute(null); + _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + _mocker.Verify(x => x.GetWatchlist(It.IsAny(), It.IsAny()), Times.Never); + _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + } + [Test] + public async Task TerminatesWhenWatchlistIsNotEnabled() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = false }); + await _subject.Execute(null); + _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + _mocker.Verify(x => x.GetWatchlist(It.IsAny(), It.IsAny()), Times.Never); + _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + } + + [Test] + public async Task EmptyWatchList() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true }); + _mocker.Setup>(x => x.GetWatchlist(It.IsAny(), It.IsAny())).ReturnsAsync(new PlexWatchlistContainer()); + await _subject.Execute(_context.Object); + _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + _mocker.Verify(x => x.GetWatchlist(It.IsAny(), It.IsAny()), Times.Once); + _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + } + + [Test] + public async Task NoPlexUsersWithToken() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true }); + var um = MockHelper.MockUserManager(new List + { + new OmbiUser { Id = "abc", UserType = UserType.EmbyUser, MediaServerToken = "abc", UserName = "abc", NormalizedUserName = "ABC" }, + new OmbiUser { Id = "abc", UserType = UserType.LocalUser, MediaServerToken = "abc", UserName = "abc", NormalizedUserName = "ABC" }, + new OmbiUser { Id = "abc", UserType = UserType.SystemUser, MediaServerToken = "abc", UserName = "abc", NormalizedUserName = "ABC" }, + new OmbiUser { Id = "abc", UserType = UserType.JellyfinUser, MediaServerToken = "abc", UserName = "abc", NormalizedUserName = "ABC" }, + new OmbiUser { Id = "abc", UserType = UserType.EmbyConnectUser, MediaServerToken = "abc", UserName = "abc", NormalizedUserName = "ABC" }, + new OmbiUser { Id = "abc", UserType = UserType.PlexUser, UserName = "abc", NormalizedUserName = "ABC" }, + }); + _mocker.Use(um); + _subject = _mocker.CreateInstance(); + + await _subject.Execute(_context.Object); + _mocker.Verify(x => x.GetWatchlist(It.IsAny(), It.IsAny()), Times.Never); + _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + } + + + [Test] + public async Task MultipleUsers() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true }); + var um = MockHelper.MockUserManager(new List + { + new OmbiUser { Id = "abc1", UserType = UserType.PlexUser, MediaServerToken = "abc1", UserName = "abc1", NormalizedUserName = "ABC1" }, + new OmbiUser { Id = "abc2", UserType = UserType.PlexUser, MediaServerToken = "abc2", UserName = "abc2", NormalizedUserName = "ABC2" }, + new OmbiUser { Id = "abc3", UserType = UserType.PlexUser, MediaServerToken = "abc3", UserName = "abc3", NormalizedUserName = "ABC3" }, + new OmbiUser { Id = "abc4", UserType = UserType.PlexUser, MediaServerToken = "abc4", UserName = "abc4", NormalizedUserName = "ABC4" }, + new OmbiUser { Id = "abc5", UserType = UserType.PlexUser, MediaServerToken = "abc5", UserName = "abc5", NormalizedUserName = "ABC5" }, + }); + _mocker.Use(um); + _subject = _mocker.CreateInstance(); + + await _subject.Execute(_context.Object); + _mocker.Verify(x => x.GetWatchlist(It.IsAny(), It.IsAny()), Times.Exactly(5)); + _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + } + + + [Test] + public async Task MovieRequestFromWatchList_NoGuid() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true }); + _mocker.Setup>(x => x.GetWatchlist(It.IsAny(), It.IsAny())).ReturnsAsync(new PlexWatchlistContainer + { + MediaContainer = new PlexWatchlist + { + Metadata = new List + { + new Metadata + { + type = "movie", + ratingKey = "abc" + } + } + } + }); + _mocker.Setup>(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny())) + .ReturnsAsync(new PlexWatchlistMetadataContainer + { + MediaContainer = new PlexWatchlistMetadata + { + Metadata = new WatchlistMetadata[] + { + new WatchlistMetadata + { + Guid = new List + { + new PlexGuids + { + Id = "tmdb://123" + } + } + } + } + + } + }); + _mocker.Setup>(x => x.RequestMovie(It.IsAny())) + .ReturnsAsync(new RequestEngineResult { RequestId = 1 }); + await _subject.Execute(_context.Object); + _mocker.Verify(x => x.RequestMovie(It.Is(x => x.TheMovieDbId == 123)), Times.Once); + _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); + _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); + _mocker.Verify>(x => x.GetAll(), Times.Once); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Once); + } + + + [Test] + public async Task TvRequestFromWatchList_NoGuid() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true }); + _mocker.Setup>(x => x.GetWatchlist(It.IsAny(), It.IsAny())).ReturnsAsync(new PlexWatchlistContainer + { + MediaContainer = new PlexWatchlist + { + Metadata = new List + { + new Metadata + { + type = "show", + ratingKey = "abc" + } + } + } + }); + _mocker.Setup>(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny())) + .ReturnsAsync(new PlexWatchlistMetadataContainer + { + MediaContainer = new PlexWatchlistMetadata + { + Metadata = new WatchlistMetadata[] + { + new WatchlistMetadata + { + Guid = new List + { + new PlexGuids + { + Id = "tmdb://123" + } + } + } + } + + } + }); + _mocker.Setup>(x => x.RequestTvShow(It.IsAny())) + .ReturnsAsync(new RequestEngineResult { RequestId = 1 }); + await _subject.Execute(_context.Object); + _mocker.Verify(x => x.RequestTvShow(It.Is(x => x.TheMovieDbId == 123 && x.LatestSeason == true)), Times.Once); + _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); + _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); + _mocker.Verify>(x => x.GetAll(), Times.Once); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Once); + } + + [Test] + public async Task MovieRequestFromWatchList_AlreadyRequested() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true }); + _mocker.Setup>(x => x.GetWatchlist(It.IsAny(), It.IsAny())).ReturnsAsync(new PlexWatchlistContainer + { + MediaContainer = new PlexWatchlist + { + Metadata = new List + { + new Metadata + { + type = "movie", + ratingKey = "abc" + } + } + } + }); + _mocker.Setup>(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny())) + .ReturnsAsync(new PlexWatchlistMetadataContainer + { + MediaContainer = new PlexWatchlistMetadata + { + Metadata = new WatchlistMetadata[] + { + new WatchlistMetadata + { + Guid = new List + { + new PlexGuids + { + Id = "tmdb://123" + } + } + } + } + + } + }); + _mocker.Setup>(x => x.RequestMovie(It.IsAny())) + .ReturnsAsync(new RequestEngineResult { ErrorCode = ErrorCode.AlreadyRequested, ErrorMessage = "Requested" }); + await _subject.Execute(_context.Object); + _mocker.Verify(x => x.RequestMovie(It.Is(x => x.TheMovieDbId == 123)), Times.Once); + _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); + _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); + _mocker.Verify>(x => x.GetAll(), Times.Once); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Once); + } + + [Test] + public async Task TvRequestFromWatchList_AlreadyRequested() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true }); + _mocker.Setup>(x => x.GetWatchlist(It.IsAny(), It.IsAny())).ReturnsAsync(new PlexWatchlistContainer + { + MediaContainer = new PlexWatchlist + { + Metadata = new List + { + new Metadata + { + type = "show", + ratingKey = "abc" + } + } + } + }); + _mocker.Setup>(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny())) + .ReturnsAsync(new PlexWatchlistMetadataContainer + { + MediaContainer = new PlexWatchlistMetadata + { + Metadata = new WatchlistMetadata[] + { + new WatchlistMetadata + { + Guid = new List + { + new PlexGuids + { + Id = "tmdb://123" + } + } + } + } + + } + }); + _mocker.Setup>(x => x.RequestTvShow(It.IsAny())) + .ReturnsAsync(new RequestEngineResult { ErrorCode = ErrorCode.AlreadyRequested, ErrorMessage = "Requested" }); + await _subject.Execute(_context.Object); + _mocker.Verify(x => x.RequestTvShow(It.Is(x => x.TheMovieDbId == 123)), Times.Once); + _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); + _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); + _mocker.Verify>(x => x.GetAll(), Times.Once); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Once); + } + + [Test] + public async Task MovieRequestFromWatchList_NoTmdbGuid() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true }); + _mocker.Setup>(x => x.GetWatchlist(It.IsAny(), It.IsAny())).ReturnsAsync(new PlexWatchlistContainer + { + MediaContainer = new PlexWatchlist + { + Metadata = new List + { + new Metadata + { + type = "movie", + ratingKey = "abc" + } + } + } + }); + _mocker.Setup>(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny())) + .ReturnsAsync(new PlexWatchlistMetadataContainer + { + MediaContainer = new PlexWatchlistMetadata + { + Metadata = new WatchlistMetadata[] + { + new WatchlistMetadata + { + Guid = new List + { + new PlexGuids + { + Id = "imdb://123" + } + } + } + } + + } + }); + _mocker.Setup>(x => x.RequestMovie(It.IsAny())) + .ReturnsAsync(new RequestEngineResult { RequestId = 1 }); + await _subject.Execute(_context.Object); + _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); + _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); + } + + [Test] + public async Task TvRequestFromWatchList_NoTmdbGuid() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true }); + _mocker.Setup>(x => x.GetWatchlist(It.IsAny(), It.IsAny())).ReturnsAsync(new PlexWatchlistContainer + { + MediaContainer = new PlexWatchlist + { + Metadata = new List + { + new Metadata + { + type = "movie", + ratingKey = "abc" + } + } + } + }); + _mocker.Setup>(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny())) + .ReturnsAsync(new PlexWatchlistMetadataContainer + { + MediaContainer = new PlexWatchlistMetadata + { + Metadata = new WatchlistMetadata[] + { + new WatchlistMetadata + { + Guid = new List + { + new PlexGuids + { + Id = "imdb://123" + } + } + } + } + + } + }); + _mocker.Setup>(x => x.RequestTvShow(It.IsAny())) + .ReturnsAsync(new RequestEngineResult { RequestId = 1 }); + await _subject.Execute(_context.Object); + _mocker.Verify(x => x.RequestTvShow(It.IsAny()), Times.Never); + _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); + _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); + } + + [Test] + public async Task MovieRequestFromWatchList_AlreadyImported() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true }); + _mocker.Setup>(x => x.GetWatchlist(It.IsAny(), It.IsAny())).ReturnsAsync(new PlexWatchlistContainer + { + MediaContainer = new PlexWatchlist + { + Metadata = new List + { + new Metadata + { + type = "movie", + ratingKey = "abc" + } + } + } + }); + _mocker.Setup>(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny())) + .ReturnsAsync(new PlexWatchlistMetadataContainer + { + MediaContainer = new PlexWatchlistMetadata + { + Metadata = new WatchlistMetadata[] + { + new WatchlistMetadata + { + Guid = new List + { + new PlexGuids + { + Id = "tmdb://123" + } + } + } + } + + } + }); + _mocker.Setup, IQueryable>(x => x.GetAll()).Returns(new List { new PlexWatchlistHistory { Id = 1, TmdbId = "123" } }.AsQueryable()); + await _subject.Execute(_context.Object); + _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); + _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Once); + } + } +} diff --git a/src/Ombi.Schedule/Jobs/ArrAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/ArrAvailabilityChecker.cs index 0020bb24f..d20f906c6 100644 --- a/src/Ombi.Schedule/Jobs/ArrAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/ArrAvailabilityChecker.cs @@ -73,23 +73,37 @@ namespace Ombi.Schedule.Jobs.Radarr private async Task ProcessMovies() { var availableRadarrMovies = _radarrRepo.GetAll().Where(x => x.HasFile).ToImmutableHashSet(); - var unavailableMovieRequests = _movies.GetAll().Where(x => !x.Available).ToImmutableHashSet(); + var unavailableMovieRequests = _movies.GetAll().Where(x => !x.Available || (!x.Available4K && x.Has4KRequest)).ToImmutableHashSet(); var itemsForAvailability = new List(); foreach (var movieRequest in unavailableMovieRequests) { // Do we have an item in the radarr list - var available = availableRadarrMovies.Any(x => x.TheMovieDbId == movieRequest.TheMovieDbId); - if (available) + var available = availableRadarrMovies.FirstOrDefault(x => x.TheMovieDbId == movieRequest.TheMovieDbId); + if (available != null) { _logger.LogInformation($"Found move '{movieRequest.Title}' available in Radarr"); - movieRequest.Available = true; - movieRequest.MarkedAsAvailable = DateTime.UtcNow; - itemsForAvailability.Add(new AvailabilityModel + if (available.Has4K && !movieRequest.Available4K) { - Id = movieRequest.Id, - RequestedUser = movieRequest.RequestedUser != null ? movieRequest.RequestedUser.Email : string.Empty - }); + itemsForAvailability.Add(new AvailabilityModel + { + Id = movieRequest.Id, + RequestedUser = movieRequest.RequestedUser != null ? movieRequest.RequestedUser.Email : string.Empty + }); + movieRequest.Available4K = true; + movieRequest.MarkedAsAvailable4K = DateTime.UtcNow; + } + if (available.HasRegular) + { + itemsForAvailability.Add(new AvailabilityModel + { + Id = movieRequest.Id, + RequestedUser = movieRequest.RequestedUser != null ? movieRequest.RequestedUser.Email : string.Empty + }); + movieRequest.Available = true; + movieRequest.MarkedAsAvailable = DateTime.UtcNow; + } + await _movies.SaveChangesAsync(); } } @@ -97,7 +111,6 @@ namespace Ombi.Schedule.Jobs.Radarr { await _hub.Clients.Clients(NotificationHub.AdminConnectionIds) .SendAsync(NotificationHub.NotificationEvent, "Radarr Availability Checker found some new available movies!"); - await _movies.SaveChangesAsync(); } foreach (var item in itemsForAvailability) { @@ -110,7 +123,6 @@ namespace Ombi.Schedule.Jobs.Radarr Recipient = item.RequestedUser }); } - } public async Task ProcessTvShows() diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs index 608d6cb82..9d88c5907 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs @@ -53,10 +53,11 @@ namespace Ombi.Schedule.Jobs.Emby private async Task ProcessMovies() { - var movies = _movieRepo.GetAll().Include(x => x.RequestedUser).Where(x => !x.Available); + var movies = _movieRepo.GetAll().Include(x => x.RequestedUser).Where(x => !x.Available || (!x.Available4K && x.Has4KRequest)); foreach (var movie in movies) { + var has4kRequest = movie.Has4KRequest; EmbyContent embyContent = null; if (movie.TheMovieDbId > 0) { @@ -75,9 +76,23 @@ namespace Ombi.Schedule.Jobs.Emby _log.LogInformation("We have found the request {0} on Emby, sending the notification", movie?.Title ?? string.Empty); - movie.Available = true; - movie.MarkedAsAvailable = DateTime.Now; - if (movie.Available) + var notify = false; + + if (has4kRequest && embyContent.Has4K && !movie.Available4K) + { + movie.Available4K = true; + movie.MarkedAsAvailable4K = DateTime.Now; + notify = true; + } + + // If we have a non-4k versison then mark as available + if (embyContent.Quality != null && !movie.Available) + { + movie.Available = true; + movie.MarkedAsAvailable = DateTime.Now; + notify = true; + } + if (notify) { var recipient = movie.RequestedUser.Email.HasValue() ? movie.RequestedUser.Email : string.Empty; @@ -124,7 +139,7 @@ namespace Ombi.Schedule.Jobs.Emby var tvDbId = child.ParentRequest.TvDbId; var imdbId = child.ParentRequest.ImdbId; - IQueryable seriesEpisodes = null; + IQueryable seriesEpisodes = null; if (useImdb) { seriesEpisodes = embyEpisodes.Where(x => x.Series.ImdbId == imdbId.ToString()); diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs index 154ae784f..b4d61f93d 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR; @@ -16,7 +17,7 @@ using Ombi.Schedule.Jobs.Ombi; using Ombi.Store.Entities; using Ombi.Store.Repository; using Quartz; -using EmbyMediaType = Ombi.Store.Entities.EmbyMediaType; +using MediaType = Ombi.Store.Entities.MediaType; namespace Ombi.Schedule.Jobs.Emby { @@ -86,10 +87,10 @@ namespace Ombi.Schedule.Jobs.Emby private async Task StartServerCache(EmbyServers server, bool recentlyAdded) { if (!ValidateSettings(server)) + { return; + } - //await _repo.ExecuteSql("DELETE FROM EmbyEpisode"); - //await _repo.ExecuteSql("DELETE FROM EmbyContent"); if (server.EmbySelectedLibraries.Any() && server.EmbySelectedLibraries.Any(x => x.Enabled)) { @@ -149,7 +150,7 @@ namespace Ombi.Schedule.Jobs.Emby foreach (var tvShow in tv.Items) { processed++; - if (string.IsNullOrEmpty(tvShow.ProviderIds?.Tvdb)) + if (!tvShow.ProviderIds.Any()) { _logger.LogInformation("Provider Id on tv {0} is null", tvShow.Name); continue; @@ -165,10 +166,10 @@ namespace Ombi.Schedule.Jobs.Emby ImdbId = tvShow.ProviderIds?.Imdb, TheMovieDbId = tvShow.ProviderIds?.Tmdb, Title = tvShow.Name, - Type = EmbyMediaType.Series, + Type = MediaType.Series, EmbyId = tvShow.Id, Url = EmbyHelper.GetEmbyMediaUrl(tvShow.Id, server?.ServerId, server.ServerHostname), - AddedAt = DateTime.UtcNow + AddedAt = DateTime.UtcNow, }); } else @@ -209,6 +210,7 @@ namespace Ombi.Schedule.Jobs.Emby var totalCount = movies.TotalRecordCount; var processed = 0; var mediaToAdd = new HashSet(); + var mediaToUpdate = new HashSet(); while (processed < totalCount) { foreach (var movie in movies.Items) @@ -219,13 +221,13 @@ namespace Ombi.Schedule.Jobs.Emby await Api.GetCollection(movie.Id, server.ApiKey, server.AdministratorId, server.FullUri); foreach (var item in movieInfo.Items) { - await ProcessMovies(item, mediaToAdd, server); + await ProcessMovies(item, mediaToAdd, mediaToUpdate, server); } } else { // Regular movie - await ProcessMovies(movie, mediaToAdd, server); + await ProcessMovies(movie, mediaToAdd, mediaToUpdate, server); } processed++; @@ -238,33 +240,63 @@ namespace Ombi.Schedule.Jobs.Emby movies = await Api.GetAllMovies(server.ApiKey, parentId, processed, AmountToTake, server.AdministratorId, server.FullUri); } await _repo.AddRange(mediaToAdd); + await _repo.UpdateRange(mediaToUpdate); mediaToAdd.Clear(); } } - private async Task ProcessMovies(EmbyMovie movieInfo, ICollection content, EmbyServers server) + private async Task ProcessMovies(EmbyMovie movieInfo, ICollection content, ICollection toUpdate, EmbyServers server) { + var quality = movieInfo.MediaStreams?.FirstOrDefault()?.DisplayTitle ?? string.Empty; + var has4K = false; + if (quality.Contains("4K", CompareOptions.IgnoreCase)) + { + has4K = true; + } + // Check if it exists var existingMovie = await _repo.GetByEmbyId(movieInfo.Id); var alreadyGoingToAdd = content.Any(x => x.EmbyId == movieInfo.Id); if (existingMovie == null && !alreadyGoingToAdd) { - _logger.LogDebug("Adding new movie {0}", movieInfo.Name); + if (!movieInfo.ProviderIds.Any()) + { + _logger.LogWarning($"Movie {movieInfo.Name} has no relevant metadata. Skipping."); + return; + } + _logger.LogDebug($"Adding new movie {movieInfo.Name}"); + content.Add(new EmbyContent { ImdbId = movieInfo.ProviderIds.Imdb, TheMovieDbId = movieInfo.ProviderIds?.Tmdb, Title = movieInfo.Name, - Type = EmbyMediaType.Movie, + Type = MediaType.Movie, EmbyId = movieInfo.Id, Url = EmbyHelper.GetEmbyMediaUrl(movieInfo.Id, server?.ServerId, server.ServerHostname), AddedAt = DateTime.UtcNow, + Quality = has4K ? null : quality, + Has4K = has4K }); } else { - // we have this - _logger.LogDebug("We already have movie {0}", movieInfo.Name); + if (!quality.Equals(existingMovie?.Quality, StringComparison.InvariantCultureIgnoreCase)) + { + _logger.LogDebug($"We have found another quality for Movie '{movieInfo.Name}', Quality: '{quality}'"); + existingMovie.Quality = has4K ? null : quality; + existingMovie.Has4K = has4K; + + // Probably could refactor here + // If a 4k movie comes in (we don't store the quality on 4k) + // it will always get updated even know it's not changed + toUpdate.Add(existingMovie); + } + else + { + // we have this + _logger.LogDebug($"We already have movie {movieInfo.Name}"); + } } } diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs index c1ca48ef7..b3c1ffbab 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs @@ -152,6 +152,13 @@ namespace Ombi.Schedule.Jobs.Emby if (existingEpisode == null && !existingInList) { + // Sanity checks + if (ep.IndexNumber == 0) + { + _logger.LogWarning($"Episode {ep.Name} has no episode number. Skipping."); + continue; + } + _logger.LogDebug("Adding new episode {0} to parent {1}", ep.Name, ep.SeriesName); // add it epToAdd.Add(new EmbyEpisode diff --git a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs index 1a621ebce..b1dafa71f 100644 --- a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs @@ -33,11 +33,9 @@ using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Ombi.Core; -using Ombi.Core.Notifications; using Ombi.Helpers; using Ombi.Hubs; using Ombi.Notifications.Models; -using Ombi.Schedule.Jobs.Ombi; using Ombi.Store.Entities; using Ombi.Store.Repository; using Ombi.Store.Repository.Requests; @@ -80,10 +78,11 @@ namespace Ombi.Schedule.Jobs.Jellyfin private async Task ProcessMovies() { - var movies = _movieRepo.GetAll().Include(x => x.RequestedUser).Where(x => !x.Available); + var movies = _movieRepo.GetAll().Include(x => x.RequestedUser).Where(x => !x.Available || (!x.Available4K && x.Has4KRequest)); foreach (var movie in movies) { + var has4kRequest = movie.Has4KRequest; JellyfinContent jellyfinContent = null; if (movie.TheMovieDbId > 0) { @@ -102,9 +101,24 @@ namespace Ombi.Schedule.Jobs.Jellyfin _log.LogInformation("We have found the request {0} on Jellyfin, sending the notification", movie?.Title ?? string.Empty); - movie.Available = true; - movie.MarkedAsAvailable = DateTime.Now; - if (movie.Available) + var notify = false; + + if (has4kRequest && jellyfinContent.Has4K && !movie.Available4K) + { + movie.Available4K = true; + movie.MarkedAsAvailable4K = DateTime.Now; + notify = true; + } + + // If we have a non-4k versison then mark as available + if (jellyfinContent.Quality != null && !movie.Available) + { + movie.Available = true; + movie.MarkedAsAvailable = DateTime.Now; + notify = true; + } + + if (notify) { var recipient = movie.RequestedUser.Email.HasValue() ? movie.RequestedUser.Email : string.Empty; @@ -151,7 +165,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin var tvDbId = child.ParentRequest.TvDbId; var imdbId = child.ParentRequest.ImdbId; - IQueryable seriesEpisodes = null; + IQueryable seriesEpisodes = null; if (useImdb) { seriesEpisodes = jellyfinEpisodes.Where(x => x.Series.ImdbId == imdbId.ToString()); diff --git a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs index e8de12bd2..060c974e7 100644 --- a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR; @@ -14,7 +15,7 @@ using Ombi.Schedule.Jobs.Ombi; using Ombi.Store.Entities; using Ombi.Store.Repository; using Quartz; -using JellyfinMediaType = Ombi.Store.Entities.JellyfinMediaType; +using MediaType = Ombi.Store.Entities.MediaType; namespace Ombi.Schedule.Jobs.Jellyfin { @@ -77,9 +78,6 @@ namespace Ombi.Schedule.Jobs.Jellyfin return; } - //await _repo.ExecuteSql("DELETE FROM JellyfinEpisode"); - //await _repo.ExecuteSql("DELETE FROM JellyfinContent"); - if (server.JellyfinSelectedLibraries.Any() && server.JellyfinSelectedLibraries.Any(x => x.Enabled)) { var movieLibsToFilter = server.JellyfinSelectedLibraries.Where(x => x.Enabled && x.CollectionType == "movies"); @@ -127,7 +125,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin { processed++; - if (string.IsNullOrEmpty(tvShow.ProviderIds?.Tvdb)) + if (!tvShow.ProviderIds.Any()) { _logger.LogInformation("Provider Id on tv {0} is null", tvShow.Name); continue; @@ -143,7 +141,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin ImdbId = tvShow.ProviderIds?.Imdb, TheMovieDbId = tvShow.ProviderIds?.Tmdb, Title = tvShow.Name, - Type = JellyfinMediaType.Series, + Type = MediaType.Series, JellyfinId = tvShow.Id, Url = JellyfinHelper.GetJellyfinMediaUrl(tvShow.Id, server?.ServerId, server.ServerHostname), AddedAt = DateTime.UtcNow @@ -179,6 +177,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin var totalCount = movies.TotalRecordCount; var processed = 0; var mediaToAdd = new HashSet(); + var mediaToUpdate = new HashSet(); while (processed < totalCount) { foreach (var movie in movies.Items) @@ -189,7 +188,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin await Api.GetCollection(movie.Id, server.ApiKey, server.AdministratorId, server.FullUri); foreach (var item in movieInfo.Items) { - await ProcessMovies(item, mediaToAdd, server); + await ProcessMovies(item, mediaToAdd, mediaToUpdate, server); } processed++; @@ -198,41 +197,70 @@ namespace Ombi.Schedule.Jobs.Jellyfin { processed++; // Regular movie - await ProcessMovies(movie, mediaToAdd, server); + await ProcessMovies(movie, mediaToAdd, mediaToUpdate, server); } } // Get the next batch movies = await Api.GetAllMovies(server.ApiKey, parentId, processed, 200, server.AdministratorId, server.FullUri); await _repo.AddRange(mediaToAdd); + await _repo.UpdateRange(mediaToUpdate); mediaToAdd.Clear(); } } - private async Task ProcessMovies(JellyfinMovie movieInfo, ICollection content, JellyfinServers server) + private async Task ProcessMovies(JellyfinMovie movieInfo, ICollection content, ICollection toUpdate, JellyfinServers server) { + var quality = movieInfo.MediaStreams?.FirstOrDefault()?.DisplayTitle ?? string.Empty; + var has4K = false; + if (quality.Contains("4K", CompareOptions.IgnoreCase)) + { + has4K = true; + } + // Check if it exists var existingMovie = await _repo.GetByJellyfinId(movieInfo.Id); var alreadyGoingToAdd = content.Any(x => x.JellyfinId == movieInfo.Id); if (existingMovie == null && !alreadyGoingToAdd) { - _logger.LogDebug("Adding new movie {0}", movieInfo.Name); + if (!movieInfo.ProviderIds.Any()) + { + _logger.LogWarning($"Movie {movieInfo.Name} has no relevant metadata. Skipping."); + return; + } + _logger.LogDebug($"Adding new movie {movieInfo.Name}"); content.Add(new JellyfinContent { ImdbId = movieInfo.ProviderIds.Imdb, TheMovieDbId = movieInfo.ProviderIds?.Tmdb, Title = movieInfo.Name, - Type = JellyfinMediaType.Movie, + Type = MediaType.Movie, JellyfinId = movieInfo.Id, Url = JellyfinHelper.GetJellyfinMediaUrl(movieInfo.Id, server?.ServerId, server.ServerHostname), AddedAt = DateTime.UtcNow, + Quality = has4K ? null : quality, + Has4K = has4K }); } else { - // we have this - _logger.LogDebug("We already have movie {0}", movieInfo.Name); + if (!quality.Equals(existingMovie?.Quality, StringComparison.InvariantCultureIgnoreCase)) + { + _logger.LogDebug($"We have found another quality for Movie '{movieInfo.Name}', Quality: '{quality}'"); + existingMovie.Quality = has4K ? null : quality; + existingMovie.Has4K = has4K; + + // Probably could refactor here + // If a 4k movie comes in (we don't store the quality on 4k) + // it will always get updated even know it's not changed + toUpdate.Add(existingMovie); + } + else + { + // we have this + _logger.LogDebug($"We already have movie {movieInfo.Name}"); + } } } diff --git a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinEpisodeSync.cs index 27e50c9b7..6e2daa7b3 100644 --- a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinEpisodeSync.cs @@ -66,7 +66,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin public async Task Execute(IJobExecutionContext job) { var settings = await _settings.GetSettingsAsync(); - + Api = _apiFactory.CreateClient(settings); await _notification.Clients.Clients(NotificationHub.AdminConnectionIds) .SendAsync(NotificationHub.NotificationEvent, "Jellyfin Episode Sync Started"); @@ -128,6 +128,13 @@ namespace Ombi.Schedule.Jobs.Jellyfin if (existingEpisode == null && !existingInList) { + // Sanity checks + if (ep.IndexNumber == 0) // no check on season number, Season 0 can be Specials + { + _logger.LogWarning($"Episode {ep.Name} has no episode number. Skipping."); + continue; + } + _logger.LogDebug("Adding new episode {0} to parent {1}", ep.Name, ep.SeriesName); // add it epToAdd.Add(new JellyfinEpisode diff --git a/src/Ombi.Schedule/Jobs/Ombi/AutoDeleteRequests.cs b/src/Ombi.Schedule/Jobs/Ombi/AutoDeleteRequests.cs index a2a7e4ed1..eba3c4998 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/AutoDeleteRequests.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/AutoDeleteRequests.cs @@ -25,7 +25,7 @@ namespace Ombi.Schedule.Jobs.Ombi _ombiSettings = ombiSettings; _movieRequests = movieRequest; _tvRequestRepository = tvRequestRepository; - _musicRequestRepository = _musicRequestRepository; + _musicRequestRepository = musicRequestRepository; _logger = logger; } diff --git a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs index 54d1d1133..9d49fe2f1 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs @@ -5,7 +5,8 @@ namespace Ombi.Schedule.Jobs.Ombi { public abstract class HtmlTemplateGenerator { - protected virtual void AddBackgroundInsideTable(StringBuilder sb, string url) + protected StringBuilder sb; + protected virtual void AddBackgroundInsideTable(string url) { sb.Append(""); sb.AppendFormat("", url); @@ -14,14 +15,14 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append("
"); } - protected virtual void AddPosterInsideTable(StringBuilder sb, string url) + protected virtual void AddPosterInsideTable(string url) { sb.Append(""); sb.Append("
"); sb.AppendFormat("", url); } - protected virtual void AddMediaServerUrl(StringBuilder sb, string mediaurl, string url) + protected virtual void AddMediaServerUrl(string mediaurl, string url) { if (url.HasValue()) { @@ -41,14 +42,14 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append(""); } - protected virtual void AddInfoTable(StringBuilder sb) + protected virtual void AddInfoTable() { sb.Append( "
"); sb.Append(""); } - protected virtual void AddTitle(StringBuilder sb, string url, string title) + protected virtual void AddTitle( string url, string title) { sb.Append(""); sb.Append(""); } - protected virtual void AddParagraph(StringBuilder sb, string text) + protected virtual void AddParagraph(string text) { sb.Append(""); sb.Append(""); } - protected virtual void AddTvParagraph(StringBuilder sb, string episodes, string summary) + protected virtual void AddTvParagraph(string episodes, string summary) { sb.Append(""); sb.Append(""); } - protected virtual void AddGenres(StringBuilder sb, string text) + protected virtual void AddGenres(string text) { sb.Append(""); sb.Append("
"); @@ -59,7 +60,7 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append("
"); @@ -68,7 +69,7 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append("
"); @@ -78,7 +79,7 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append("
"); diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 7752d298d..a11a9ff80 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -1,27 +1,22 @@ using System; -using System.Collections; using System.Collections.Generic; -using System.Collections.Immutable; using System.Linq; -using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; -using MailKit; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using MimeKit; -using Ombi.Api.CouchPotato.Models; using Ombi.Api.Lidarr; using Ombi.Api.Lidarr.Models; using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; -using Ombi.Api.TvMaze; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Helpers; using Ombi.Hubs; +using Ombi.I18n.Resources; using Ombi.Notifications; using Ombi.Notifications.Models; using Ombi.Notifications.Templates; @@ -30,7 +25,6 @@ using Ombi.Settings.Settings.Models.External; using Ombi.Settings.Settings.Models.Notifications; using Ombi.Store.Entities; using Ombi.Store.Repository; -using Org.BouncyCastle.Utilities.Collections; using Quartz; using ContentType = Ombi.Store.Entities.ContentType; @@ -39,7 +33,7 @@ namespace Ombi.Schedule.Jobs.Ombi public class NewsletterJob : HtmlTemplateGenerator, INewsletterJob { public NewsletterJob(IPlexContentRepository plex, IEmbyContentRepository emby, IJellyfinContentRepository jellyfin, IRepository addedLog, - IMovieDbApi movieApi, ITvMazeApi tvApi, IEmailProvider email, ISettingsService custom, + IMovieDbApi movieApi, IEmailProvider email, ISettingsService custom, ISettingsService emailSettings, INotificationTemplatesRepository templateRepo, UserManager um, ISettingsService newsletter, ILogger log, ILidarrApi lidarrApi, IExternalRepository albumCache, ISettingsService lidarrSettings, @@ -51,7 +45,6 @@ namespace Ombi.Schedule.Jobs.Ombi _jellyfin = jellyfin; _recentlyAddedLog = addedLog; _movieApi = movieApi; - _tvApi = tvApi; _email = email; _customizationSettings = custom; _templateRepo = templateRepo; @@ -74,12 +67,11 @@ namespace Ombi.Schedule.Jobs.Ombi _refreshMetadata = refreshMetadata; } - private readonly IPlexContentRepository _plex; - private readonly IEmbyContentRepository _emby; - private readonly IJellyfinContentRepository _jellyfin; + private readonly IMediaServerContentRepository _plex; + private readonly IMediaServerContentRepository _emby; + private readonly IMediaServerContentRepository _jellyfin; private readonly IRepository _recentlyAddedLog; private readonly IMovieDbApi _movieApi; - private readonly ITvMazeApi _tvApi; private readonly IEmailProvider _email; private readonly ISettingsService _customizationSettings; private readonly INotificationTemplatesRepository _templateRepo; @@ -122,88 +114,37 @@ namespace Ombi.Schedule.Jobs.Ombi try { - - var customization = await _customizationSettings.GetSettingsAsync(); - // Get the Content - var plexContent = _plex.GetAll().Include(x => x.Episodes).AsNoTracking(); - var embyContent = _emby.GetAll().Include(x => x.Episodes).AsNoTracking(); - var jellyfinContent = _jellyfin.GetAll().Include(x => x.Episodes).AsNoTracking(); - var lidarrContent = _lidarrAlbumRepository.GetAll().AsNoTracking().ToList().Where(x => x.FullyAvailable); - - var addedLog = _recentlyAddedLog.GetAll().ToList(); - - HashSet addedPlexMovieLogIds, addedEmbyMoviesLogIds, addedJellyfinMoviesLogIds; - HashSet addedAlbumLogIds; - GetRecentlyAddedMoviesData(addedLog, out addedPlexMovieLogIds, out addedEmbyMoviesLogIds, out addedJellyfinMoviesLogIds, out addedAlbumLogIds); - - var addedPlexEpisodesLogIds = - addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Episode); - var addedEmbyEpisodesLogIds = - addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Episode); - var addedJellyfinEpisodesLogIds = - addedLog.Where(x => x.Type == RecentlyAddedType.Jellyfin && x.ContentType == ContentType.Episode); - - - // Filter out the ones that we haven't sent yet - var plexContentLocalDataset = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet(); - var embyContentLocalDataset = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet(); - var jellyfinContentLocalDataset = jellyfinContent.Where(x => x.Type == JellyfinMediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet(); - var plexContentMoviesToSend = plexContentLocalDataset.Where(x => !addedPlexMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))).ToHashSet(); - var embyContentMoviesToSend = embyContentLocalDataset.Where(x => !addedEmbyMoviesLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))).ToHashSet(); - var jellyfinContentMoviesToSend = jellyfinContentLocalDataset.Where(x => !addedJellyfinMoviesLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))).ToHashSet(); - var lidarrContentAlbumsToSend = lidarrContent.Where(x => !addedAlbumLogIds.Contains(x.ForeignAlbumId)).ToHashSet(); - _log.LogInformation("Plex Movies to send: {0}", plexContentMoviesToSend.Count()); - _log.LogInformation("Emby Movies to send: {0}", embyContentMoviesToSend.Count()); - _log.LogInformation("Jellyfin Movies to send: {0}", jellyfinContentMoviesToSend.Count()); - _log.LogInformation("Albums to send: {0}", lidarrContentAlbumsToSend.Count()); - - // Find the movies that do not yet have MovieDbIds - var needsMovieDbPlex = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet(); - var needsMovieDbEmby = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet(); - var needsMovieDbJellyfin = jellyfinContent.Where(x => x.Type == JellyfinMediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet(); - var newPlexMovies = await GetMoviesWithoutId(addedPlexMovieLogIds, needsMovieDbPlex); - var newEmbyMovies = await GetMoviesWithoutId(addedEmbyMoviesLogIds, needsMovieDbEmby); - var newJellyfinMovies = await GetMoviesWithoutId(addedJellyfinMoviesLogIds, needsMovieDbJellyfin); - plexContentMoviesToSend = plexContentMoviesToSend.Union(newPlexMovies).ToHashSet(); - embyContentMoviesToSend = embyContentMoviesToSend.Union(newEmbyMovies).ToHashSet(); - jellyfinContentMoviesToSend = jellyfinContentMoviesToSend.Union(newJellyfinMovies).ToHashSet(); - - plexContentMoviesToSend = plexContentMoviesToSend.DistinctBy(x => x.Id).ToHashSet(); - embyContentMoviesToSend = embyContentMoviesToSend.DistinctBy(x => x.Id).ToHashSet(); - jellyfinContentMoviesToSend = jellyfinContentMoviesToSend.DistinctBy(x => x.Id).ToHashSet(); - - var plexEpisodesToSend = - FilterPlexEpisodes(_plex.GetAllEpisodes().Include(x => x.Series).AsNoTracking(), addedPlexEpisodesLogIds); - var embyEpisodesToSend = FilterEmbyEpisodes(_emby.GetAllEpisodes().Include(x => x.Series).AsNoTracking(), - addedEmbyEpisodesLogIds); - var jellyfinEpisodesToSend = FilterJellyfinEpisodes(_jellyfin.GetAllEpisodes().Include(x => x.Series).AsNoTracking(), - addedJellyfinEpisodesLogIds); - - _log.LogInformation("Plex Episodes to send: {0}", plexEpisodesToSend.Count()); - _log.LogInformation("Emby Episodes to send: {0}", embyEpisodesToSend.Count()); - _log.LogInformation("Jellyfin Episodes to send: {0}", jellyfinEpisodesToSend.Count()); var plexSettings = await _plexSettings.GetSettingsAsync(); var embySettings = await _embySettings.GetSettingsAsync(); var jellyfinSettings = await _jellyfinSettings.GetSettingsAsync(); - var body = string.Empty; - if (test) + + var customization = await _customizationSettings.GetSettingsAsync(); + + var moviesContents = new List(); + var seriesContents = new List(); + if (plexSettings.Enable) { - var plexm = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie).OrderByDescending(x => x.AddedAt).Take(10); - var embym = embyContent.Where(x => x.Type == EmbyMediaType.Movie).OrderByDescending(x => x.AddedAt).Take(10); - var jellyfinm = jellyfinContent.Where(x => x.Type == JellyfinMediaType.Movie).OrderByDescending(x => x.AddedAt).Take(10); - var plext = _plex.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).Take(10).ToHashSet(); - var embyt = _emby.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10).ToHashSet(); - var jellyfint = _jellyfin.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10).ToHashSet(); - var lidarr = lidarrContent.OrderByDescending(x => x.AddedAt).Take(10).ToHashSet(); - body = await BuildHtml(plexm, embym, jellyfinm, plext, embyt, jellyfint, lidarr, settings, embySettings, jellyfinSettings, plexSettings); + moviesContents.AddRange(await GetMoviesContent(_plex, test)); + seriesContents.AddRange(GetSeriesContent(_plex, test)); } - else + if (embySettings.Enable) { - body = await BuildHtml(plexContentMoviesToSend.AsQueryable(), embyContentMoviesToSend.AsQueryable(), jellyfinContentMoviesToSend.AsQueryable(), plexEpisodesToSend, embyEpisodesToSend, jellyfinEpisodesToSend, lidarrContentAlbumsToSend, settings, embySettings, jellyfinSettings, plexSettings); - if (body.IsNullOrEmpty()) - { - return; - } + moviesContents.AddRange(await GetMoviesContent(_emby, test)); + seriesContents.AddRange(GetSeriesContent(_emby, test)); + } + if (jellyfinSettings.Enable) + { + moviesContents.AddRange(await GetMoviesContent(_jellyfin, test)); + seriesContents.AddRange(GetSeriesContent(_jellyfin, test)); + } + + var albumsContents = GetMusicContent(_lidarrAlbumRepository, test); + + var body = await BuildHtml(moviesContents, seriesContents, albumsContents, settings); + + if (body.IsNullOrEmpty()) + { + return; } if (!test) @@ -223,7 +164,7 @@ namespace Ombi.Schedule.Jobs.Ombi if (!users.Any()) { return; - } + } var messageContent = ParseTemplate(template, customization); var email = new NewsletterTemplate(); @@ -258,84 +199,8 @@ namespace Ombi.Schedule.Jobs.Ombi // Now add all of this to the Recently Added log var recentlyAddedLog = new HashSet(); - foreach (var p in plexContentMoviesToSend) - { - recentlyAddedLog.Add(new RecentlyAddedLog - { - AddedAt = DateTime.Now, - Type = RecentlyAddedType.Plex, - ContentType = ContentType.Parent, - ContentId = StringHelper.IntParseLinq(p.TheMovieDbId), - }); - - } - - foreach (var p in plexEpisodesToSend) - { - recentlyAddedLog.Add(new RecentlyAddedLog - { - AddedAt = DateTime.Now, - Type = RecentlyAddedType.Plex, - ContentType = ContentType.Episode, - ContentId = StringHelper.IntParseLinq(p.Series.TvDbId), - EpisodeNumber = p.EpisodeNumber, - SeasonNumber = p.SeasonNumber - }); - } - foreach (var e in embyContentMoviesToSend) - { - if (e.Type == EmbyMediaType.Movie) - { - recentlyAddedLog.Add(new RecentlyAddedLog - { - AddedAt = DateTime.Now, - Type = RecentlyAddedType.Emby, - ContentType = ContentType.Parent, - ContentId = StringHelper.IntParseLinq(e.TheMovieDbId), - }); - } - } - - foreach (var p in embyEpisodesToSend) - { - recentlyAddedLog.Add(new RecentlyAddedLog - { - AddedAt = DateTime.Now, - Type = RecentlyAddedType.Emby, - ContentType = ContentType.Episode, - ContentId = StringHelper.IntParseLinq(p.Series.TvDbId), - EpisodeNumber = p.EpisodeNumber, - SeasonNumber = p.SeasonNumber - }); - } - - foreach (var e in jellyfinContentMoviesToSend) - { - if (e.Type == JellyfinMediaType.Movie) - { - recentlyAddedLog.Add(new RecentlyAddedLog - { - AddedAt = DateTime.Now, - Type = RecentlyAddedType.Jellyfin, - ContentType = ContentType.Parent, - ContentId = StringHelper.IntParseLinq(e.TheMovieDbId), - }); - } - } - - foreach (var p in jellyfinEpisodesToSend) - { - recentlyAddedLog.Add(new RecentlyAddedLog - { - AddedAt = DateTime.Now, - Type = RecentlyAddedType.Jellyfin, - ContentType = ContentType.Episode, - ContentId = StringHelper.IntParseLinq(p.Series.TvDbId), - EpisodeNumber = p.EpisodeNumber, - SeasonNumber = p.SeasonNumber - }); - } - + AddToRecentlyAddedLog(moviesContents, recentlyAddedLog); + AddToRecentlyAddedLog(seriesContents, recentlyAddedLog); await _recentlyAddedLog.AddRange(recentlyAddedLog); } else @@ -375,21 +240,118 @@ namespace Ombi.Schedule.Jobs.Ombi .SendAsync(NotificationHub.NotificationEvent, "Newsletter Finished"); } - private void GetRecentlyAddedMoviesData(List addedLog, out HashSet addedPlexMovieLogIds, out HashSet addedEmbyMoviesLogIds, out HashSet addedJellyfinMoviesLogIds, out HashSet addedAlbumLogIds) + private void AddToRecentlyAddedLog(ICollection moviesContents, + HashSet recentlyAddedLog) { - var plexParent = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Parent).ToList(); - addedPlexMovieLogIds = plexParent != null && plexParent.Any() ? (plexParent?.Select(x => x.ContentId)?.ToHashSet() ?? new HashSet()) : new HashSet(); - - var embyParent = addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Parent); - addedEmbyMoviesLogIds = embyParent != null && embyParent.Any() ? (embyParent?.Select(x => x.ContentId)?.ToHashSet() ?? new HashSet()) : new HashSet(); - - var jellyFinParent = addedLog.Where(x => x.Type == RecentlyAddedType.Jellyfin && x.ContentType == ContentType.Parent); - addedJellyfinMoviesLogIds = jellyFinParent != null && jellyFinParent.Any() ? (jellyFinParent?.Select(x => x.ContentId)?.ToHashSet() ?? new HashSet()) : new HashSet(); + foreach (var p in moviesContents) + { + recentlyAddedLog.Add(new RecentlyAddedLog + { + AddedAt = DateTime.Now, + Type = p.RecentlyAddedType, + ContentType = ContentType.Parent, + ContentId = StringHelper.IntParseLinq(p.TheMovieDbId), + }); + } + } + private void AddToRecentlyAddedLog(ICollection episodes, + HashSet recentlyAddedLog) + { + foreach (var p in episodes) + { + recentlyAddedLog.Add(new RecentlyAddedLog + { + AddedAt = DateTime.Now, + Type = p.Series.RecentlyAddedType, + ContentType = ContentType.Episode, + ContentId = StringHelper.IntParseLinq(p.Series.TvDbId), + EpisodeNumber = p.EpisodeNumber, + SeasonNumber = p.SeasonNumber + }); + } + } + private void GetRecentlyAddedMoviesData(List addedLog, out HashSet addedAlbumLogIds) + { var lidarrParent = addedLog.Where(x => x.Type == RecentlyAddedType.Lidarr && x.ContentType == ContentType.Album); addedAlbumLogIds = lidarrParent != null && lidarrParent.Any() ? (lidarrParent?.Select(x => x.AlbumId)?.ToHashSet() ?? new HashSet()) : new HashSet(); } + private async Task> GetMoviesContent(IMediaServerContentRepository repository, bool test) where T : class, IMediaServerContent + { + IQueryable content = repository.GetAll().Include(x => x.Episodes).AsNoTracking().Where(x => x.Type == MediaType.Movie).OrderByDescending(x => x.AddedAt); + var localDataset = content.Where(x => x.Type == MediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet(); + + HashSet moviesToSend; + if (test) + { + moviesToSend = content.Take(10).ToHashSet(); + } + else + { + // Filter out the ones that we haven't sent yet + var parent = _recentlyAddedLog.GetAll().Where(x => x.Type == repository.RecentlyAddedType + && x.ContentType == ContentType.Parent).ToList(); + var addedMovieLogIds = parent != null && parent.Any() ? (parent?.Select(x => x.ContentId)?.ToHashSet() ?? new HashSet()) : new HashSet(); + moviesToSend = localDataset.Where(x => !addedMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))).ToHashSet(); + _log.LogInformation("Movies to send: {0}", moviesToSend.Count()); + + // Find the movies that do not yet have MovieDbIds + var needsMovieDb = content.Where(x => x.Type == MediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet(); + var newMovies = await GetMoviesWithoutId(addedMovieLogIds, needsMovieDb, repository); + moviesToSend = moviesToSend.Union(newMovies).ToHashSet(); + } + + _log.LogInformation("Movies to send: {0}", moviesToSend.Count()); + return moviesToSend.DistinctBy(x => x.Id).ToHashSet(); + } + + private HashSet GetSeriesContent(IMediaServerContentRepository repository, bool test) where T : class, IMediaServerContent + { + var content = repository.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).AsNoTracking(); + + HashSet episodesToSend; + if (test) + { + var count = repository.GetAllEpisodes().Count(); + episodesToSend = content.Take(10).ToHashSet(); + } + else + { + // Filter out the ones that we haven't sent yet + var addedEpisodesLogIds = + _recentlyAddedLog.GetAll().Where(x => x.Type == repository.RecentlyAddedType && x.ContentType == ContentType.Episode); + episodesToSend = + FilterEpisodes(content, addedEpisodesLogIds); + } + + _log.LogInformation("Episodes to send: {0}", episodesToSend.Count()); + return episodesToSend; + + } + private HashSet GetMusicContent(IExternalRepository repository, bool test) + { + + var lidarrContent = repository.GetAll().AsNoTracking().ToList().Where(x => x.FullyAvailable); + + HashSet albumsToSend; + if (test) + { + albumsToSend = lidarrContent.OrderByDescending(x => x.AddedAt).Take(10).ToHashSet(); + } + else + { + // Filter out the ones that we haven't sent yet + var addedLog = _recentlyAddedLog.GetAll().ToList(); + HashSet addedAlbumLogIds; + GetRecentlyAddedMoviesData(addedLog, out addedAlbumLogIds); + albumsToSend = lidarrContent.Where(x => !addedAlbumLogIds.Contains(x.ForeignAlbumId)).ToHashSet(); + } + _log.LogInformation("Albums to send: {0}", albumsToSend.Count()); + return albumsToSend; + + } + public static string GenerateUnsubscribeLink(string applicationUrl, string id) { if (!applicationUrl.HasValue() || !id.HasValue()) @@ -405,49 +367,21 @@ namespace Ombi.Schedule.Jobs.Ombi return b.ToString(); } - private async Task> GetMoviesWithoutId(HashSet addedMovieLogIds, HashSet needsMovieDbPlex) + private async Task> GetMoviesWithoutId(HashSet addedMovieLogIds, HashSet needsMovieDb, IMediaServerContentRepository repository) where T : class, IMediaServerContent { - foreach (var movie in needsMovieDbPlex) + foreach (var movie in needsMovieDb) { var id = await _refreshMetadata.GetTheMovieDbId(false, true, null, movie.ImdbId, movie.Title, true); movie.TheMovieDbId = id.ToString(); } - var result = needsMovieDbPlex.Where(x => x.HasTheMovieDb && !addedMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))); - await UpdateTheMovieDbId(result); + var result = needsMovieDb.Where(x => x.HasTheMovieDb && !addedMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))); + await UpdateTheMovieDbId(result, repository); // Filter them out now return result.ToHashSet(); } - private async Task> GetMoviesWithoutId(HashSet addedMovieLogIds, HashSet needsMovieDbPlex) - { - foreach (var movie in needsMovieDbPlex) - { - var id = await _refreshMetadata.GetTheMovieDbId(false, true, null, movie.ImdbId, movie.Title, true); - movie.TheMovieDbId = id.ToString(); - } - - var result = needsMovieDbPlex.Where(x => x.HasTheMovieDb && !addedMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))); - await UpdateTheMovieDbId(result); - // Filter them out now - return result.ToHashSet(); - } - - private async Task> GetMoviesWithoutId(HashSet addedMovieLogIds, HashSet needsMovieDbJellyfin) - { - foreach (var movie in needsMovieDbJellyfin) - { - var id = await _refreshMetadata.GetTheMovieDbId(false, true, null, movie.ImdbId, movie.Title, true); - movie.TheMovieDbId = id.ToString(); - } - - var result = needsMovieDbJellyfin.Where(x => x.HasTheMovieDb && !addedMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))); - await UpdateTheMovieDbId(result); - // Filter them out now - return result.ToHashSet(); - } - - private async Task UpdateTheMovieDbId(IEnumerable content) + private async Task UpdateTheMovieDbId(IEnumerable content, IMediaServerContentRepository repository) where T : class, IMediaServerContent { foreach (var movie in content) { @@ -455,45 +389,15 @@ namespace Ombi.Schedule.Jobs.Ombi { continue; } - var entity = await _plex.Find(movie.Id); + var entity = await repository.Find(movie.Id); if (entity == null) { return; } entity.TheMovieDbId = movie.TheMovieDbId; - _plex.UpdateWithoutSave(entity); + repository.UpdateWithoutSave(entity); } - await _plex.SaveChangesAsync(); - } - - private async Task UpdateTheMovieDbId(IEnumerable content) - { - foreach (var movie in content) - { - if (!movie.HasTheMovieDb) - { - continue; - } - var entity = await _emby.Find(movie.Id); - entity.TheMovieDbId = movie.TheMovieDbId; - _emby.UpdateWithoutSave(entity); - } - await _plex.SaveChangesAsync(); - } - - private async Task UpdateTheMovieDbId(IEnumerable content) - { - foreach (var movie in content) - { - if (!movie.HasTheMovieDb) - { - continue; - } - var entity = await _jellyfin.Find(movie.Id); - entity.TheMovieDbId = movie.TheMovieDbId; - _jellyfin.UpdateWithoutSave(entity); - } - await _plex.SaveChangesAsync(); + await repository.SaveChangesAsync(); } public async Task Execute(IJobExecutionContext job) @@ -502,43 +406,9 @@ namespace Ombi.Schedule.Jobs.Ombi await Start(newsletterSettings, false); } - private HashSet FilterPlexEpisodes(IEnumerable source, IEnumerable recentlyAdded) + private HashSet FilterEpisodes(IEnumerable source, IEnumerable recentlyAdded) { - var itemsToReturn = new HashSet(); - foreach (var ep in source.Where(x => x.Series.HasTvDb)) - { - var tvDbId = StringHelper.IntParseLinq(ep.Series.TvDbId); - if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber)) - { - continue; - } - - itemsToReturn.Add(ep); - } - - return itemsToReturn; - } - - private HashSet FilterEmbyEpisodes(IEnumerable source, IEnumerable recentlyAdded) - { - var itemsToReturn = new HashSet(); - foreach (var ep in source.Where(x => x.Series.HasTvDb)) - { - var tvDbId = StringHelper.IntParseLinq(ep.Series.TvDbId); - if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber)) - { - continue; - } - - itemsToReturn.Add(ep); - } - - return itemsToReturn; - } - - private HashSet FilterJellyfinEpisodes(IEnumerable source, IEnumerable recentlyAdded) - { - var itemsToReturn = new HashSet(); + var itemsToReturn = new HashSet(); foreach (var ep in source.Where(x => x.Series.HasTvDb)) { var tvDbId = StringHelper.IntParseLinq(ep.Series.TvDbId); @@ -563,40 +433,22 @@ namespace Ombi.Schedule.Jobs.Ombi return resolver.ParseMessage(template, curlys); } - private async Task BuildHtml(IQueryable plexContentToSend, IQueryable embyContentToSend, IQueryable jellyfinContentToSend, - HashSet plexEpisodes, HashSet embyEp, HashSet jellyfinEp, HashSet albums, NewsletterSettings settings, EmbySettings embySettings, JellyfinSettings jellyfinSettings, - PlexSettings plexSettings) + private async Task BuildHtml(ICollection movies, + IEnumerable episodes, HashSet albums, NewsletterSettings settings) { var ombiSettings = await _ombiSettings.GetSettingsAsync(); - var sb = new StringBuilder(); + sb = new StringBuilder(); - var plexMovies = plexContentToSend.Where(x => x.Type == PlexMediaTypeEntity.Movie); - var embyMovies = embyContentToSend.Where(x => x.Type == EmbyMediaType.Movie); - var jellyfinMovies = jellyfinContentToSend.Where(x => x.Type == JellyfinMediaType.Movie); - if ((plexMovies.Any() || embyMovies.Any() || jellyfinMovies.Any()) && !settings.DisableMovies) + if (movies.Any() && !settings.DisableMovies) { - sb.Append("

New Movies



"); + sb.Append($"

{Texts.NewMovies}



"); sb.Append( ""); sb.Append(""); sb.Append(""); @@ -604,30 +456,16 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append("
"); sb.Append(""); sb.Append(""); - if (plexSettings.Enable) - { - await ProcessPlexMovies(plexMovies, sb, ombiSettings.DefaultLanguageCode, plexSettings.Servers.FirstOrDefault().ServerHostname ?? string.Empty); - } - - if (embySettings.Enable) - { - await ProcessEmbyMovies(embyMovies, sb, ombiSettings.DefaultLanguageCode, embySettings.Servers.FirstOrDefault()?.ServerHostname ?? string.Empty); - } - - if (jellyfinSettings.Enable) - { - await ProcessJellyfinMovies(jellyfinMovies, sb, ombiSettings.DefaultLanguageCode, jellyfinSettings.Servers.FirstOrDefault()?.ServerHostname ?? string.Empty); - } - + await ProcessMovies(movies, ombiSettings.DefaultLanguageCode); sb.Append(""); sb.Append("
"); sb.Append("
"); } - if ((plexEpisodes.Any() || embyEp.Any() || jellyfinEp.Any()) && !settings.DisableTv) + if (episodes.Any() && !settings.DisableTv) { - sb.Append("

New TV



"); + sb.Append($"

{Texts.NewTV}



"); sb.Append( ""); sb.Append(""); sb.Append(""); @@ -638,14 +476,14 @@ namespace Ombi.Schedule.Jobs.Ombi if (albums.Any() && !settings.DisableMusic) { - sb.Append("

New Albums



"); + sb.Append($"

{Texts.NewAlbums}



"); sb.Append( "
"); sb.Append(""); sb.Append(""); - if (plexSettings.Enable) - { - await ProcessPlexTv(plexEpisodes, sb, ombiSettings.DefaultLanguageCode, plexSettings.Servers.FirstOrDefault().ServerHostname ?? string.Empty); - } - - if (embySettings.Enable) - { - await ProcessEmbyTv(embyEp, sb, ombiSettings.DefaultLanguageCode, embySettings.Servers.FirstOrDefault()?.ServerHostname ?? string.Empty); - } - - if (jellyfinSettings.Enable) - { - await ProcessJellyfinTv(jellyfinEp, sb, ombiSettings.DefaultLanguageCode, jellyfinSettings.Servers.FirstOrDefault()?.ServerHostname ?? string.Empty); - } - + await ProcessTv(episodes, ombiSettings.DefaultLanguageCode); sb.Append(""); sb.Append("
"); sb.Append("
"); sb.Append(""); sb.Append(""); @@ -656,35 +494,37 @@ namespace Ombi.Schedule.Jobs.Ombi return sb.ToString(); } - private async Task ProcessPlexMovies(IQueryable plexContentToSend, StringBuilder sb, string defaultLanguageCode, string mediaServerUrl) + private async Task ProcessMovies(ICollection plexContentToSend, string defaultLanguageCode) { int count = 0; - var ordered = plexContentToSend.OrderByDescending(x => x.AddedAt); + var ordered = plexContentToSend; foreach (var content in ordered) { int.TryParse(content.TheMovieDbId, out var movieDbId); if (movieDbId <= 0) { + _log.LogWarning($"{content.Title} does not have a TMDB ID, it won't be published."); continue; } var info = await _movieApi.GetMovieInformationWithExtraInfo(movieDbId, defaultLanguageCode); - var mediaurl = PlexHelper.BuildPlexMediaUrl(content.Url, mediaServerUrl); + var mediaurl = content.Url; if (info == null) { + _log.LogWarning($"TMDB does not know movie {content.Title}, it won't be published."); continue; } try { - CreateMovieHtmlContent(sb, info, mediaurl); + CreateMovieHtmlContent(info, mediaurl); count += 1; } catch (Exception e) { - _log.LogError(e, "Error when Processing Plex Movies {0}", info.Title); + _log.LogError(e, "Error when Processing Movies {0}", info.Title); } finally { - EndLoopHtml(sb); + EndLoopHtml(); } if (count == 2) @@ -695,7 +535,7 @@ namespace Ombi.Schedule.Jobs.Ombi } } } - private async Task ProcessAlbums(HashSet albumsToSend, StringBuilder sb) + private async Task ProcessAlbums(HashSet albumsToSend) { var settings = await _lidarrSettings.GetSettingsAsync(); int count = 0; @@ -709,7 +549,7 @@ namespace Ombi.Schedule.Jobs.Ombi } try { - CreateAlbumHtmlContent(sb, info); + CreateAlbumHtmlContent(info); count += 1; } catch (Exception e) @@ -718,7 +558,7 @@ namespace Ombi.Schedule.Jobs.Ombi } finally { - EndLoopHtml(sb); + EndLoopHtml(); } if (count == 2) @@ -730,119 +570,13 @@ namespace Ombi.Schedule.Jobs.Ombi } } - private async Task ProcessEmbyMovies(IQueryable embyContent, StringBuilder sb, string defaultLangaugeCode, string customUrl) + private void CreateMovieHtmlContent(MovieResponseDto info, string mediaurl) { - int count = 0; - var ordered = embyContent.OrderByDescending(x => x.AddedAt); - foreach (var content in ordered) - { - var theMovieDbId = content.TheMovieDbId; - if (!content.TheMovieDbId.HasValue()) - { - var imdbId = content.ImdbId; - var findResult = await _movieApi.Find(imdbId, ExternalSource.imdb_id); - var result = findResult.movie_results?.FirstOrDefault(); - if (result == null) - { - continue; - } + AddBackgroundInsideTable($"https://image.tmdb.org/t/p/w1280/{info.BackdropPath}"); + AddPosterInsideTable($"https://image.tmdb.org/t/p/original{info.PosterPath}"); - theMovieDbId = result.id.ToString(); - } - - var mediaurl = content.Url; - if (customUrl.HasValue()) - { - mediaurl = customUrl; - } - var info = await _movieApi.GetMovieInformationWithExtraInfo(StringHelper.IntParseLinq(theMovieDbId), defaultLangaugeCode); - if (info == null) - { - continue; - } - try - { - CreateMovieHtmlContent(sb, info, mediaurl); - count += 1; - } - catch (Exception e) - { - _log.LogError(e, "Error when processing Emby Movies {0}", info.Title); - } - finally - { - EndLoopHtml(sb); - } - - if (count == 2) - { - count = 0; - sb.Append(""); - sb.Append(""); - } - } - } - - private async Task ProcessJellyfinMovies(IQueryable embyContent, StringBuilder sb, string defaultLangaugeCode, string customUrl) - { - int count = 0; - var ordered = embyContent.OrderByDescending(x => x.AddedAt); - foreach (var content in ordered) - { - var theMovieDbId = content.TheMovieDbId; - if (!content.TheMovieDbId.HasValue()) - { - var imdbId = content.ImdbId; - var findResult = await _movieApi.Find(imdbId, ExternalSource.imdb_id); - var result = findResult.movie_results?.FirstOrDefault(); - if (result == null) - { - continue; - } - - theMovieDbId = result.id.ToString(); - } - - var mediaurl = content.Url; - if (customUrl.HasValue()) - { - mediaurl = customUrl; - } - var info = await _movieApi.GetMovieInformationWithExtraInfo(StringHelper.IntParseLinq(theMovieDbId), defaultLangaugeCode); - if (info == null) - { - continue; - } - try - { - CreateMovieHtmlContent(sb, info, mediaurl); - count += 1; - } - catch (Exception e) - { - _log.LogError(e, "Error when processing Jellyfin Movies {0}", info.Title); - } - finally - { - EndLoopHtml(sb); - } - - if (count == 2) - { - count = 0; - sb.Append(""); - sb.Append(""); - } - } - } - - private void CreateMovieHtmlContent(StringBuilder sb, MovieResponseDto info, string mediaurl) - { - AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w1280/{info.BackdropPath}"); - AddPosterInsideTable(sb, $"https://image.tmdb.org/t/p/original{info.PosterPath}"); - - AddMediaServerUrl(sb, mediaurl, $"https://image.tmdb.org/t/p/original{info.PosterPath}"); - AddInfoTable(sb); + AddMediaServerUrl(mediaurl, $"https://image.tmdb.org/t/p/original{info.PosterPath}"); + AddInfoTable(); var releaseDate = string.Empty; try @@ -856,7 +590,7 @@ namespace Ombi.Schedule.Jobs.Ombi // Swallow, couldn't parse the date } - AddTitle(sb, $"https://www.imdb.com/title/{info.ImdbId}/", $"{info.Title} {releaseDate}"); + AddTitle($"https://www.imdb.com/title/{info.ImdbId}/", $"{info.Title} {releaseDate}"); var summary = info.Overview; if (summary.Length > 280) @@ -864,16 +598,15 @@ namespace Ombi.Schedule.Jobs.Ombi summary = summary.Remove(280); summary = summary + "...

"; } - AddParagraph(sb, summary); + AddParagraph(summary); if (info.Genres.Any()) { - AddGenres(sb, - $"Genres: {string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())}"); + AddGenres($"{Texts.GenresLabel} {string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())}"); } } - private void CreateAlbumHtmlContent(StringBuilder sb, AlbumLookup info) + private void CreateAlbumHtmlContent(AlbumLookup info) { var cover = info.images .FirstOrDefault(x => x.coverType.Equals("cover", StringComparison.InvariantCultureIgnoreCase))?.url; @@ -881,21 +614,21 @@ namespace Ombi.Schedule.Jobs.Ombi { cover = info.remoteCover; } - AddBackgroundInsideTable(sb, cover); + AddBackgroundInsideTable(cover); var disk = info.images .FirstOrDefault(x => x.coverType.Equals("disc", StringComparison.InvariantCultureIgnoreCase))?.url; if (disk.IsNullOrEmpty()) { disk = info.remoteCover; } - AddPosterInsideTable(sb, disk); + AddPosterInsideTable(disk); - AddMediaServerUrl(sb, string.Empty, string.Empty); - AddInfoTable(sb); + AddMediaServerUrl(string.Empty, string.Empty); + AddInfoTable(); var releaseDate = $"({info.releaseDate.Year})"; - AddTitle(sb, string.Empty, $"{info.title} {releaseDate}"); + AddTitle(string.Empty, $"{info.title} {releaseDate}"); var summary = info.artist?.artistName ?? string.Empty; if (summary.Length > 280) @@ -903,29 +636,28 @@ namespace Ombi.Schedule.Jobs.Ombi summary = summary.Remove(280); summary = summary + "...

"; } - AddParagraph(sb, summary); + AddParagraph(summary); - AddGenres(sb, $"Type: {info.albumType}"); + AddGenres($"{Texts.AlbumTypeLabel} {info.albumType}"); } - private async Task ProcessPlexTv(HashSet plexContent, StringBuilder sb, string languageCode, string serverHostname) + private async Task ProcessTv(IEnumerable episodes, string languageCode) { - var series = new List(); - foreach (var plexEpisode in plexContent) + var series = new List(); + foreach (var episode in episodes) { - var alreadyAdded = series.FirstOrDefault(x => x.Key == plexEpisode.Series.Key); - if (alreadyAdded != null) + var existingSeries = episode.SeriesIsIn(series); + if (existingSeries != null) { - var episodeExists = alreadyAdded.Episodes.Any(x => x.Key == plexEpisode.Key); - if (!episodeExists) + if (!episode.IsIn(existingSeries)) { - alreadyAdded.Episodes.Add(plexEpisode); + existingSeries.Episodes.Add(episode); } } else { - plexEpisode.Series.Episodes = new List { plexEpisode }; - series.Add(plexEpisode.Series); + episode.Series.Episodes = new List { episode }; + series.Add(episode.Series); } } @@ -942,6 +674,8 @@ namespace Ombi.Schedule.Jobs.Ombi var externals = await _movieApi.GetTvExternals(movieId); if (externals == null || externals.tvdb_id <= 0) { + // needed later for recently added log + _log.LogWarning($"{t.Title} has no TVDB ID, it won't be published."); continue; } t.TvDbId = externals.tvdb_id.ToString(); @@ -960,59 +694,40 @@ namespace Ombi.Schedule.Jobs.Ombi } - int.TryParse(t.TvDbId, out var tvdbId); - var info = await _tvApi.ShowLookupByTheTvDbId(tvdbId); - if (info == null) - { - continue; - } - try { - var banner = info.image?.original; - if (!string.IsNullOrEmpty(banner)) + var tvInfo = await _movieApi.GetTVInfo(t.TheMovieDbId, languageCode); + if (tvInfo == null) { - banner = banner.ToHttpsUrl(); // Always use the Https banners + _log.LogWarning($"TMDB does not know series {t.Title}, it won't be published."); + continue; } - var tvInfo = await _movieApi.GetTVInfo(t.TheMovieDbId, languageCode); - if (tvInfo != null && tvInfo.backdrop_path.HasValue()) + + if (tvInfo.backdrop_path.HasValue()) { - AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w500{tvInfo.backdrop_path}"); + AddBackgroundInsideTable($"https://image.tmdb.org/t/p/w500{tvInfo.backdrop_path}"); } else { - AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w1280/"); + AddBackgroundInsideTable($"https://image.tmdb.org/t/p/w1280/"); } - AddPosterInsideTable(sb, banner); - AddMediaServerUrl(sb, PlexHelper.BuildPlexMediaUrl(t.Url, serverHostname), banner); - AddInfoTable(sb); - AddTvTitle(sb, info, tvInfo); - - // Group by the season number - var results = t.Episodes.GroupBy(p => p.SeasonNumber, - (key, g) => new - { - SeasonNumber = key, - Episodes = g.ToList(), - EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date).FirstOrDefault() - } - ); - - // Group the episodes - var finalsb = new StringBuilder(); - foreach (var epInformation in results.OrderBy(x => x.SeasonNumber)) + var banner = tvInfo.poster_path; + if (!string.IsNullOrEmpty(banner)) { - var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); - var episodeString = StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber)); - var episodeAirDate = epInformation.EpisodeAirDate; - finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString} {episodeAirDate}"); - finalsb.Append("
"); - } + banner = $"https://image.tmdb.org/t/p/w300/{banner?.TrimStart('/') ?? string.Empty}"; + }; + AddPosterInsideTable(banner); + AddMediaServerUrl(t.Url, banner); - AddTvEpisodesSummaryGenres(sb, finalsb.ToString(), tvInfo); + AddInfoTable(); + + AddTvTitle(tvInfo); + + var tvEpisodesString = GetTvEpisodesString(tvInfo, t.Episodes); + AddTvEpisodesSummaryGenres(tvEpisodesString, tvInfo); } catch (Exception e) @@ -1021,7 +736,7 @@ namespace Ombi.Schedule.Jobs.Ombi } finally { - EndLoopHtml(sb); + EndLoopHtml(); count += 1; } @@ -1034,229 +749,59 @@ namespace Ombi.Schedule.Jobs.Ombi } } - - - private async Task ProcessEmbyTv(HashSet embyContent, StringBuilder sb, string languageCode, string serverUrl) + private string GetTvEpisodesString(TvInfo tvInfo, ICollection episodes) { - var series = new List(); - foreach (var episode in embyContent) + if (episodes.Count >= tvInfo.number_of_episodes) { - var alreadyAdded = series.FirstOrDefault(x => x.EmbyId == episode.Series.EmbyId); - if (alreadyAdded != null) + // do not list individual episodes when the series is complete + return string.Empty; + } + + var sb = new StringBuilder(); + // Group by the season number + var seasons = episodes.GroupBy(p => p.SeasonNumber, + (key, g) => new { - alreadyAdded.Episodes.Add(episode); + SeasonNumber = key, + Episodes = g.ToList(), + Header = tvInfo?.seasons?.Where(x => x.season_number == key).FirstOrDefault(), + } + ); + // Group the episodes + foreach (var season in seasons.OrderBy(x => x.SeasonNumber)) + { + string episodeList; + if (season.Episodes.Count >= season.Header.episode_count) + { + // do not list individual episodes when the season is complete + episodeList = string.Empty; } else { - episode.Series.Episodes = new List - { - episode - }; - series.Add(episode.Series); - } - } - - int count = 0; - var orderedTv = series.OrderByDescending(x => x.AddedAt); - foreach (var t in orderedTv) - { - if (!t.TvDbId.HasValue()) - { - continue; - } - - int.TryParse(t.TvDbId, out var tvdbId); - var info = await _tvApi.ShowLookupByTheTvDbId(tvdbId); - if (info == null) - { - continue; - } - - try - { - var banner = info.image?.original; - if (!string.IsNullOrEmpty(banner)) - { - banner = banner.ToHttpsUrl(); // Always use the Https banners - } - - var tvInfo = await _movieApi.GetTVInfo(t.TheMovieDbId, languageCode); - if (tvInfo != null && tvInfo.backdrop_path.HasValue()) - { - - AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w500{tvInfo.backdrop_path}"); - } - else - { - AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w1280/"); - } - AddPosterInsideTable(sb, banner); - AddMediaServerUrl(sb, serverUrl.HasValue() ? serverUrl : t.Url, banner); - AddInfoTable(sb); - - AddTvTitle(sb, info, tvInfo); - - // Group by the season number - var results = t.Episodes?.GroupBy(p => p.SeasonNumber, - (key, g) => new - { - SeasonNumber = key, - Episodes = g.ToList(), - EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date).FirstOrDefault() - } - ); - - // Group the episodes - var finalsb = new StringBuilder(); - foreach (var epInformation in results.OrderBy(x => x.SeasonNumber)) - { - var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); - var episodeString = StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber)); - var episodeAirDate = epInformation.EpisodeAirDate; - finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString} {episodeAirDate}"); - finalsb.Append("
"); - } - - AddTvEpisodesSummaryGenres(sb, finalsb.ToString(), tvInfo); - - } - catch (Exception e) - { - _log.LogError(e, "Error when processing Emby TV {0}", t.Title); - } - finally - { - EndLoopHtml(sb); - count += 1; - } - - if (count == 2) - { - count = 0; - sb.Append("
"); - sb.Append(""); + var orderedEpisodes = season.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); + episodeList = $"{Texts.EpisodesLabel} {StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber))}"; } + var episodeAirDate = season.Header.air_date; + sb.Append($"{Texts.SeasonLabel} {season.SeasonNumber} - {episodeList} {episodeAirDate}"); + sb.Append("
"); } + return sb.ToString(); } - - private async Task ProcessJellyfinTv(HashSet jellyfinContent, StringBuilder sb, string languageCode, string serverUrl) - { - var series = new List(); - foreach (var episode in jellyfinContent) - { - var alreadyAdded = series.FirstOrDefault(x => x.JellyfinId == episode.Series.JellyfinId); - if (alreadyAdded != null) - { - alreadyAdded.Episodes.Add(episode); - } - else - { - episode.Series.Episodes = new List - { - episode - }; - series.Add(episode.Series); - } - } - - int count = 0; - var orderedTv = series.OrderByDescending(x => x.AddedAt); - foreach (var t in orderedTv) - { - if (!t.TvDbId.HasValue()) - { - continue; - } - - int.TryParse(t.TvDbId, out var tvdbId); - var info = await _tvApi.ShowLookupByTheTvDbId(tvdbId); - if (info == null) - { - continue; - } - - try - { - var banner = info.image?.original; - if (!string.IsNullOrEmpty(banner)) - { - banner = banner.ToHttpsUrl(); // Always use the Https banners - } - - var tvInfo = await _movieApi.GetTVInfo(t.TheMovieDbId, languageCode); - if (tvInfo != null && tvInfo.backdrop_path.HasValue()) - { - - AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w500{tvInfo.backdrop_path}"); - } - else - { - AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w1280/"); - } - AddPosterInsideTable(sb, banner); - AddMediaServerUrl(sb, serverUrl.HasValue() ? serverUrl : t.Url, banner); - AddInfoTable(sb); - - AddTvTitle(sb, info, tvInfo); - - // Group by the season number - var results = t.Episodes?.GroupBy(p => p.SeasonNumber, - (key, g) => new - { - SeasonNumber = key, - Episodes = g.ToList(), - EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date).FirstOrDefault() - } - ); - - // Group the episodes - var finalsb = new StringBuilder(); - foreach (var epInformation in results.OrderBy(x => x.SeasonNumber)) - { - var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); - var episodeString = StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber)); - var episodeAirDate = epInformation.EpisodeAirDate; - finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString} {episodeAirDate}"); - finalsb.Append("
"); - } - - AddTvEpisodesSummaryGenres(sb, finalsb.ToString(), tvInfo); - - } - catch (Exception e) - { - _log.LogError(e, "Error when processing Jellyfin TV {0}", t.Title); - } - finally - { - EndLoopHtml(sb); - count += 1; - } - - if (count == 2) - { - count = 0; - sb.Append("
"); - sb.Append(""); - } - } - } - - private void AddTvTitle(StringBuilder sb, Api.TvMaze.Models.TvMazeShow info, TvInfo tvInfo) + private void AddTvTitle(TvInfo tvInfo) { var title = ""; - if (!String.IsNullOrEmpty(info.premiered) && info.premiered.Length > 4) + if (!String.IsNullOrEmpty(tvInfo.first_air_date) && tvInfo.first_air_date.Length > 4) { - title = $"{tvInfo.name} ({info.premiered.Remove(4)})"; + title = $"{tvInfo.name} ({tvInfo.first_air_date.Remove(4)})"; } else { title = $"{tvInfo.name}"; } - AddTitle(sb, $"https://www.imdb.com/title/{info.externals.imdb}/", title); + AddTitle($"https://www.themoviedb.org/tv/{tvInfo.id}/", title); } - private void AddTvEpisodesSummaryGenres(StringBuilder sb, string episodes, TvInfo tvInfo) + private void AddTvEpisodesSummaryGenres(string episodes, TvInfo tvInfo) { var summary = tvInfo.overview; if (summary.Length > 280) @@ -1264,15 +809,15 @@ namespace Ombi.Schedule.Jobs.Ombi summary = summary.Remove(280); summary = summary + "...

"; } - AddTvParagraph(sb, episodes, summary); + AddTvParagraph(episodes, summary); if (tvInfo.genres.Any()) { - AddGenres(sb, $"Genres: {string.Join(", ", tvInfo.genres.Select(x => x.name.ToString()).ToArray())}"); + AddGenres($"{Texts.GenresLabel} {string.Join(", ", tvInfo.genres.Select(x => x.name.ToString()).ToArray())}"); } } - private void EndLoopHtml(StringBuilder sb) + private void EndLoopHtml() { //NOTE: BR have to be in TD's as per html spec or it will be put outside of the table... //Source: http://stackoverflow.com/questions/6588638/phantom-br-tag-rendered-by-browsers-prior-to-table-tag @@ -1299,7 +844,7 @@ namespace Ombi.Schedule.Jobs.Ombi return false; } } - if (string.IsNullOrEmpty(settings.Host) || string.IsNullOrEmpty(settings.AdminEmail) || string.IsNullOrEmpty(settings.Port.ToString())) + if (string.IsNullOrEmpty(settings.Host) || string.IsNullOrEmpty(settings.Port.ToString())) { return false; } diff --git a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs index a24d07da0..64abb2aac 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs @@ -7,6 +7,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Ombi.Api.Emby; using Ombi.Api.Jellyfin; +using Ombi.Api.Plex; using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; using Ombi.Api.TvMaze; @@ -30,7 +31,8 @@ namespace Ombi.Schedule.Jobs.Ombi IMovieDbApi movieApi, ISettingsService embySettings, IEmbyApiFactory embyApi, ISettingsService jellyfinSettings, IJellyfinApiFactory jellyfinApi, - IHubContext notification, IMediaCacheService mediaCacheService) + IHubContext notification, IMediaCacheService mediaCacheService, + IPlexApi plexApi) { _plexRepo = plexRepo; _embyRepo = embyRepo; @@ -45,6 +47,7 @@ namespace Ombi.Schedule.Jobs.Ombi _jellyfinApiFactory = jellyfinApi; _notification = notification; _mediaCacheService = mediaCacheService; + _plexApi = plexApi; } private readonly IPlexContentRepository _plexRepo; @@ -60,6 +63,7 @@ namespace Ombi.Schedule.Jobs.Ombi private readonly IJellyfinApiFactory _jellyfinApiFactory; private readonly IHubContext _notification; private readonly IMediaCacheService _mediaCacheService; + private readonly IPlexApi _plexApi; private IEmbyApi EmbyApi { get; set; } private IJellyfinApi JellyfinApi { get; set; } @@ -75,7 +79,7 @@ namespace Ombi.Schedule.Jobs.Ombi var settings = await _plexSettings.GetSettingsAsync(); if (settings.Enable) { - await StartPlex(); + await StartPlex(settings); await OmbiQuartz.TriggerJob(nameof(IPlexAvailabilityChecker), "Plex"); } @@ -112,16 +116,16 @@ namespace Ombi.Schedule.Jobs.Ombi .SendAsync(NotificationHub.NotificationEvent, "Metadata Refresh Finished"); } - private async Task StartPlex() + private async Task StartPlex(PlexSettings settings) { // Ensure we check that we have not linked this item to a request var allMovies = await _plexRepo.GetAll().Where(x => - x.Type == PlexMediaTypeEntity.Movie && x.RequestId == null && (x.TheMovieDbId == null || x.ImdbId == null)).ToListAsync(); - await StartPlexMovies(allMovies); + x.Type == MediaType.Movie && x.RequestId == null && ((x.TheMovieDbId == null || x.TheMovieDbId == string.Empty ) || (x.ImdbId == null || x.ImdbId == string.Empty))).ToListAsync(); + await StartPlexMovies(allMovies, settings); // Now Tv var allTv = await _plexRepo.GetAll().Where(x => - x.Type == PlexMediaTypeEntity.Show && x.RequestId == null && (x.TheMovieDbId == null || x.ImdbId == null || x.TvDbId == null)).ToListAsync(); + x.Type == MediaType.Series && x.RequestId == null && (x.TheMovieDbId == null || x.ImdbId == null || x.TvDbId == null)).ToListAsync(); await StartPlexTv(allTv); } @@ -178,7 +182,7 @@ namespace Ombi.Schedule.Jobs.Ombi private async Task StartEmbyTv() { var allTv = await _embyRepo.GetAll().Where(x => - x.Type == EmbyMediaType.Series && (x.TheMovieDbId == null || x.ImdbId == null || x.TvDbId == null)).ToListAsync(); + x.Type == MediaType.Series && (x.TheMovieDbId == null || x.ImdbId == null || x.TvDbId == null)).ToListAsync(); foreach (var show in allTv) { @@ -213,7 +217,7 @@ namespace Ombi.Schedule.Jobs.Ombi private async Task StartJellyfinTv() { var allTv = await _jellyfinRepo.GetAll().Where(x => - x.Type == JellyfinMediaType.Series && (x.TheMovieDbId == null || x.ImdbId == null || x.TvDbId == null)).ToListAsync(); + x.Type == MediaType.Series && (x.TheMovieDbId == null || x.ImdbId == null || x.TvDbId == null)).ToListAsync(); foreach (var show in allTv) { @@ -245,7 +249,7 @@ namespace Ombi.Schedule.Jobs.Ombi } } - private async Task StartPlexMovies(List allMovies) + private async Task StartPlexMovies(List allMovies, PlexSettings settings) { foreach (var movie in allMovies) { @@ -261,14 +265,58 @@ namespace Ombi.Schedule.Jobs.Ombi if (!hasImdb) { var imdbId = await GetImdbId(hasTheMovieDb, false, movie.Title, movie.TheMovieDbId, string.Empty, RequestType.Movie); - movie.ImdbId = imdbId; - _plexRepo.UpdateWithoutSave(movie); + if (imdbId.HasValue()) + { + movie.ImdbId = imdbId; + hasImdb = true; + _plexRepo.UpdateWithoutSave(movie); + } } if (!hasTheMovieDb) { var id = await GetTheMovieDbId(false, hasImdb, string.Empty, movie.ImdbId, movie.Title, true); - movie.TheMovieDbId = id; - _plexRepo.UpdateWithoutSave(movie); + if (id.HasValue()) + { + movie.TheMovieDbId = id; + hasTheMovieDb = true; + _plexRepo.UpdateWithoutSave(movie); + } + } + if (!hasTheMovieDb || !hasImdb) + { + // Check to see if the Plex item has anything + if (!settings.Servers.Any()) + { + continue; + } + var servers = settings.Servers[0]; + var metaData = await _plexApi.GetMetadata(servers.PlexAuthToken, settings.Servers[0].FullUri, movie.Key); + var guids = new List(); + + var meta = metaData.MediaContainer.Metadata.FirstOrDefault(); + guids.Add(meta.guid); + if (meta.Guid != null) + { + foreach (var g in meta.Guid) + { + guids.Add(g.Id); + } + } + + var providerIds = PlexHelper.GetProviderIdsFromMetadata(guids.ToArray()); + if (providerIds.Any()) + { + if (providerIds.TheMovieDb.HasValue() && !hasTheMovieDb) + { + movie.TheMovieDbId = providerIds.TheMovieDb; + _plexRepo.UpdateWithoutSave(movie); + } + if (providerIds.ImdbId.HasValue() && !hasImdb) + { + movie.ImdbId = providerIds.ImdbId; + _plexRepo.UpdateWithoutSave(movie); + } + } } await _plexRepo.SaveChangesAsync(); @@ -278,7 +326,7 @@ namespace Ombi.Schedule.Jobs.Ombi private async Task StartEmbyMovies(EmbySettings settings) { var allMovies = await _embyRepo.GetAll().Where(x => - x.Type == EmbyMediaType.Movie && (x.TheMovieDbId == null || x.ImdbId == null)).ToListAsync(); + x.Type == MediaType.Movie && (x.TheMovieDbId == null || x.ImdbId == null)).ToListAsync(); foreach (var movie in allMovies) { movie.ImdbId.HasValue(); @@ -333,7 +381,7 @@ namespace Ombi.Schedule.Jobs.Ombi private async Task StartJellyfinMovies(JellyfinSettings settings) { var allMovies = await _jellyfinRepo.GetAll().Where(x => - x.Type == JellyfinMediaType.Movie && (x.TheMovieDbId == null || x.ImdbId == null)).ToListAsync(); + x.Type == MediaType.Movie && (x.TheMovieDbId == null || x.ImdbId == null)).ToListAsync(); foreach (var movie in allMovies) { movie.ImdbId.HasValue(); @@ -447,17 +495,20 @@ namespace Ombi.Schedule.Jobs.Ombi default: break; } - + } } if (hasTvDbId && type == RequestType.TvShow) { _log.LogInformation("The show {0} has tvdbid but not ImdbId, searching for ImdbId", title); - if (int.TryParse(tvDbId, out var id)) + + var result = await _movieApi.Find(tvDbId.ToString(), ExternalSource.tvdb_id); + var movieDbId = result.tv_results.FirstOrDefault()?.id ?? 0; + if (movieDbId != 0) { - var result = await _tvApi.ShowLookupByTheTvDbId(id); - return result?.externals?.imdb; + var externalsResult = await _movieApi.GetTvExternals(movieDbId); + return externalsResult.imdb_id; } } return string.Empty; diff --git a/src/Ombi.Schedule/Jobs/Ombi/ResendFailedRequests.cs b/src/Ombi.Schedule/Jobs/Ombi/ResendFailedRequests.cs index 3a9a75835..e0df3752c 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/ResendFailedRequests.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/ResendFailedRequests.cs @@ -49,7 +49,9 @@ namespace Ombi.Schedule.Jobs.Ombi await _requestQueue.SaveChangesAsync(); continue; } - var result = await _movieSender.Send(movieRequest); + + // TODO probably need to add something to the request queue to better idenitfy if it's a 4k request + var result = await _movieSender.Send(movieRequest, movieRequest.Approved4K); if (result.Success) { request.Completed = DateTime.UtcNow; diff --git a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexWatchlistImport.cs b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexWatchlistImport.cs new file mode 100644 index 000000000..2dd6d46e4 --- /dev/null +++ b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexWatchlistImport.cs @@ -0,0 +1,6 @@ +namespace Ombi.Schedule.Jobs.Plex +{ + public interface IPlexWatchlistImport : IBaseJob + { + } +} \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Plex/Models/ProcessedContent.cs b/src/Ombi.Schedule/Jobs/Plex/Models/ProcessedContent.cs index fc46e88b7..84748c1f7 100644 --- a/src/Ombi.Schedule/Jobs/Plex/Models/ProcessedContent.cs +++ b/src/Ombi.Schedule/Jobs/Plex/Models/ProcessedContent.cs @@ -5,7 +5,7 @@ namespace Ombi.Schedule.Jobs.Plex.Models { public class ProcessedContent { - public IEnumerable Content { get; set; } + public IEnumerable Content { get; set; } public IEnumerable Episodes { get; set; } public bool HasProcessedContent => Content?.Any() ?? false; diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs index 7a05f794b..e686c6dee 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs @@ -6,10 +6,12 @@ using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Ombi.Core; +using Ombi.Core.Services; using Ombi.Helpers; using Ombi.Hubs; using Ombi.Notifications.Models; using Ombi.Schedule.Jobs.Plex.Models; +using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; @@ -21,7 +23,7 @@ namespace Ombi.Schedule.Jobs.Plex public class PlexAvailabilityChecker : IPlexAvailabilityChecker { public PlexAvailabilityChecker(IPlexContentRepository repo, ITvRequestRepository tvRequest, IMovieRequestRepository movies, - INotificationHelper notification, ILogger log, IHubContext hub) + INotificationHelper notification, ILogger log, IHubContext hub, IFeatureService featureService) { _tvRepo = tvRequest; _repo = repo; @@ -29,6 +31,7 @@ namespace Ombi.Schedule.Jobs.Plex _notificationService = notification; _log = log; _notification = hub; + _featureService = featureService; } private readonly ITvRequestRepository _tvRepo; @@ -37,6 +40,7 @@ namespace Ombi.Schedule.Jobs.Plex private readonly INotificationHelper _notificationService; private readonly ILogger _log; private readonly IHubContext _notification; + private readonly IFeatureService _featureService; public async Task Execute(IJobExecutionContext job) { @@ -86,7 +90,7 @@ namespace Ombi.Schedule.Jobs.Plex var tvDbId = child.ParentRequest.TvDbId; var imdbId = child.ParentRequest.ImdbId; - IQueryable seriesEpisodes = null; + IQueryable seriesEpisodes = null; if (useImdb) { seriesEpisodes = plexEpisodes.Where(x => x.Series.ImdbId == imdbId.ToString()); @@ -105,8 +109,7 @@ namespace Ombi.Schedule.Jobs.Plex { // Let's try and match the series by name seriesEpisodes = plexEpisodes.Where(x => - x.Series.Title == child.Title && - x.Series.ReleaseYear == child.ParentRequest.ReleaseDate.Year.ToString()); + x.Series.Title == child.Title); } @@ -180,17 +183,14 @@ namespace Ombi.Schedule.Jobs.Plex private async Task ProcessMovies() { + var feature4kEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests); // Get all non available - var movies = _movieRepo.GetAll().Include(x => x.RequestedUser).Where(x => !x.Available); + var movies = _movieRepo.GetAll().Include(x => x.RequestedUser).Where(x => !x.Available || (!x.Available4K && x.Has4KRequest)); var itemsForAvailbility = new List(); foreach (var movie in movies) { - if (movie.Available) - { - return; - } - + var has4kRequest = movie.Has4KRequest; PlexServerContent item = null; if (movie.ImdbId.HasValue()) { @@ -209,23 +209,49 @@ namespace Ombi.Schedule.Jobs.Plex continue; } - _log.LogInformation("[PAC] - Movie request {0} is now available, sending notification", $"{movie.Title} - {movie.Id}"); - movie.Available = true; - movie.MarkedAsAvailable = DateTime.UtcNow; - itemsForAvailbility.Add(new AvailabilityModel + _log.LogInformation($"[PAC] - Movie request {movie.Title} - {movie.Id} is now available, sending notification"); + + var notify = false; + + if (has4kRequest && item.Has4K && !movie.Available4K && feature4kEnabled) { - Id = movie.Id, - RequestedUser = movie.RequestedUser != null ? movie.RequestedUser.Email : string.Empty - }); + movie.Available4K = true; + movie.Approved4K = true; + movie.MarkedAsAvailable4K = DateTime.Now; + await _movieRepo.SaveChangesAsync(); + notify = true; + } + + if (!feature4kEnabled && !movie.Available) + { + movie.Available = true; + movie.MarkedAsAvailable = DateTime.Now; + await _movieRepo.SaveChangesAsync(); + notify = true; + } + + // If we have a non-4k versison then mark as available + if (item.Quality != null && !movie.Available) + { + movie.Available = true; + movie.Approved = true; + movie.MarkedAsAvailable = DateTime.Now; + await _movieRepo.SaveChangesAsync(); + notify = true; + } + + if (notify) + { + itemsForAvailbility.Add(new AvailabilityModel + { + Id = movie.Id, + RequestedUser = movie.RequestedUser != null ? movie.RequestedUser.Email : string.Empty + }); + } } - if (itemsForAvailbility.Any()) + foreach (var i in itemsForAvailbility.DistinctBy(x => x.Id)) { - await _movieRepo.SaveChangesAsync(); - } - foreach (var i in itemsForAvailbility) - { - await _notificationService.Notify(new NotificationOptions { DateTime = DateTime.Now, @@ -235,8 +261,6 @@ namespace Ombi.Schedule.Jobs.Plex Recipient = i.RequestedUser }); } - - //await _repo.SaveChangesAsync(); } private bool _disposed; diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index 3289c5a24..9c5a651e2 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -167,7 +167,7 @@ namespace Ombi.Schedule.Jobs.Plex private async Task ProcessServer(PlexServers servers, bool recentlyAddedSearch) { var retVal = new ProcessedContent(); - var contentProcessed = new Dictionary(); + var contentProcessed = new Dictionary(); var episodesProcessed = new List(); Logger.LogDebug("Getting all content from server {0}", servers.Name); var allContent = await GetAllContent(servers, recentlyAddedSearch); @@ -226,7 +226,7 @@ namespace Ombi.Schedule.Jobs.Plex await Repo.SaveChangesAsync(); if (content.Metadata != null) { - var episodesAdded = await EpisodeSync.ProcessEpsiodes(content.Metadata, allEps); + var episodesAdded = await EpisodeSync.ProcessEpsiodes(content.Metadata, (IQueryable)allEps); episodesProcessed.AddRange(episodesAdded.Select(x => x.Id)); } } @@ -290,10 +290,10 @@ namespace Ombi.Schedule.Jobs.Plex } public async Task MovieLoop(PlexServers servers, Mediacontainer content, HashSet contentToAdd, - Dictionary contentProcessed) + Dictionary contentProcessed) { Logger.LogDebug("Processing Movies"); - foreach (var movie in content?.Metadata ?? new Metadata[] { }) + foreach (var movie in content?.Metadata ?? Array.Empty()) { // Let's check if we have this movie @@ -301,20 +301,50 @@ namespace Ombi.Schedule.Jobs.Plex { var existing = await Repo.GetFirstContentByCustom(x => x.Title == movie.title && x.ReleaseYear == movie.year.ToString() - && x.Type == PlexMediaTypeEntity.Movie); - // The rating key keeps changing - //var existing = await Repo.GetByKey(movie.ratingKey); + && x.Type == MediaType.Movie); if (existing != null) { - Logger.LogDebug("We already have movie {0}", movie.title); + // We need to see if this is a different quality, + // We want to know if this is a 4k content for example + var foundQualities = movie.Media?.Select(x => x.videoResolution); + var qualitySaved = false; + foreach (var quality in foundQualities) + { + if (qualitySaved) + { + break; + } + if (quality.Equals(existing.Quality)) + { + // We got it + continue; + } + + // We don't have this quality + if (quality.Equals("4k", StringComparison.InvariantCultureIgnoreCase)) + { + Logger.LogDebug($"We already have movie {movie.title}, But found a 4K version!"); + existing.Has4K = true; + await Repo.Update(existing); + } + else + { + qualitySaved = true; + existing.Quality = quality; + await Repo.Update(existing); + } + } + + + Logger.LogDebug($"We already have movie {movie.title}"); continue; } - var hasSameKey = await Repo.GetByKey(movie.ratingKey); - if (hasSameKey != null) - { - await Repo.Delete(hasSameKey); - } + //var hasSameKey = await Repo.GetByKey(movie.ratingKey); + //if (hasSameKey != null) + //{ + // await Repo.Delete(hasSameKey); + //} Logger.LogDebug("Adding movie {0}", movie.title); var guids = new List(); @@ -342,18 +372,34 @@ namespace Ombi.Schedule.Jobs.Plex } } + if (!guids.Any()) + { + Logger.LogWarning($"Movie {movie.title} has no relevant metadata. Skipping."); + continue; + } var providerIds = PlexHelper.GetProviderIdsFromMetadata(guids.ToArray()); + if (!providerIds.Any()) + { + Logger.LogWarning($"Movie {movie.title} has no External Ids in Plex (ImdbId, TheMovieDbId). Skipping."); + continue; + } + + var qualities = movie?.Media?.Select(x => x?.videoResolution ?? string.Empty) ?? Enumerable.Empty(); + var is4k = qualities != null && qualities.Any(x => x.Equals("4k", StringComparison.InvariantCultureIgnoreCase)); + var selectedQuality = is4k ? null : qualities?.OrderBy(x => x)?.FirstOrDefault() ?? string.Empty; + var item = new PlexServerContent { AddedAt = DateTime.Now, Key = movie.ratingKey, ReleaseYear = movie.year.ToString(), - Type = PlexMediaTypeEntity.Movie, + Type = MediaType.Movie, Title = movie.title, - Url = PlexHelper.GetPlexMediaUrl(servers.MachineIdentifier, movie.ratingKey), + Url = PlexHelper.GetPlexMediaUrl(servers.MachineIdentifier, movie.ratingKey, servers.ServerHostname), Seasons = new List(), - Quality = movie.Media?.FirstOrDefault()?.videoResolution ?? string.Empty + Quality = selectedQuality, + Has4K = is4k, }; if (providerIds.ImdbId.HasValue()) { @@ -391,7 +437,7 @@ namespace Ombi.Schedule.Jobs.Plex } } - private async Task ProcessTvShow(PlexServers servers, Metadata show, HashSet contentToAdd, Dictionary contentProcessed) + private async Task ProcessTvShow(PlexServers servers, Metadata show, HashSet contentToAdd, Dictionary contentProcessed) { var seasonList = await PlexApi.GetSeasons(servers.PlexAuthToken, servers.FullUri, show.ratingKey); @@ -411,7 +457,7 @@ namespace Ombi.Schedule.Jobs.Plex // Let's try and match var existingContent = await Repo.GetFirstContentByCustom(x => x.Title == show.title && x.ReleaseYear == show.year.ToString() - && x.Type == PlexMediaTypeEntity.Show); + && x.Type == MediaType.Series); // Just double check the rating key, since this is our unique constraint var existingKey = await Repo.GetByKey(show.ratingKey); @@ -463,7 +509,7 @@ namespace Ombi.Schedule.Jobs.Plex Repo.DeleteWithoutSave(existingContent); // Because we have changed the rating key, we need to change all children too - var episodeToChange = Repo.GetAllEpisodes().Where(x => x.GrandparentKey == oldKey); + var episodeToChange = Repo.GetAllEpisodes().Cast().Where(x => x.GrandparentKey == oldKey); if (episodeToChange.Any()) { foreach (var e in episodeToChange) @@ -553,9 +599,9 @@ namespace Ombi.Schedule.Jobs.Plex AddedAt = DateTime.Now, Key = show.ratingKey, ReleaseYear = show.year.ToString(), - Type = PlexMediaTypeEntity.Show, + Type = MediaType.Series, Title = show.title, - Url = PlexHelper.GetPlexMediaUrl(servers.MachineIdentifier, show.ratingKey), + Url = PlexHelper.GetPlexMediaUrl(servers.MachineIdentifier, show.ratingKey, servers.ServerHostname), Seasons = new List() }; await GetProviderIds(showMetadata, item); @@ -567,19 +613,19 @@ namespace Ombi.Schedule.Jobs.Plex if (item.ImdbId.HasValue()) { existingImdb = await Repo.GetAll().AnyAsync(x => - x.ImdbId == item.ImdbId && x.Type == PlexMediaTypeEntity.Show); + x.ImdbId == item.ImdbId && x.Type == MediaType.Series); } if (item.TheMovieDbId.HasValue()) { existingMovieDbId = await Repo.GetAll().AnyAsync(x => - x.TheMovieDbId == item.TheMovieDbId && x.Type == PlexMediaTypeEntity.Show); + x.TheMovieDbId == item.TheMovieDbId && x.Type == MediaType.Series); } if (item.TvDbId.HasValue()) { existingTvDbId = await Repo.GetAll().AnyAsync(x => - x.TvDbId == item.TvDbId && x.Type == PlexMediaTypeEntity.Show); + x.TvDbId == item.TvDbId && x.Type == MediaType.Series); } if (existingImdb || existingTvDbId || existingMovieDbId) diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs index 50c5d1f39..c17af088c 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs @@ -113,7 +113,7 @@ namespace Ombi.Schedule.Jobs.Plex { var currentPosition = 0; var resultCount = settings.EpisodeBatchSize == 0 ? 150 : settings.EpisodeBatchSize; - var currentEpisodes = _repo.GetAllEpisodes(); + var currentEpisodes = _repo.GetAllEpisodes().Cast(); var episodes = await _api.GetAllEpisodes(settings.PlexAuthToken, settings.FullUri, section.key, currentPosition, resultCount); _log.LogInformation(LoggingEvents.PlexEpisodeCacher, $"Total Epsiodes found for {episodes.MediaContainer.librarySectionTitle} = {episodes.MediaContainer.totalSize}"); @@ -179,6 +179,13 @@ namespace Ombi.Schedule.Jobs.Plex episode.grandparentRatingKey = seriesExists.Key; } + // Sanity checks + if (episode.index == 0) + { + _log.LogWarning($"Episode {episode.title} has no episode number. Skipping."); + continue; + } + ep.Add(new PlexEpisode { EpisodeNumber = episode.index, diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs new file mode 100644 index 000000000..8e6b443ef --- /dev/null +++ b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs @@ -0,0 +1,211 @@ +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Logging; +using Ombi.Api.Plex; +using Ombi.Api.Plex.Models; +using Ombi.Core.Authentication; +using Ombi.Core.Engine; +using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Models.Requests; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; +using Ombi.Helpers; +using Ombi.Hubs; +using Ombi.Store.Entities; +using Ombi.Store.Entities.Requests; +using Ombi.Store.Repository; +using Quartz; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Ombi.Schedule.Jobs.Plex +{ + public class PlexWatchlistImport : IPlexWatchlistImport + { + private readonly IPlexApi _plexApi; + private readonly ISettingsService _settings; + private readonly OmbiUserManager _ombiUserManager; + private readonly IMovieRequestEngine _movieRequestEngine; + private readonly ITvRequestEngine _tvRequestEngine; + private readonly IHubContext _hub; + private readonly ILogger _logger; + private readonly IExternalRepository _watchlistRepo; + + public PlexWatchlistImport(IPlexApi plexApi, ISettingsService settings, OmbiUserManager ombiUserManager, + IMovieRequestEngine movieRequestEngine, ITvRequestEngine tvRequestEngine, IHubContext hub, + ILogger logger, IExternalRepository watchlistRepo) + { + _plexApi = plexApi; + _settings = settings; + _ombiUserManager = ombiUserManager; + _movieRequestEngine = movieRequestEngine; + _tvRequestEngine = tvRequestEngine; + _hub = hub; + _logger = logger; + _watchlistRepo = watchlistRepo; + } + + public async Task Execute(IJobExecutionContext context) + { + var settings = await _settings.GetSettingsAsync(); + if (!settings.Enable || !settings.EnableWatchlistImport) + { + _logger.LogDebug($"Not enabled. Plex Enabled: {settings.Enable}, Watchlist Enabled: {settings.EnableWatchlistImport}"); + return; + } + + var plexUsersWithTokens = _ombiUserManager.Users.Where(x => x.UserType == UserType.PlexUser && x.MediaServerToken != null).ToList(); + _logger.LogInformation($"Found {plexUsersWithTokens.Count} users with tokens"); + await NotifyClient("Starting Watchlist Import"); + + foreach (var user in plexUsersWithTokens) + { + try + { + + _logger.LogDebug($"Starting Watchlist Import for {user.UserName} with token {user.MediaServerToken}"); + var watchlist = await _plexApi.GetWatchlist(user.MediaServerToken, context?.CancellationToken ?? CancellationToken.None); + if (watchlist == null || !(watchlist.MediaContainer?.Metadata?.Any() ?? false)) + { + _logger.LogDebug($"No watchlist found for {user.UserName}"); + continue; + } + + var items = watchlist.MediaContainer.Metadata; + _logger.LogDebug($"Items found in watchlist: {watchlist.MediaContainer.totalSize}"); + foreach (var item in items) + { + _logger.LogDebug($"Processing {item.title} {item.type}"); + var providerIds = await GetProviderIds(user.MediaServerToken, item, context?.CancellationToken ?? CancellationToken.None); + if (!providerIds.TheMovieDb.HasValue()) + { + _logger.LogWarning($"No TheMovieDb Id found for {item.title}, could not import via Plex WatchList"); + // We need a MovieDbId to support this; + continue; + } + + // Check to see if we have already imported this item + var alreadyImported = _watchlistRepo.GetAll().Any(x => x.TmdbId == providerIds.TheMovieDb); + if (alreadyImported) + { + _logger.LogDebug($"{item.title} already imported via Plex WatchList, skipping"); + continue; + } + + switch (item.type) + { + case "show": + await ProcessShow(int.Parse(providerIds.TheMovieDb), user); + break; + case "movie": + await ProcessMovie(int.Parse(providerIds.TheMovieDb), user); + break; + } + } + } + catch (Exception ex) + { + _logger.LogError(ex, $"Exception thrown when importing watchlist for user {user.UserName}"); + continue; + } + } + + await NotifyClient("Finished Watchlist Import"); + } + + private async Task ProcessMovie(int theMovieDbId, OmbiUser user) + { + _movieRequestEngine.SetUser(user); + var response = await _movieRequestEngine.RequestMovie(new() { TheMovieDbId = theMovieDbId, Source = RequestSource.PlexWatchlist }); + if (response.IsError) + { + if (response.ErrorCode == ErrorCode.AlreadyRequested) + { + _logger.LogDebug($"Movie already requested for user '{user.UserName}'"); + await AddToHistory(theMovieDbId); + return; + } + _logger.LogInformation($"Error adding title from PlexWatchlist for user '{user.UserName}'. Message: '{response.ErrorMessage}'"); + } + else + { + await AddToHistory(theMovieDbId); + + _logger.LogInformation($"Added title from PlexWatchlist for user '{user.UserName}'. {response.Message}"); + } + } + + private async Task ProcessShow(int theMovieDbId, OmbiUser user) + { + _tvRequestEngine.SetUser(user); + var response = await _tvRequestEngine.RequestTvShow(new TvRequestViewModelV2 { LatestSeason = true, TheMovieDbId = theMovieDbId, Source = RequestSource.PlexWatchlist }); + if (response.IsError) + { + if (response.ErrorCode == ErrorCode.AlreadyRequested) + { + _logger.LogDebug($"Show already requested for user '{user.UserName}'"); + await AddToHistory(theMovieDbId); + return; + } + _logger.LogInformation($"Error adding title from PlexWatchlist for user '{user.UserName}'. Message: '{response.ErrorMessage}'"); + } + else + { + await AddToHistory(theMovieDbId); + _logger.LogInformation($"Added title from PlexWatchlist for user '{user.UserName}'. {response.Message}"); + } + } + private async Task AddToHistory(int theMovieDbId) + { + + // Add to the watchlist history + var history = new PlexWatchlistHistory + { + TmdbId = theMovieDbId.ToString() + }; + await _watchlistRepo.Add(history); + } + + private async Task GetProviderIds(string authToken, Metadata movie, CancellationToken cancellationToken) + { + var guids = new List(); + if (!movie.Guid.Any()) + { + var metaData = await _plexApi.GetWatchlistMetadata(movie.ratingKey, authToken, cancellationToken); + + var meta = metaData.MediaContainer.Metadata.FirstOrDefault(); + guids.Add(meta.guid); + if (meta.Guid != null) + { + foreach (var g in meta.Guid) + { + guids.Add(g.Id); + } + } + } + else + { + // Currently a Plex Pass feature only + foreach (var g in movie.Guid) + { + guids.Add(g.Id); + } + } + var providerIds = PlexHelper.GetProviderIdsFromMetadata(guids.ToArray()); + return providerIds; + } + + private async Task NotifyClient(string message) + { + if (_hub?.Clients == null) + { + return; + } + await _hub?.Clients?.Clients(NotificationHub.AdminConnectionIds)? + .SendAsync(NotificationHub.NotificationEvent, $"Plex Watchlist Import - {message}"); + } + public void Dispose() { } + } +} diff --git a/src/Ombi.Schedule/Jobs/Radarr/IRadarrSync.cs b/src/Ombi.Schedule/Jobs/Radarr/IRadarrSync.cs index 1fb191fd1..19178ca48 100644 --- a/src/Ombi.Schedule/Jobs/Radarr/IRadarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Radarr/IRadarrSync.cs @@ -1,11 +1,6 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Ombi.Store.Entities; - -namespace Ombi.Schedule.Jobs.Radarr +namespace Ombi.Schedule.Jobs.Radarr { public interface IRadarrSync : IBaseJob { - Task> GetCachedContent(); } } \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs index 3cda06281..94970305a 100644 --- a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -10,106 +9,112 @@ using Ombi.Helpers; using Ombi.Settings.Settings.Models.External; using Ombi.Store.Context; using Ombi.Store.Entities; +using Ombi.Store.Repository; using Quartz; -using Serilog; namespace Ombi.Schedule.Jobs.Radarr { public class RadarrSync : IRadarrSync { - public RadarrSync(ISettingsService radarr, IRadarrV3Api radarrApi, ILogger log, ExternalContext ctx) + public RadarrSync(ISettingsService radarr, ISettingsService radarr4k, IRadarrV3Api radarrApi, ILogger log, ExternalContext ctx, + IExternalRepository radarrRepo) { - RadarrSettings = radarr; - RadarrApi = radarrApi; - Logger = log; + _radarrSettings = radarr; + _radarr4kSettings = radarr4k; + _api = radarrApi; + _logger = log; _ctx = ctx; - RadarrSettings.ClearCache(); + _radarrRepo = radarrRepo; + _radarrSettings.ClearCache(); + _radarr4kSettings.ClearCache(); } - private ISettingsService RadarrSettings { get; } - private IRadarrV3Api RadarrApi { get; } - private ILogger Logger { get; } + private readonly ISettingsService _radarrSettings; + private readonly ISettingsService _radarr4kSettings; + private readonly IRadarrV3Api _api; + private readonly ILogger _logger; private readonly ExternalContext _ctx; - - private static readonly SemaphoreSlim SemaphoreSlim = new SemaphoreSlim(1, 1); + private readonly IExternalRepository _radarrRepo; public async Task Execute(IJobExecutionContext job) { - await SemaphoreSlim.WaitAsync(); try { - var settings = await RadarrSettings.GetSettingsAsync(); - if (settings.Enabled) + var strat = _ctx.Database.CreateExecutionStrategy(); + await strat.ExecuteAsync(async () => { - try - { - var movies = await RadarrApi.GetMovies(settings.ApiKey, settings.FullUri); - if (movies != null) - { - var strat = _ctx.Database.CreateExecutionStrategy(); - await strat.ExecuteAsync(async () => - { - // Let's remove the old cached data - using (var tran = await _ctx.Database.BeginTransactionAsync()) - { - await _ctx.Database.ExecuteSqlRawAsync("DELETE FROM RadarrCache"); - tran.Commit(); - } - }); + // Let's remove the old cached data + using var tran = await _ctx.Database.BeginTransactionAsync(); + await _ctx.Database.ExecuteSqlRawAsync("DELETE FROM RadarrCache"); + tran.Commit(); + }); - var movieIds = new List(); - foreach (var m in movies) + var radarrSettings = _radarrSettings.GetSettingsAsync(); + var radarr4kSettings = _radarr4kSettings.GetSettingsAsync(); + await Process(await radarrSettings); + await Process(await radarr4kSettings); + } + catch (Exception) + { + _logger.LogInformation(LoggingEvents.RadarrCacher, "Radarr is not setup, cannot cache episodes"); + } + } + + private async Task Process(RadarrSettings settings) + { + if (settings.Enabled) + { + try + { + var movies = await _api.GetMovies(settings.ApiKey, settings.FullUri); + var existingMovies = _radarrRepo.GetAll(); + if (movies != null) + { + var movieIds = new List(); + foreach (var m in movies) + { + if (m.monitored || m.hasFile) { - if (m.monitored || m.hasFile) + if (m.tmdbId > 0) { - if (m.tmdbId > 0) + var is4k = m.movieFile?.quality?.quality?.resolution >= 2160; + + // Do we have a cached movie for this already? + var existing = await existingMovies.FirstOrDefaultAsync(x => x.TheMovieDbId == m.tmdbId); + if (existing != null) + { + existing.Has4K = is4k; + existing.HasFile = m.hasFile; + } + else { movieIds.Add(new RadarrCache { TheMovieDbId = m.tmdbId, - HasFile = m.hasFile + HasFile = m.hasFile, + Has4K = is4k, + HasRegular = !is4k }); } - else - { - Logger.LogError("TMDBId is not > 0 for movie {0}", m.title); - } + } + else + { + _logger.LogError($"TMDBId is not > 0 for movie {m.title}"); } } - strat = _ctx.Database.CreateExecutionStrategy(); - await strat.ExecuteAsync(async () => - { - using (var tran = await _ctx.Database.BeginTransactionAsync()) - { - await _ctx.RadarrCache.AddRangeAsync(movieIds); - - await _ctx.SaveChangesAsync(); - tran.Commit(); - } - }); } + // Save from the updates made to the existing movies (they are in the EF Change Tracker) + await _radarrRepo.SaveChangesAsync(); + await _radarrRepo.AddRange(movieIds); + } - await OmbiQuartz.TriggerJob(nameof(IArrAvailabilityChecker), "DVR"); - } - catch (System.Exception ex) - { - Logger.LogError(LoggingEvents.Cacher, ex, "Failed caching queued items from Radarr"); - } + await OmbiQuartz.TriggerJob(nameof(IArrAvailabilityChecker), "DVR"); + } + catch (System.Exception ex) + { + _logger.LogError(LoggingEvents.Cacher, ex, "Failed caching queued items from Radarr"); } } - catch (Exception) - { - Logger.LogInformation(LoggingEvents.RadarrCacher, "Radarr is not setup, cannot cache episodes"); - } - finally - { - SemaphoreSlim.Release(); - } - } - - public async Task> GetCachedContent() - { - return await _ctx.RadarrCache.ToListAsync(); } private bool _disposed; diff --git a/src/Ombi.Schedule/Ombi.Schedule.csproj b/src/Ombi.Schedule/Ombi.Schedule.csproj index ed1a7d9a1..a972aa6bb 100644 --- a/src/Ombi.Schedule/Ombi.Schedule.csproj +++ b/src/Ombi.Schedule/Ombi.Schedule.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Schedule/OmbiScheduler.cs b/src/Ombi.Schedule/OmbiScheduler.cs index 8e45be57c..41602f641 100644 --- a/src/Ombi.Schedule/OmbiScheduler.cs +++ b/src/Ombi.Schedule/OmbiScheduler.cs @@ -91,6 +91,7 @@ namespace Ombi.Schedule await OmbiQuartz.Instance.AddJob(nameof(IPlexUserImporter), "Plex", JobSettingsHelper.UserImporter(s)); await OmbiQuartz.Instance.AddJob(nameof(IPlexEpisodeSync), "Plex", null); await OmbiQuartz.Instance.AddJob(nameof(IPlexAvailabilityChecker), "Plex", null); + await OmbiQuartz.Instance.AddJob(nameof(IPlexWatchlistImport), "Plex", JobSettingsHelper.PlexWatchlistImport(s)); } private static async Task AddEmby(JobSettings s) diff --git a/src/Ombi.Settings/Ombi.Settings.csproj b/src/Ombi.Settings/Ombi.Settings.csproj index b39c123e2..3821892f0 100644 --- a/src/Ombi.Settings/Ombi.Settings.csproj +++ b/src/Ombi.Settings/Ombi.Settings.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild @@ -18,6 +18,7 @@ + diff --git a/src/Ombi.Settings/Settings/Models/AuthenticationSettings.cs b/src/Ombi.Settings/Settings/Models/AuthenticationSettings.cs index f6736e7c5..ed2775480 100644 --- a/src/Ombi.Settings/Settings/Models/AuthenticationSettings.cs +++ b/src/Ombi.Settings/Settings/Models/AuthenticationSettings.cs @@ -13,5 +13,7 @@ namespace Ombi.Settings.Settings.Models public bool RequireNonAlphanumeric { get; set; } public bool RequireUppercase { get; set; } public bool EnableOAuth { get; set; } // Plex OAuth + public bool EnableHeaderAuth { get; set; } // Header SSO + public string HeaderAuthVariable { get; set; } // Header SSO } } \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs b/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs index 6cf021f7c..5917e2592 100644 --- a/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs +++ b/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs @@ -7,6 +7,7 @@ namespace Ombi.Core.Settings.Models.External public sealed class PlexSettings : Ombi.Settings.Settings.Models.Settings { public bool Enable { get; set; } + public bool EnableWatchlistImport { get; set; } /// /// This is the ClientId for OAuth /// diff --git a/src/Ombi.Settings/Settings/Models/External/RadarrSettings.cs b/src/Ombi.Settings/Settings/Models/External/RadarrSettings.cs index b074e28d6..1b3e0982f 100644 --- a/src/Ombi.Settings/Settings/Models/External/RadarrSettings.cs +++ b/src/Ombi.Settings/Settings/Models/External/RadarrSettings.cs @@ -10,4 +10,15 @@ public string MinimumAvailability { get; set; } public bool ScanForAvailability { get; set; } } + + public class Radarr4KSettings : RadarrSettings + { + // no additional properties needed + } + + public class RadarrCombinedModel + { + public RadarrSettings Radarr { get; set; } + public Radarr4KSettings Radarr4K { get; set; } + } } \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/FeatureSettings.cs b/src/Ombi.Settings/Settings/Models/FeatureSettings.cs new file mode 100644 index 000000000..6a285d422 --- /dev/null +++ b/src/Ombi.Settings/Settings/Models/FeatureSettings.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Ombi.Settings.Settings.Models +{ + public class FeatureSettings : Settings + { + public List Features { get; set; } + } + + public class FeatureEnablement + { + public string Name { get; set; } + public bool Enabled { get; set; } + } + + public static class FeatureNames + { + public const string Movie4KRequests = nameof(Movie4KRequests); + } +} diff --git a/src/Ombi.Settings/Settings/Models/JobSettings.cs b/src/Ombi.Settings/Settings/Models/JobSettings.cs index ac7ab3bdc..cc4ed2e23 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettings.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettings.cs @@ -19,5 +19,6 @@ public string RetryRequests { get; set; } public string MediaDatabaseRefresh { get; set; } public string AutoDeleteRequests { get; set; } + public string PlexWatchlistImport { get; set; } } } diff --git a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs index e580e1977..b80943cc5 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs @@ -54,6 +54,11 @@ namespace Ombi.Settings.Settings.Models { return ValidateCron(Get(s.UserImporter, Cron.Daily())); } + + public static string PlexWatchlistImport(JobSettings s) + { + return ValidateCron(Get(s.PlexWatchlistImport, Cron.Hourly(25))); + } public static string Newsletter(JobSettings s) { diff --git a/src/Ombi.Settings/Settings/Models/Notifications/EmailNotificationSettings.cs b/src/Ombi.Settings/Settings/Models/Notifications/EmailNotificationSettings.cs index 9ea8cc492..f63b77ae5 100644 --- a/src/Ombi.Settings/Settings/Models/Notifications/EmailNotificationSettings.cs +++ b/src/Ombi.Settings/Settings/Models/Notifications/EmailNotificationSettings.cs @@ -10,7 +10,6 @@ public string SenderAddress { get; set; } public string Username { get; set; } public bool Authentication { get; set; } - public string AdminEmail { get; set; } public bool DisableTLS { get; set; } public bool DisableCertificateChecking { get; set; } } diff --git a/src/Ombi.Settings/Settings/Models/OmbiSettings.cs b/src/Ombi.Settings/Settings/Models/OmbiSettings.cs index ba460a2bd..e224b5c70 100644 --- a/src/Ombi.Settings/Settings/Models/OmbiSettings.cs +++ b/src/Ombi.Settings/Settings/Models/OmbiSettings.cs @@ -1,7 +1,10 @@ -namespace Ombi.Settings.Settings.Models +using Ombi.I18n.Resources; +using System.Globalization; +namespace Ombi.Settings.Settings.Models { public class OmbiSettings : Settings { + private string defaultLanguageCode = "en"; public string BaseUrl { get; set; } public bool CollectAnalyticData { get; set; } public bool Wizard { get; set; } @@ -9,7 +12,14 @@ public bool DoNotSendNotificationsForAutoApprove { get; set; } public bool HideRequestsUsers { get; set; } public bool DisableHealthChecks { get; set; } - public string DefaultLanguageCode { get; set; } = "en"; + public string DefaultLanguageCode + { + get => defaultLanguageCode; + set { + defaultLanguageCode = value; + Texts.Culture = new CultureInfo(value); + } + } public bool AutoDeleteAvailableRequests { get; set; } public int AutoDeleteAfterDays { get; set; } public Branch Branch { get; set; } diff --git a/src/Ombi.Store/Context/ExternalContext.cs b/src/Ombi.Store/Context/ExternalContext.cs index ce121fe10..f13c1e74f 100644 --- a/src/Ombi.Store/Context/ExternalContext.cs +++ b/src/Ombi.Store/Context/ExternalContext.cs @@ -1,4 +1,5 @@ -using System.IO; +using System.Collections.Generic; +using System.IO; using Microsoft.EntityFrameworkCore; using Ombi.Helpers; using Ombi.Store.Entities; @@ -26,6 +27,7 @@ namespace Ombi.Store.Context public DbSet PlexServerContent { get; set; } public DbSet PlexSeasonsContent { get; set; } public DbSet PlexEpisode { get; set; } + public DbSet PlexWatchlistHistory { get; set; } public DbSet RadarrCache { get; set; } public DbSet CouchPotatoCache { get; set; } public DbSet EmbyContent { get; set; } @@ -42,20 +44,20 @@ namespace Ombi.Store.Context protected override void OnModelCreating(ModelBuilder builder) { - builder.Entity().HasMany(x => x.Episodes) - .WithOne(x => x.Series) + builder.Entity().HasMany(x => (ICollection) x.Episodes) + .WithOne(x => (PlexServerContent) x.Series) .HasPrincipalKey(x => x.Key) .HasForeignKey(x => x.GrandparentKey); builder.Entity() - .HasOne(p => p.Series) - .WithMany(b => b.Episodes) + .HasOne(p => (EmbyContent) p.Series) + .WithMany(b => (ICollection) b.Episodes) .HasPrincipalKey(x => x.EmbyId) .HasForeignKey(p => p.ParentId); builder.Entity() - .HasOne(p => p.Series) - .WithMany(b => b.Episodes) + .HasOne(p => (JellyfinContent) p.Series) + .WithMany(b => (ICollection) b.Episodes) .HasPrincipalKey(x => x.JellyfinId) .HasForeignKey(p => p.ParentId); diff --git a/src/Ombi.Store/Context/SettingsContext.cs b/src/Ombi.Store/Context/SettingsContext.cs index 83ffa792d..39883cb92 100644 --- a/src/Ombi.Store/Context/SettingsContext.cs +++ b/src/Ombi.Store/Context/SettingsContext.cs @@ -1,5 +1,6 @@ using System.Linq; using Microsoft.EntityFrameworkCore; +using Newtonsoft.Json; using Ombi.Store.Entities; namespace Ombi.Store.Context diff --git a/src/Ombi.Store/Entities/EmbyContent.cs b/src/Ombi.Store/Entities/EmbyContent.cs index 348573f28..08118b6df 100644 --- a/src/Ombi.Store/Entities/EmbyContent.cs +++ b/src/Ombi.Store/Entities/EmbyContent.cs @@ -32,40 +32,13 @@ using System.ComponentModel.DataAnnotations.Schema; namespace Ombi.Store.Entities { [Table("EmbyContent")] - public class EmbyContent : Entity + public class EmbyContent : MediaServerContent { - public string Title { get; set; } - /// - /// OBSOLETE, Cannot delete due to DB migration issues with SQLite - /// + [Obsolete("Cannot delete due to DB migration issues with SQLite")] public string ProviderId { get; set; } public string EmbyId { get; set; } - public EmbyMediaType Type { get; set; } - public DateTime AddedAt { get; set; } - - public string ImdbId { get; set; } - public string TheMovieDbId { get; set; } - public string TvDbId { get; set; } - - public string Url { get; set; } - - public ICollection Episodes { get; set; } - - [NotMapped] - public bool HasImdb => !string.IsNullOrEmpty(ImdbId); - - [NotMapped] - public bool HasTvDb => !string.IsNullOrEmpty(TvDbId); - - [NotMapped] - public bool HasTheMovieDb => !string.IsNullOrEmpty(TheMovieDbId); + public override RecentlyAddedType RecentlyAddedType => RecentlyAddedType.Emby; } - public enum EmbyMediaType - { - Movie = 0, - Series = 1, - Music = 2 - } } \ No newline at end of file diff --git a/src/Ombi.Store/Entities/EmbyEpisode.cs b/src/Ombi.Store/Entities/EmbyEpisode.cs index e4e5b6a4b..89103c580 100644 --- a/src/Ombi.Store/Entities/EmbyEpisode.cs +++ b/src/Ombi.Store/Entities/EmbyEpisode.cs @@ -26,18 +26,16 @@ #endregion using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; -using Microsoft.EntityFrameworkCore.Metadata; +using System.Linq; namespace Ombi.Store.Entities { [Table("EmbyEpisode")] - public class EmbyEpisode : Entity + public class EmbyEpisode : MediaServerEpisode { - public string Title { get; set; } public string EmbyId { get; set; } - public int EpisodeNumber { get; set; } - public int SeasonNumber { get; set; } public string ParentId { get; set; } /// /// NOT USED @@ -47,7 +45,17 @@ namespace Ombi.Store.Entities public string TvDbId { get; set; } public string ImdbId { get; set; } public string TheMovieDbId { get; set; } + [NotMapped] + public EmbyContent EmbySeries + { + get => (EmbyContent)Series; + set => Series = value; + } - public EmbyContent Series { get; set; } + public override IMediaServerContent SeriesIsIn(ICollection content) + { + return content.OfType().FirstOrDefault( + x => x.EmbyId == this.EmbySeries.EmbyId); + } } } \ No newline at end of file diff --git a/src/Ombi.Store/Entities/Entity.cs b/src/Ombi.Store/Entities/Entity.cs index 8e1cd2887..fac70de91 100644 --- a/src/Ombi.Store/Entities/Entity.cs +++ b/src/Ombi.Store/Entities/Entity.cs @@ -2,7 +2,7 @@ namespace Ombi.Store.Entities { - public abstract class Entity + public abstract class Entity: IEntity { [Key] public int Id { get; set; } diff --git a/src/Ombi.Store/Entities/IEntity.cs b/src/Ombi.Store/Entities/IEntity.cs new file mode 100644 index 000000000..004d214f1 --- /dev/null +++ b/src/Ombi.Store/Entities/IEntity.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations; + +namespace Ombi.Store.Entities +{ + public interface IEntity + { + [Key] + public int Id { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Entities/IMediaServerContent.cs b/src/Ombi.Store/Entities/IMediaServerContent.cs new file mode 100644 index 000000000..25e4d5f50 --- /dev/null +++ b/src/Ombi.Store/Entities/IMediaServerContent.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Ombi.Store.Entities +{ + public interface IMediaServerContent: IEntity + { + public string Title { get; set; } + public string ImdbId { get; set; } + public string TvDbId { get; set; } + public string TheMovieDbId { get; set; } + public MediaType Type { get; set; } + public RecentlyAddedType RecentlyAddedType{ get; } + + public string Url { get; set; } + + public ICollection Episodes { get; set; } + + public DateTime AddedAt { get; set; } + + [NotMapped] + public bool HasImdb => !string.IsNullOrEmpty(ImdbId); + + [NotMapped] + public bool HasTvDb => !string.IsNullOrEmpty(TvDbId); + + [NotMapped] + public bool HasTheMovieDb => !string.IsNullOrEmpty(TheMovieDbId); + } + + public interface IMediaServerEpisode + { + public int EpisodeNumber { get; set; } + public int SeasonNumber { get; set; } + public string Title { get; set; } + /// + /// The Season key + /// + /// + /// The parent key. + /// + + + public IMediaServerContent Series { get; set; } + public IMediaServerContent SeriesIsIn(ICollection content); + public bool IsIn(IMediaServerContent content); + } + + public enum MediaType + { + Movie = 0, + Series = 1, + Music = 2, + Episode = 3 + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Entities/JellyfinContent.cs b/src/Ombi.Store/Entities/JellyfinContent.cs index 857457bde..b2bb63959 100644 --- a/src/Ombi.Store/Entities/JellyfinContent.cs +++ b/src/Ombi.Store/Entities/JellyfinContent.cs @@ -32,40 +32,14 @@ using System.ComponentModel.DataAnnotations.Schema; namespace Ombi.Store.Entities { [Table("JellyfinContent")] - public class JellyfinContent : Entity + public class JellyfinContent : MediaServerContent { - public string Title { get; set; } - /// - /// OBSOLETE, Cannot delete due to DB migration issues with SQLite - /// + + [Obsolete("Cannot delete due to DB migration issues with SQLite")] public string ProviderId { get; set; } public string JellyfinId { get; set; } - public JellyfinMediaType Type { get; set; } - public DateTime AddedAt { get; set; } - - public string ImdbId { get; set; } - public string TheMovieDbId { get; set; } - public string TvDbId { get; set; } - - public string Url { get; set; } - - public ICollection Episodes { get; set; } - - [NotMapped] - public bool HasImdb => !string.IsNullOrEmpty(ImdbId); - - [NotMapped] - public bool HasTvDb => !string.IsNullOrEmpty(TvDbId); - - [NotMapped] - public bool HasTheMovieDb => !string.IsNullOrEmpty(TheMovieDbId); + public override RecentlyAddedType RecentlyAddedType => RecentlyAddedType.Jellyfin; } - public enum JellyfinMediaType - { - Movie = 0, - Series = 1, - Music = 2 - } } diff --git a/src/Ombi.Store/Entities/JellyfinEpisode.cs b/src/Ombi.Store/Entities/JellyfinEpisode.cs index f2c2f820d..5b105003c 100644 --- a/src/Ombi.Store/Entities/JellyfinEpisode.cs +++ b/src/Ombi.Store/Entities/JellyfinEpisode.cs @@ -26,18 +26,17 @@ #endregion using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; using Microsoft.EntityFrameworkCore.Metadata; namespace Ombi.Store.Entities { [Table("JellyfinEpisode")] - public class JellyfinEpisode : Entity + public class JellyfinEpisode : MediaServerEpisode { - public string Title { get; set; } public string JellyfinId { get; set; } - public int EpisodeNumber { get; set; } - public int SeasonNumber { get; set; } public string ParentId { get; set; } /// /// NOT USED @@ -47,7 +46,17 @@ namespace Ombi.Store.Entities public string TvDbId { get; set; } public string ImdbId { get; set; } public string TheMovieDbId { get; set; } - - public JellyfinContent Series { get; set; } + [NotMapped] + public JellyfinContent JellyfinSeries + { + get => (JellyfinContent)Series; + set => Series = value; + } + + public override IMediaServerContent SeriesIsIn(ICollection content) + { + return content.OfType().FirstOrDefault( + x => x.JellyfinId == this.JellyfinSeries.JellyfinId); + } } } diff --git a/src/Ombi.Store/Entities/MediaServerContent.cs b/src/Ombi.Store/Entities/MediaServerContent.cs new file mode 100644 index 000000000..4f086060b --- /dev/null +++ b/src/Ombi.Store/Entities/MediaServerContent.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; + +namespace Ombi.Store.Entities +{ + public abstract class MediaServerContent: Entity, IMediaServerContent + { + public string Title { get; set; } + public string ImdbId { get; set; } + public string TvDbId { get; set; } + public string TheMovieDbId { get; set; } + public MediaType Type { get; set; } + /// + /// Only populated if it's not 4k + /// + public string Quality { get; set; } + public bool Has4K { get; set; } + public string Url { get; set; } + + public ICollection Episodes { get; set; } + + public DateTime AddedAt { get; set; } + + [NotMapped] + public bool HasImdb => !string.IsNullOrEmpty(ImdbId); + + [NotMapped] + public bool HasTvDb => !string.IsNullOrEmpty(TvDbId); + + [NotMapped] + public bool HasTheMovieDb => !string.IsNullOrEmpty(TheMovieDbId); + + [NotMapped] + public abstract RecentlyAddedType RecentlyAddedType { get; } + } + + public abstract class MediaServerEpisode: Entity, IMediaServerEpisode + { + public int EpisodeNumber { get; set; } + public int SeasonNumber { get; set; } + public string Title { get; set; } + + public IMediaServerContent Series { get; set; } + + public abstract IMediaServerContent SeriesIsIn(ICollection content); + public bool IsIn(IMediaServerContent content) + { + return content.Episodes.Any(x => x.SeasonNumber == this.SeasonNumber && x.EpisodeNumber == this.EpisodeNumber); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Entities/OmbiUser.cs b/src/Ombi.Store/Entities/OmbiUser.cs index 1b7ea6f7c..376db28f7 100644 --- a/src/Ombi.Store/Entities/OmbiUser.cs +++ b/src/Ombi.Store/Entities/OmbiUser.cs @@ -36,6 +36,7 @@ namespace Ombi.Store.Entities public RequestLimitType? MusicRequestLimitType { get; set; } public string UserAccessToken { get; set; } + public string MediaServerToken { get; set; } public List NotificationUserIds { get; set; } public List UserNotificationPreferences { get; set; } diff --git a/src/Ombi.Store/Entities/PlexEpisode.cs b/src/Ombi.Store/Entities/PlexEpisode.cs index 3acca8f3b..a9628a13d 100644 --- a/src/Ombi.Store/Entities/PlexEpisode.cs +++ b/src/Ombi.Store/Entities/PlexEpisode.cs @@ -1,30 +1,32 @@ -using System.ComponentModel.DataAnnotations.Schema; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; namespace Ombi.Store.Entities { [Table("PlexEpisode")] - public class PlexEpisode : Entity + public class PlexEpisode : MediaServerEpisode { - public int EpisodeNumber { get; set; } - public int SeasonNumber { get; set; } - public int Key { get; set; } // RatingKey - public string Title { get; set; } - /// - /// The Season key - /// + public string Key { get; set; } // RatingKey /// /// The parent key. /// - public int ParentKey { get; set; } - /// - /// The Series key - /// + public string ParentKey { get; set; } /// /// The grandparent key. /// - public int GrandparentKey { get; set; } + public string GrandparentKey { get; set; } + [NotMapped] + public PlexServerContent PlexSeries + { + get => (PlexServerContent)Series; + set => Series = value; + } - - public PlexServerContent Series { get; set; } + public override IMediaServerContent SeriesIsIn(ICollection content) + { + return content.OfType().FirstOrDefault( + x => x.Key == this.PlexSeries.Key); + } } } \ No newline at end of file diff --git a/src/Ombi.Store/Entities/PlexServerContent.cs b/src/Ombi.Store/Entities/PlexServerContent.cs index f8e0e01d4..8af5e250e 100644 --- a/src/Ombi.Store/Entities/PlexServerContent.cs +++ b/src/Ombi.Store/Entities/PlexServerContent.cs @@ -32,51 +32,27 @@ using System.ComponentModel.DataAnnotations.Schema; namespace Ombi.Store.Entities { [Table("PlexServerContent")] - public class PlexServerContent : Entity + public class PlexServerContent : MediaServerContent { - public string Title { get; set; } public string ReleaseYear { get; set; } - public string ImdbId { get; set; } - public string TvDbId { get; set; } - public string TheMovieDbId { get; set; } - public PlexMediaTypeEntity Type { get; set; } - - public string Url { get; set; } - - public ICollection Episodes { get; set; } public ICollection Seasons { get; set; } /// /// Plex's internal ID for this item /// - public int Key { get; set; } - public DateTime AddedAt { get; set; } - public string Quality { get; set; } + public string Key { get; set; } public int? RequestId { get; set; } - - [NotMapped] - public bool HasImdb => !string.IsNullOrEmpty(ImdbId); - - [NotMapped] - public bool HasTvDb => !string.IsNullOrEmpty(TvDbId); - - [NotMapped] - public bool HasTheMovieDb => !string.IsNullOrEmpty(TheMovieDbId); + + public override RecentlyAddedType RecentlyAddedType => RecentlyAddedType.Plex; } [Table("PlexSeasonsContent")] public class PlexSeasonsContent : Entity { - public int PlexContentId { get; set; } + public string PlexContentId { get; set; } public int SeasonNumber { get; set; } - public int SeasonKey { get; set; } - public int ParentKey { get; set; } - } - - public enum PlexMediaTypeEntity - { - Movie = 0, - Show = 1 + public string SeasonKey { get; set; } + public string ParentKey { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Store/Entities/PlexWatchlistHistory.cs b/src/Ombi.Store/Entities/PlexWatchlistHistory.cs new file mode 100644 index 000000000..e6aee29b4 --- /dev/null +++ b/src/Ombi.Store/Entities/PlexWatchlistHistory.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace Ombi.Store.Entities +{ + [Table(nameof(PlexWatchlistHistory))] + public class PlexWatchlistHistory : Entity + { + public string TmdbId { get; set; } + } +} diff --git a/src/Ombi.Store/Entities/RadarrCache.cs b/src/Ombi.Store/Entities/RadarrCache.cs index 4b62412fc..553e84f2b 100644 --- a/src/Ombi.Store/Entities/RadarrCache.cs +++ b/src/Ombi.Store/Entities/RadarrCache.cs @@ -7,5 +7,7 @@ namespace Ombi.Store.Entities { public int TheMovieDbId { get; set; } public bool HasFile { get; set; } + public bool Has4K { get; set; } + public bool HasRegular { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Store/Entities/Requests/BaseRequest.cs b/src/Ombi.Store/Entities/Requests/BaseRequest.cs index 596041a51..9c564376b 100644 --- a/src/Ombi.Store/Entities/Requests/BaseRequest.cs +++ b/src/Ombi.Store/Entities/Requests/BaseRequest.cs @@ -22,8 +22,10 @@ namespace Ombi.Store.Entities.Requests [ForeignKey(nameof(RequestedUserId))] public OmbiUser RequestedUser { get; set; } + public RequestSource Source { get; set; } = RequestSource.Ombi; + [NotMapped] - public bool CanApprove => !Approved && !Available; + public virtual bool CanApprove => !Approved && !Available; } } \ No newline at end of file diff --git a/src/Ombi.Store/Entities/Requests/MovieRequests.cs b/src/Ombi.Store/Entities/Requests/MovieRequests.cs index 42b17be73..415efded2 100644 --- a/src/Ombi.Store/Entities/Requests/MovieRequests.cs +++ b/src/Ombi.Store/Entities/Requests/MovieRequests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using Newtonsoft.Json; +using System; namespace Ombi.Store.Entities.Requests { @@ -22,9 +23,28 @@ namespace Ombi.Store.Entities.Requests [NotMapped] public bool ShowSubscribe { get; set; } + /// + /// This is only used during the request process to identify if + /// it's a regular request or a 4k + /// + [NotMapped] + public bool Is4kRequest { get; set; } + public int RootPathOverride { get; set; } public int QualityOverride { get; set; } + public bool Has4KRequest { get; set; } + + public bool Approved4K { get; set; } + public DateTime MarkedAsApproved4K { get; set; } + public DateTime RequestedDate4k { get; set; } + public bool Available4K { get; set; } + public DateTime? MarkedAsAvailable4K { get; set; } + public bool? Denied4K { get; set; } + public DateTime MarkedAsDenied4K { get; set; } + public string DeniedReason4K { get; set; } + + /// /// Only Use for setting the Language Code, Use the LanguageCode property for reading /// @@ -61,5 +81,8 @@ namespace Ombi.Store.Entities.Requests return string.Empty; } } + + [NotMapped] + public override bool CanApprove => !Approved && !Available || !Approved4K && !Available4K; } } diff --git a/src/Ombi.Store/Entities/Requests/RequestSource.cs b/src/Ombi.Store/Entities/Requests/RequestSource.cs new file mode 100644 index 000000000..44ccc20d8 --- /dev/null +++ b/src/Ombi.Store/Entities/Requests/RequestSource.cs @@ -0,0 +1,8 @@ +namespace Ombi.Store.Entities.Requests +{ + public enum RequestSource + { + Ombi = 0, + PlexWatchlist = 1 + } +} diff --git a/src/Ombi.Store/Entities/Requests/SeasonRequests.cs b/src/Ombi.Store/Entities/Requests/SeasonRequests.cs index 0d8d587a5..5de8003a1 100644 --- a/src/Ombi.Store/Entities/Requests/SeasonRequests.cs +++ b/src/Ombi.Store/Entities/Requests/SeasonRequests.cs @@ -31,6 +31,8 @@ namespace Ombi.Store.Repository.Requests public bool Requested { get; set; } [NotMapped] public bool? Denied { get; set; } + [NotMapped] + public string DeniedReason { get; set; } public int SeasonId { get; set; } [ForeignKey(nameof(SeasonId))] @@ -58,7 +60,7 @@ namespace Ombi.Store.Repository.Requests return "Common.ProcessingRequest"; } - if (!Approved && !Available) + if (Requested && !Approved && !Available) { return "Common.PendingApproval"; } diff --git a/src/Ombi.Store/MigrationHelper.cs b/src/Ombi.Store/MigrationHelper.cs new file mode 100644 index 000000000..58b6d6b68 --- /dev/null +++ b/src/Ombi.Store/MigrationHelper.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; + +namespace Ombi.Store +{ + internal static class MigrationHelper + { + public static void InsertRole(this MigrationBuilder mb, string role) + { + mb.Sql($@" +INSERT INTO AspnetRoles(Id, ConcurrencyStamp, Name, NormalizedName) +SELECT '{Guid.NewGuid()}','{Guid.NewGuid()}','{role}', '{role.ToUpper()}' +WHERE NOT EXISTS(SELECT 1 FROM AspnetRoles WHERE Name = '{role}');"); + } + + public static void InsertRoleMySql(this MigrationBuilder mb, string role) + { + mb.Sql($@" +INSERT INTO AspNetRoles(Id, ConcurrencyStamp, Name, NormalizedName) +SELECT '{Guid.NewGuid()}','{Guid.NewGuid()}','{role}', '{role.ToUpper()}' +WHERE NOT EXISTS(SELECT 1 FROM AspNetRoles WHERE Name = '{role}');"); + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalMySql/20220211213229_MediaServerQualities.Designer.cs b/src/Ombi.Store/Migrations/ExternalMySql/20220211213229_MediaServerQualities.Designer.cs new file mode 100644 index 000000000..ab88ff30d --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalMySql/20220211213229_MediaServerQualities.Designer.cs @@ -0,0 +1,527 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalMySql +{ + [DbContext(typeof(ExternalMySqlContext))] + [Migration("20220211213229_MediaServerQualities")] + partial class MediaServerQualities + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EmbyId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EmbyId") + .HasColumnType("longtext"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("ParentId") + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("JellyfinId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("JellyfinContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("JellyfinId") + .HasColumnType("longtext"); + + b.Property("ParentId") + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("JellyfinEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("ArtistId") + .HasColumnType("int"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext"); + + b.Property("Monitored") + .HasColumnType("tinyint(1)"); + + b.Property("PercentOfTracks") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TrackCount") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ArtistId") + .HasColumnType("int"); + + b.Property("ArtistName") + .HasColumnType("longtext"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext"); + + b.Property("Monitored") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("GrandparentKey") + .HasColumnType("int"); + + b.Property("Key") + .HasColumnType("int"); + + b.Property("ParentKey") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ParentKey") + .HasColumnType("int"); + + b.Property("PlexContentId") + .HasColumnType("int"); + + b.Property("PlexServerContentId") + .HasColumnType("int"); + + b.Property("SeasonKey") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("Key") + .HasColumnType("int"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("ReleaseYear") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("HasFile") + .HasColumnType("tinyint(1)"); + + b.Property("HasRegular") + .HasColumnType("tinyint(1)"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("HasFile") + .HasColumnType("tinyint(1)"); + + b.Property("MovieDbId") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.HasOne("Ombi.Store.Entities.JellyfinContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("JellyfinId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", null) + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Navigation("Episodes"); + + b.Navigation("Seasons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalMySql/20220211213229_MediaServerQualities.cs b/src/Ombi.Store/Migrations/ExternalMySql/20220211213229_MediaServerQualities.cs new file mode 100644 index 000000000..add7da05e --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalMySql/20220211213229_MediaServerQualities.cs @@ -0,0 +1,59 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalMySql +{ + public partial class MediaServerQualities : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Has4K", + table: "RadarrCache", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "HasRegular", + table: "RadarrCache", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Quality", + table: "JellyfinContent", + type: "longtext", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "Quality", + table: "EmbyContent", + type: "longtext", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Has4K", + table: "RadarrCache"); + + migrationBuilder.DropColumn( + name: "HasRegular", + table: "RadarrCache"); + + migrationBuilder.DropColumn( + name: "Quality", + table: "JellyfinContent"); + + migrationBuilder.DropColumn( + name: "Quality", + table: "EmbyContent"); + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalMySql/20220212210902_MediaServer4k.Designer.cs b/src/Ombi.Store/Migrations/ExternalMySql/20220212210902_MediaServer4k.Designer.cs new file mode 100644 index 000000000..fbdc63e32 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalMySql/20220212210902_MediaServer4k.Designer.cs @@ -0,0 +1,536 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalMySql +{ + [DbContext(typeof(ExternalMySqlContext))] + [Migration("20220212210902_MediaServer4k")] + partial class MediaServer4k + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EmbyId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EmbyId") + .HasColumnType("longtext"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("ParentId") + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("JellyfinId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("JellyfinContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("JellyfinId") + .HasColumnType("longtext"); + + b.Property("ParentId") + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("JellyfinEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("ArtistId") + .HasColumnType("int"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext"); + + b.Property("Monitored") + .HasColumnType("tinyint(1)"); + + b.Property("PercentOfTracks") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TrackCount") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ArtistId") + .HasColumnType("int"); + + b.Property("ArtistName") + .HasColumnType("longtext"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext"); + + b.Property("Monitored") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("GrandparentKey") + .HasColumnType("int"); + + b.Property("Key") + .HasColumnType("int"); + + b.Property("ParentKey") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ParentKey") + .HasColumnType("int"); + + b.Property("PlexContentId") + .HasColumnType("int"); + + b.Property("PlexServerContentId") + .HasColumnType("int"); + + b.Property("SeasonKey") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("Key") + .HasColumnType("int"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("ReleaseYear") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("HasFile") + .HasColumnType("tinyint(1)"); + + b.Property("HasRegular") + .HasColumnType("tinyint(1)"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("HasFile") + .HasColumnType("tinyint(1)"); + + b.Property("MovieDbId") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.HasOne("Ombi.Store.Entities.JellyfinContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("JellyfinId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", null) + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Navigation("Episodes"); + + b.Navigation("Seasons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalMySql/20220212210902_MediaServer4k.cs b/src/Ombi.Store/Migrations/ExternalMySql/20220212210902_MediaServer4k.cs new file mode 100644 index 000000000..c7e1888a6 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalMySql/20220212210902_MediaServer4k.cs @@ -0,0 +1,48 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalMySql +{ + public partial class MediaServer4k : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Has4K", + table: "PlexServerContent", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Has4K", + table: "JellyfinContent", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Has4K", + table: "EmbyContent", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Has4K", + table: "PlexServerContent"); + + migrationBuilder.DropColumn( + name: "Has4K", + table: "JellyfinContent"); + + migrationBuilder.DropColumn( + name: "Has4K", + table: "EmbyContent"); + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalMySql/20220407114744_PlexIds.Designer.cs b/src/Ombi.Store/Migrations/ExternalMySql/20220407114744_PlexIds.Designer.cs new file mode 100644 index 000000000..e0ca84108 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalMySql/20220407114744_PlexIds.Designer.cs @@ -0,0 +1,535 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalMySql +{ + [DbContext(typeof(ExternalMySqlContext))] + [Migration("20220407114744_PlexIds")] + partial class PlexIds + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EmbyId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EmbyId") + .HasColumnType("longtext"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("ParentId") + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("JellyfinId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("JellyfinContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("JellyfinId") + .HasColumnType("longtext"); + + b.Property("ParentId") + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("JellyfinEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("ArtistId") + .HasColumnType("int"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext"); + + b.Property("Monitored") + .HasColumnType("tinyint(1)"); + + b.Property("PercentOfTracks") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TrackCount") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ArtistId") + .HasColumnType("int"); + + b.Property("ArtistName") + .HasColumnType("longtext"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext"); + + b.Property("Monitored") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("GrandparentKey") + .HasColumnType("varchar(255)"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("ParentKey") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ParentKey") + .HasColumnType("longtext"); + + b.Property("PlexContentId") + .HasColumnType("longtext"); + + b.Property("PlexServerContentId") + .HasColumnType("int"); + + b.Property("SeasonKey") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("Key") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("ReleaseYear") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("HasFile") + .HasColumnType("tinyint(1)"); + + b.Property("HasRegular") + .HasColumnType("tinyint(1)"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("HasFile") + .HasColumnType("tinyint(1)"); + + b.Property("MovieDbId") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.HasOne("Ombi.Store.Entities.JellyfinContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("JellyfinId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", null) + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Navigation("Episodes"); + + b.Navigation("Seasons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalMySql/20220407114744_PlexIds.cs b/src/Ombi.Store/Migrations/ExternalMySql/20220407114744_PlexIds.cs new file mode 100644 index 000000000..826260c93 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalMySql/20220407114744_PlexIds.cs @@ -0,0 +1,176 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalMySql +{ + public partial class PlexIds : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_PlexEpisode_PlexServerContent_GrandparentKey", + table: "PlexEpisode"); + + migrationBuilder.AlterColumn( + name: "Key", + table: "PlexServerContent", + type: "varchar(255)", + nullable: false, + oldClrType: typeof(int), + oldType: "int") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "SeasonKey", + table: "PlexSeasonsContent", + type: "longtext", + nullable: true, + oldClrType: typeof(int), + oldType: "int") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "PlexContentId", + table: "PlexSeasonsContent", + type: "longtext", + nullable: true, + oldClrType: typeof(int), + oldType: "int") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "ParentKey", + table: "PlexSeasonsContent", + type: "longtext", + nullable: true, + oldClrType: typeof(int), + oldType: "int") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "ParentKey", + table: "PlexEpisode", + type: "longtext", + nullable: true, + oldClrType: typeof(int), + oldType: "int") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Key", + table: "PlexEpisode", + type: "longtext", + nullable: true, + oldClrType: typeof(int), + oldType: "int") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "GrandparentKey", + table: "PlexEpisode", + type: "varchar(255)", + nullable: true, + oldClrType: typeof(int), + oldType: "int") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddForeignKey( + name: "FK_PlexEpisode_PlexServerContent_GrandparentKey", + table: "PlexEpisode", + column: "GrandparentKey", + principalTable: "PlexServerContent", + principalColumn: "Key"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_PlexEpisode_PlexServerContent_GrandparentKey", + table: "PlexEpisode"); + + migrationBuilder.AlterColumn( + name: "Key", + table: "PlexServerContent", + type: "int", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(255)") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "SeasonKey", + table: "PlexSeasonsContent", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "PlexContentId", + table: "PlexSeasonsContent", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "ParentKey", + table: "PlexSeasonsContent", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "ParentKey", + table: "PlexEpisode", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Key", + table: "PlexEpisode", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "GrandparentKey", + table: "PlexEpisode", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "varchar(255)", + oldNullable: true) + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddForeignKey( + name: "FK_PlexEpisode_PlexServerContent_GrandparentKey", + table: "PlexEpisode", + column: "GrandparentKey", + principalTable: "PlexServerContent", + principalColumn: "Key", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalMySql/20220411193943_WatchlistHistory.Designer.cs b/src/Ombi.Store/Migrations/ExternalMySql/20220411193943_WatchlistHistory.Designer.cs new file mode 100644 index 000000000..69d012d5d --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalMySql/20220411193943_WatchlistHistory.Designer.cs @@ -0,0 +1,549 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalMySql +{ + [DbContext(typeof(ExternalMySqlContext))] + [Migration("20220411193943_WatchlistHistory")] + partial class WatchlistHistory + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EmbyId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EmbyId") + .HasColumnType("longtext"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("ParentId") + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("JellyfinId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("JellyfinContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("JellyfinId") + .HasColumnType("longtext"); + + b.Property("ParentId") + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("JellyfinEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("ArtistId") + .HasColumnType("int"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext"); + + b.Property("Monitored") + .HasColumnType("tinyint(1)"); + + b.Property("PercentOfTracks") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TrackCount") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ArtistId") + .HasColumnType("int"); + + b.Property("ArtistName") + .HasColumnType("longtext"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext"); + + b.Property("Monitored") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("GrandparentKey") + .HasColumnType("varchar(255)"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("ParentKey") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ParentKey") + .HasColumnType("longtext"); + + b.Property("PlexContentId") + .HasColumnType("longtext"); + + b.Property("PlexServerContentId") + .HasColumnType("int"); + + b.Property("SeasonKey") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("Key") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("ReleaseYear") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexWatchlistHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TmdbId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PlexWatchlistHistory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("HasFile") + .HasColumnType("tinyint(1)"); + + b.Property("HasRegular") + .HasColumnType("tinyint(1)"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("HasFile") + .HasColumnType("tinyint(1)"); + + b.Property("MovieDbId") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.HasOne("Ombi.Store.Entities.JellyfinContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("JellyfinId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", null) + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Navigation("Episodes"); + + b.Navigation("Seasons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalMySql/20220411193943_WatchlistHistory.cs b/src/Ombi.Store/Migrations/ExternalMySql/20220411193943_WatchlistHistory.cs new file mode 100644 index 000000000..760f40c25 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalMySql/20220411193943_WatchlistHistory.cs @@ -0,0 +1,34 @@ +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalMySql +{ + public partial class WatchlistHistory : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "PlexWatchlistHistory", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + TmdbId = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_PlexWatchlistHistory", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "PlexWatchlistHistory"); + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs b/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs index dbdbe6f55..1e86ddf7b 100644 --- a/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Ombi.Store.Context.MySql; +#nullable disable + namespace Ombi.Store.Migrations.ExternalMySql { [DbContext(typeof(ExternalMySqlContext))] @@ -14,8 +16,8 @@ namespace Ombi.Store.Migrations.ExternalMySql { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("Relational:MaxIdentifierLength", 64) - .HasAnnotation("ProductVersion", "5.0.1"); + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => { @@ -44,12 +46,18 @@ namespace Ombi.Store.Migrations.ExternalMySql .IsRequired() .HasColumnType("varchar(255)"); + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + b.Property("ImdbId") .HasColumnType("longtext"); b.Property("ProviderId") .HasColumnType("longtext"); + b.Property("Quality") + .HasColumnType("longtext"); + b.Property("TheMovieDbId") .HasColumnType("longtext"); @@ -122,6 +130,9 @@ namespace Ombi.Store.Migrations.ExternalMySql b.Property("AddedAt") .HasColumnType("datetime(6)"); + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + b.Property("ImdbId") .HasColumnType("longtext"); @@ -132,6 +143,9 @@ namespace Ombi.Store.Migrations.ExternalMySql b.Property("ProviderId") .HasColumnType("longtext"); + b.Property("Quality") + .HasColumnType("longtext"); + b.Property("TheMovieDbId") .HasColumnType("longtext"); @@ -262,14 +276,14 @@ namespace Ombi.Store.Migrations.ExternalMySql b.Property("EpisodeNumber") .HasColumnType("int"); - b.Property("GrandparentKey") - .HasColumnType("int"); + b.Property("GrandparentKey") + .HasColumnType("varchar(255)"); - b.Property("Key") - .HasColumnType("int"); + b.Property("Key") + .HasColumnType("longtext"); - b.Property("ParentKey") - .HasColumnType("int"); + b.Property("ParentKey") + .HasColumnType("longtext"); b.Property("SeasonNumber") .HasColumnType("int"); @@ -290,17 +304,17 @@ namespace Ombi.Store.Migrations.ExternalMySql .ValueGeneratedOnAdd() .HasColumnType("int"); - b.Property("ParentKey") - .HasColumnType("int"); + b.Property("ParentKey") + .HasColumnType("longtext"); - b.Property("PlexContentId") - .HasColumnType("int"); + b.Property("PlexContentId") + .HasColumnType("longtext"); b.Property("PlexServerContentId") .HasColumnType("int"); - b.Property("SeasonKey") - .HasColumnType("int"); + b.Property("SeasonKey") + .HasColumnType("longtext"); b.Property("SeasonNumber") .HasColumnType("int"); @@ -321,11 +335,15 @@ namespace Ombi.Store.Migrations.ExternalMySql b.Property("AddedAt") .HasColumnType("datetime(6)"); + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + b.Property("ImdbId") .HasColumnType("longtext"); - b.Property("Key") - .HasColumnType("int"); + b.Property("Key") + .IsRequired() + .HasColumnType("varchar(255)"); b.Property("Quality") .HasColumnType("longtext"); @@ -356,15 +374,35 @@ namespace Ombi.Store.Migrations.ExternalMySql b.ToTable("PlexServerContent"); }); + modelBuilder.Entity("Ombi.Store.Entities.PlexWatchlistHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TmdbId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PlexWatchlistHistory"); + }); + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int"); + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + b.Property("HasFile") .HasColumnType("tinyint(1)"); + b.Property("HasRegular") + .HasColumnType("tinyint(1)"); + b.Property("TheMovieDbId") .HasColumnType("int"); @@ -475,9 +513,7 @@ namespace Ombi.Store.Migrations.ExternalMySql b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") .WithMany("Episodes") .HasForeignKey("GrandparentKey") - .HasPrincipalKey("Key") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + .HasPrincipalKey("Key"); b.Navigation("Series"); }); diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20220211213347_MediaServerQualities.Designer.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20220211213347_MediaServerQualities.Designer.cs new file mode 100644 index 000000000..4ec8422d5 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20220211213347_MediaServerQualities.Designer.cs @@ -0,0 +1,525 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + [DbContext(typeof(ExternalSqliteContext))] + [Migration("20220211213347_MediaServerQualities")] + partial class MediaServerQualities + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EmbyId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EmbyId") + .HasColumnType("TEXT"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("ParentId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("JellyfinId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("JellyfinContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("JellyfinId") + .HasColumnType("TEXT"); + + b.Property("ParentId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("JellyfinEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("ArtistId") + .HasColumnType("INTEGER"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("Monitored") + .HasColumnType("INTEGER"); + + b.Property("PercentOfTracks") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TrackCount") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistId") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("Monitored") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("GrandparentKey") + .HasColumnType("INTEGER"); + + b.Property("Key") + .HasColumnType("INTEGER"); + + b.Property("ParentKey") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ParentKey") + .HasColumnType("INTEGER"); + + b.Property("PlexContentId") + .HasColumnType("INTEGER"); + + b.Property("PlexServerContentId") + .HasColumnType("INTEGER"); + + b.Property("SeasonKey") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("INTEGER"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("ReleaseYear") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("HasFile") + .HasColumnType("INTEGER"); + + b.Property("HasRegular") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("HasFile") + .HasColumnType("INTEGER"); + + b.Property("MovieDbId") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.HasOne("Ombi.Store.Entities.JellyfinContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("JellyfinId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", null) + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Navigation("Episodes"); + + b.Navigation("Seasons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20220211213347_MediaServerQualities.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20220211213347_MediaServerQualities.cs new file mode 100644 index 000000000..b194b7845 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20220211213347_MediaServerQualities.cs @@ -0,0 +1,57 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + public partial class MediaServerQualities : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Has4K", + table: "RadarrCache", + type: "INTEGER", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "HasRegular", + table: "RadarrCache", + type: "INTEGER", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Quality", + table: "JellyfinContent", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "Quality", + table: "EmbyContent", + type: "TEXT", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Has4K", + table: "RadarrCache"); + + migrationBuilder.DropColumn( + name: "HasRegular", + table: "RadarrCache"); + + migrationBuilder.DropColumn( + name: "Quality", + table: "JellyfinContent"); + + migrationBuilder.DropColumn( + name: "Quality", + table: "EmbyContent"); + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20220212210807_MediaServer4k.Designer.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20220212210807_MediaServer4k.Designer.cs new file mode 100644 index 000000000..70cd280e9 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20220212210807_MediaServer4k.Designer.cs @@ -0,0 +1,534 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + [DbContext(typeof(ExternalSqliteContext))] + [Migration("20220212210807_MediaServer4k")] + partial class MediaServer4k + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EmbyId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EmbyId") + .HasColumnType("TEXT"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("ParentId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("JellyfinId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("JellyfinContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("JellyfinId") + .HasColumnType("TEXT"); + + b.Property("ParentId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("JellyfinEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("ArtistId") + .HasColumnType("INTEGER"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("Monitored") + .HasColumnType("INTEGER"); + + b.Property("PercentOfTracks") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TrackCount") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistId") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("Monitored") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("GrandparentKey") + .HasColumnType("INTEGER"); + + b.Property("Key") + .HasColumnType("INTEGER"); + + b.Property("ParentKey") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ParentKey") + .HasColumnType("INTEGER"); + + b.Property("PlexContentId") + .HasColumnType("INTEGER"); + + b.Property("PlexServerContentId") + .HasColumnType("INTEGER"); + + b.Property("SeasonKey") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("INTEGER"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("ReleaseYear") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("HasFile") + .HasColumnType("INTEGER"); + + b.Property("HasRegular") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("HasFile") + .HasColumnType("INTEGER"); + + b.Property("MovieDbId") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.HasOne("Ombi.Store.Entities.JellyfinContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("JellyfinId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", null) + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Navigation("Episodes"); + + b.Navigation("Seasons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20220212210807_MediaServer4k.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20220212210807_MediaServer4k.cs new file mode 100644 index 000000000..593465c0a --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20220212210807_MediaServer4k.cs @@ -0,0 +1,48 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + public partial class MediaServer4k : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Has4K", + table: "PlexServerContent", + type: "INTEGER", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Has4K", + table: "JellyfinContent", + type: "INTEGER", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Has4K", + table: "EmbyContent", + type: "INTEGER", + nullable: false, + defaultValue: false); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Has4K", + table: "PlexServerContent"); + + migrationBuilder.DropColumn( + name: "Has4K", + table: "JellyfinContent"); + + migrationBuilder.DropColumn( + name: "Has4K", + table: "EmbyContent"); + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20220406212825_PlexIds.Designer.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20220406212825_PlexIds.Designer.cs new file mode 100644 index 000000000..eb5a07394 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20220406212825_PlexIds.Designer.cs @@ -0,0 +1,533 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + [DbContext(typeof(ExternalSqliteContext))] + [Migration("20220406212825_PlexIds")] + partial class PlexIds + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EmbyId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EmbyId") + .HasColumnType("TEXT"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("ParentId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("JellyfinId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("JellyfinContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("JellyfinId") + .HasColumnType("TEXT"); + + b.Property("ParentId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("JellyfinEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("ArtistId") + .HasColumnType("INTEGER"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("Monitored") + .HasColumnType("INTEGER"); + + b.Property("PercentOfTracks") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TrackCount") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistId") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("Monitored") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("GrandparentKey") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("ParentKey") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ParentKey") + .HasColumnType("TEXT"); + + b.Property("PlexContentId") + .HasColumnType("TEXT"); + + b.Property("PlexServerContentId") + .HasColumnType("INTEGER"); + + b.Property("SeasonKey") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("ReleaseYear") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("HasFile") + .HasColumnType("INTEGER"); + + b.Property("HasRegular") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("HasFile") + .HasColumnType("INTEGER"); + + b.Property("MovieDbId") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.HasOne("Ombi.Store.Entities.JellyfinContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("JellyfinId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", null) + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Navigation("Episodes"); + + b.Navigation("Seasons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20220406212825_PlexIds.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20220406212825_PlexIds.cs new file mode 100644 index 000000000..4f3d92ece --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20220406212825_PlexIds.cs @@ -0,0 +1,162 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + public partial class PlexIds : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_PlexEpisode_PlexServerContent_GrandparentKey", + table: "PlexEpisode"); + + migrationBuilder.AlterColumn( + name: "Key", + table: "PlexServerContent", + type: "TEXT", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "SeasonKey", + table: "PlexSeasonsContent", + type: "TEXT", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "PlexContentId", + table: "PlexSeasonsContent", + type: "TEXT", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ParentKey", + table: "PlexSeasonsContent", + type: "TEXT", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ParentKey", + table: "PlexEpisode", + type: "TEXT", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Key", + table: "PlexEpisode", + type: "TEXT", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "GrandparentKey", + table: "PlexEpisode", + type: "TEXT", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AddForeignKey( + name: "FK_PlexEpisode_PlexServerContent_GrandparentKey", + table: "PlexEpisode", + column: "GrandparentKey", + principalTable: "PlexServerContent", + principalColumn: "Key"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_PlexEpisode_PlexServerContent_GrandparentKey", + table: "PlexEpisode"); + + migrationBuilder.AlterColumn( + name: "Key", + table: "PlexServerContent", + type: "INTEGER", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "SeasonKey", + table: "PlexSeasonsContent", + type: "INTEGER", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "PlexContentId", + table: "PlexSeasonsContent", + type: "INTEGER", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ParentKey", + table: "PlexSeasonsContent", + type: "INTEGER", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ParentKey", + table: "PlexEpisode", + type: "INTEGER", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Key", + table: "PlexEpisode", + type: "INTEGER", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "GrandparentKey", + table: "PlexEpisode", + type: "INTEGER", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AddForeignKey( + name: "FK_PlexEpisode_PlexServerContent_GrandparentKey", + table: "PlexEpisode", + column: "GrandparentKey", + principalTable: "PlexServerContent", + principalColumn: "Key", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20220411193827_WatchlistHistory.Designer.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20220411193827_WatchlistHistory.Designer.cs new file mode 100644 index 000000000..03da8c7eb --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20220411193827_WatchlistHistory.Designer.cs @@ -0,0 +1,547 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + [DbContext(typeof(ExternalSqliteContext))] + [Migration("20220411193827_WatchlistHistory")] + partial class WatchlistHistory + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EmbyId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EmbyId") + .HasColumnType("TEXT"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("ParentId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("JellyfinId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("JellyfinContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("JellyfinId") + .HasColumnType("TEXT"); + + b.Property("ParentId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("JellyfinEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("ArtistId") + .HasColumnType("INTEGER"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("Monitored") + .HasColumnType("INTEGER"); + + b.Property("PercentOfTracks") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TrackCount") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistId") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("Monitored") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("GrandparentKey") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("ParentKey") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ParentKey") + .HasColumnType("TEXT"); + + b.Property("PlexContentId") + .HasColumnType("TEXT"); + + b.Property("PlexServerContentId") + .HasColumnType("INTEGER"); + + b.Property("SeasonKey") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("ReleaseYear") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexWatchlistHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TmdbId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("PlexWatchlistHistory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("HasFile") + .HasColumnType("INTEGER"); + + b.Property("HasRegular") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("HasFile") + .HasColumnType("INTEGER"); + + b.Property("MovieDbId") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.HasOne("Ombi.Store.Entities.JellyfinContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("JellyfinId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", null) + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Navigation("Episodes"); + + b.Navigation("Seasons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20220411193827_WatchlistHistory.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20220411193827_WatchlistHistory.cs new file mode 100644 index 000000000..030cefa1d --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20220411193827_WatchlistHistory.cs @@ -0,0 +1,31 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + public partial class WatchlistHistory : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "PlexWatchlistHistory", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + TmdbId = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PlexWatchlistHistory", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "PlexWatchlistHistory"); + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/ExternalSqliteContextModelSnapshot.cs b/src/Ombi.Store/Migrations/ExternalSqlite/ExternalSqliteContextModelSnapshot.cs index 00d4f44f4..2f5de3382 100644 --- a/src/Ombi.Store/Migrations/ExternalSqlite/ExternalSqliteContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/ExternalSqlite/ExternalSqliteContextModelSnapshot.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Ombi.Store.Context.Sqlite; +#nullable disable + namespace Ombi.Store.Migrations.ExternalSqlite { [DbContext(typeof(ExternalSqliteContext))] @@ -13,8 +15,7 @@ namespace Ombi.Store.Migrations.ExternalSqlite protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "5.0.1"); + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => { @@ -43,12 +44,18 @@ namespace Ombi.Store.Migrations.ExternalSqlite .IsRequired() .HasColumnType("TEXT"); + b.Property("Has4K") + .HasColumnType("INTEGER"); + b.Property("ImdbId") .HasColumnType("TEXT"); b.Property("ProviderId") .HasColumnType("TEXT"); + b.Property("Quality") + .HasColumnType("TEXT"); + b.Property("TheMovieDbId") .HasColumnType("TEXT"); @@ -121,6 +128,9 @@ namespace Ombi.Store.Migrations.ExternalSqlite b.Property("AddedAt") .HasColumnType("TEXT"); + b.Property("Has4K") + .HasColumnType("INTEGER"); + b.Property("ImdbId") .HasColumnType("TEXT"); @@ -131,6 +141,9 @@ namespace Ombi.Store.Migrations.ExternalSqlite b.Property("ProviderId") .HasColumnType("TEXT"); + b.Property("Quality") + .HasColumnType("TEXT"); + b.Property("TheMovieDbId") .HasColumnType("TEXT"); @@ -261,14 +274,14 @@ namespace Ombi.Store.Migrations.ExternalSqlite b.Property("EpisodeNumber") .HasColumnType("INTEGER"); - b.Property("GrandparentKey") - .HasColumnType("INTEGER"); + b.Property("GrandparentKey") + .HasColumnType("TEXT"); - b.Property("Key") - .HasColumnType("INTEGER"); + b.Property("Key") + .HasColumnType("TEXT"); - b.Property("ParentKey") - .HasColumnType("INTEGER"); + b.Property("ParentKey") + .HasColumnType("TEXT"); b.Property("SeasonNumber") .HasColumnType("INTEGER"); @@ -289,17 +302,17 @@ namespace Ombi.Store.Migrations.ExternalSqlite .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); - b.Property("ParentKey") - .HasColumnType("INTEGER"); + b.Property("ParentKey") + .HasColumnType("TEXT"); - b.Property("PlexContentId") - .HasColumnType("INTEGER"); + b.Property("PlexContentId") + .HasColumnType("TEXT"); b.Property("PlexServerContentId") .HasColumnType("INTEGER"); - b.Property("SeasonKey") - .HasColumnType("INTEGER"); + b.Property("SeasonKey") + .HasColumnType("TEXT"); b.Property("SeasonNumber") .HasColumnType("INTEGER"); @@ -320,11 +333,15 @@ namespace Ombi.Store.Migrations.ExternalSqlite b.Property("AddedAt") .HasColumnType("TEXT"); + b.Property("Has4K") + .HasColumnType("INTEGER"); + b.Property("ImdbId") .HasColumnType("TEXT"); - b.Property("Key") - .HasColumnType("INTEGER"); + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT"); b.Property("Quality") .HasColumnType("TEXT"); @@ -355,15 +372,35 @@ namespace Ombi.Store.Migrations.ExternalSqlite b.ToTable("PlexServerContent"); }); + modelBuilder.Entity("Ombi.Store.Entities.PlexWatchlistHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TmdbId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("PlexWatchlistHistory"); + }); + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); + b.Property("Has4K") + .HasColumnType("INTEGER"); + b.Property("HasFile") .HasColumnType("INTEGER"); + b.Property("HasRegular") + .HasColumnType("INTEGER"); + b.Property("TheMovieDbId") .HasColumnType("INTEGER"); @@ -474,9 +511,7 @@ namespace Ombi.Store.Migrations.ExternalSqlite b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") .WithMany("Episodes") .HasForeignKey("GrandparentKey") - .HasPrincipalKey("Key") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + .HasPrincipalKey("Key"); b.Navigation("Series"); }); diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20220210195008_Radarr4kRole.Designer.cs b/src/Ombi.Store/Migrations/OmbiMySql/20220210195008_Radarr4kRole.Designer.cs new file mode 100644 index 000000000..713672bcf --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20220210195008_Radarr4kRole.Designer.cs @@ -0,0 +1,1246 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiMySql +{ + [DbContext(typeof(OmbiMySqlContext))] + [Migration("20220210195008_Radarr4kRole")] + partial class Radarr4kRole + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AuditArea") + .HasColumnType("int"); + + b.Property("AuditType") + .HasColumnType("int"); + + b.Property("DateTime") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("User") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("Message") + .HasColumnType("longtext"); + + b.Property("NotificationType") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("PlayerId") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Alias") + .HasColumnType("longtext"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("int"); + + b.Property("EpisodeRequestLimitType") + .HasColumnType("int"); + + b.Property("Language") + .HasColumnType("longtext"); + + b.Property("LastLoggedIn") + .HasColumnType("datetime(6)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("MovieRequestLimit") + .HasColumnType("int"); + + b.Property("MovieRequestLimitType") + .HasColumnType("int"); + + b.Property("MusicRequestLimit") + .HasColumnType("int"); + + b.Property("MusicRequestLimitType") + .HasColumnType("int"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("ProviderUserId") + .HasColumnType("longtext"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("StreamingCountry") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserAccessToken") + .HasColumnType("longtext"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("UserType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("AlbumId") + .HasColumnType("longtext"); + + b.Property("ContentId") + .HasColumnType("int"); + + b.Property("ContentType") + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Completed") + .HasColumnType("datetime(6)"); + + b.Property("Dts") + .HasColumnType("datetime(6)"); + + b.Property("Error") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RetryCount") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("ArtistName") + .HasColumnType("longtext"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Cover") + .HasColumnType("longtext"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("Disk") + .HasColumnType("longtext"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Rating") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("ParentRequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("SeriesType") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Comment") + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("IssuesId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IssueCategoryId") + .HasColumnType("int"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("ResovledDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("UserReportedId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Background") + .HasColumnType("longtext"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("DigitalReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("LangCode") + .HasColumnType("longtext"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("PosterPath") + .HasColumnType("longtext"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("RootPathOverride") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeCount") + .HasColumnType("int"); + + b.Property("RequestDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Background") + .HasColumnType("longtext"); + + b.Property("ExternalProviderId") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("LanguageProfile") + .HasColumnType("int"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("PosterPath") + .HasColumnType("longtext"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RootFolder") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TotalSeasons") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RadarrQualityProfile") + .HasColumnType("int"); + + b.Property("RadarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrQualityProfile") + .HasColumnType("int"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("int"); + + b.Property("SonarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("Deleted") + .HasColumnType("tinyint(1)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("VoteType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AirDate") + .HasColumnType("datetime(6)"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("Requested") + .HasColumnType("tinyint(1)"); + + b.Property("SeasonId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ChildRequestId") + .HasColumnType("int"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("ParentRequest"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Issues"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + + b.Navigation("IssueCategory"); + + b.Navigation("UserReported"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRequest"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Navigation("NotificationUserIds"); + + b.Navigation("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Navigation("Issues"); + + b.Navigation("SeasonRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Navigation("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Navigation("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Navigation("Episodes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20220210195008_Radarr4kRole.cs b/src/Ombi.Store/Migrations/OmbiMySql/20220210195008_Radarr4kRole.cs new file mode 100644 index 000000000..88eeed9f2 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20220210195008_Radarr4kRole.cs @@ -0,0 +1,20 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Ombi.Helpers; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiMySql +{ + public partial class Radarr4kRole : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.InsertRoleMySql(OmbiRoles.Request4KMovie); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20220210201011_MovieRequest4K.Designer.cs b/src/Ombi.Store/Migrations/OmbiMySql/20220210201011_MovieRequest4K.Designer.cs new file mode 100644 index 000000000..7a6c430bd --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20220210201011_MovieRequest4K.Designer.cs @@ -0,0 +1,1249 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiMySql +{ + [DbContext(typeof(OmbiMySqlContext))] + [Migration("20220210201011_MovieRequest4K")] + partial class MovieRequest4K + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AuditArea") + .HasColumnType("int"); + + b.Property("AuditType") + .HasColumnType("int"); + + b.Property("DateTime") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("User") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("Message") + .HasColumnType("longtext"); + + b.Property("NotificationType") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("PlayerId") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Alias") + .HasColumnType("longtext"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("int"); + + b.Property("EpisodeRequestLimitType") + .HasColumnType("int"); + + b.Property("Language") + .HasColumnType("longtext"); + + b.Property("LastLoggedIn") + .HasColumnType("datetime(6)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("MovieRequestLimit") + .HasColumnType("int"); + + b.Property("MovieRequestLimitType") + .HasColumnType("int"); + + b.Property("MusicRequestLimit") + .HasColumnType("int"); + + b.Property("MusicRequestLimitType") + .HasColumnType("int"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("ProviderUserId") + .HasColumnType("longtext"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("StreamingCountry") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserAccessToken") + .HasColumnType("longtext"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("UserType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("AlbumId") + .HasColumnType("longtext"); + + b.Property("ContentId") + .HasColumnType("int"); + + b.Property("ContentType") + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Completed") + .HasColumnType("datetime(6)"); + + b.Property("Dts") + .HasColumnType("datetime(6)"); + + b.Property("Error") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RetryCount") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("ArtistName") + .HasColumnType("longtext"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Cover") + .HasColumnType("longtext"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("Disk") + .HasColumnType("longtext"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Rating") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("ParentRequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("SeriesType") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Comment") + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("IssuesId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IssueCategoryId") + .HasColumnType("int"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("ResovledDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("UserReportedId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Background") + .HasColumnType("longtext"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("DigitalReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("Is4KRequest") + .HasColumnType("tinyint(1)"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("LangCode") + .HasColumnType("longtext"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("PosterPath") + .HasColumnType("longtext"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("RootPathOverride") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeCount") + .HasColumnType("int"); + + b.Property("RequestDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Background") + .HasColumnType("longtext"); + + b.Property("ExternalProviderId") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("LanguageProfile") + .HasColumnType("int"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("PosterPath") + .HasColumnType("longtext"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RootFolder") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TotalSeasons") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RadarrQualityProfile") + .HasColumnType("int"); + + b.Property("RadarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrQualityProfile") + .HasColumnType("int"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("int"); + + b.Property("SonarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("Deleted") + .HasColumnType("tinyint(1)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("VoteType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AirDate") + .HasColumnType("datetime(6)"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("Requested") + .HasColumnType("tinyint(1)"); + + b.Property("SeasonId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ChildRequestId") + .HasColumnType("int"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("ParentRequest"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Issues"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + + b.Navigation("IssueCategory"); + + b.Navigation("UserReported"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRequest"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Navigation("NotificationUserIds"); + + b.Navigation("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Navigation("Issues"); + + b.Navigation("SeasonRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Navigation("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Navigation("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Navigation("Episodes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20220210201011_MovieRequest4K.cs b/src/Ombi.Store/Migrations/OmbiMySql/20220210201011_MovieRequest4K.cs new file mode 100644 index 000000000..f9d02b876 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20220210201011_MovieRequest4K.cs @@ -0,0 +1,26 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiMySql +{ + public partial class MovieRequest4K : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Has4KRequest", + table: "MovieRequests", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Has4KRequest", + table: "MovieRequests"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20220210215019_4kMovieProperties.Designer.cs b/src/Ombi.Store/Migrations/OmbiMySql/20220210215019_4kMovieProperties.Designer.cs new file mode 100644 index 000000000..240993d15 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20220210215019_4kMovieProperties.Designer.cs @@ -0,0 +1,1273 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiMySql +{ + [DbContext(typeof(OmbiMySqlContext))] + [Migration("20220210215019_4kMovieProperties")] + partial class _4kMovieProperties + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AuditArea") + .HasColumnType("int"); + + b.Property("AuditType") + .HasColumnType("int"); + + b.Property("DateTime") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("User") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("Message") + .HasColumnType("longtext"); + + b.Property("NotificationType") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("PlayerId") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Alias") + .HasColumnType("longtext"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("int"); + + b.Property("EpisodeRequestLimitType") + .HasColumnType("int"); + + b.Property("Language") + .HasColumnType("longtext"); + + b.Property("LastLoggedIn") + .HasColumnType("datetime(6)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("MovieRequestLimit") + .HasColumnType("int"); + + b.Property("MovieRequestLimitType") + .HasColumnType("int"); + + b.Property("MusicRequestLimit") + .HasColumnType("int"); + + b.Property("MusicRequestLimitType") + .HasColumnType("int"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("ProviderUserId") + .HasColumnType("longtext"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("StreamingCountry") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserAccessToken") + .HasColumnType("longtext"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("UserType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("AlbumId") + .HasColumnType("longtext"); + + b.Property("ContentId") + .HasColumnType("int"); + + b.Property("ContentType") + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Completed") + .HasColumnType("datetime(6)"); + + b.Property("Dts") + .HasColumnType("datetime(6)"); + + b.Property("Error") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RetryCount") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("ArtistName") + .HasColumnType("longtext"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Cover") + .HasColumnType("longtext"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("Disk") + .HasColumnType("longtext"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Rating") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("ParentRequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("SeriesType") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Comment") + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("IssuesId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IssueCategoryId") + .HasColumnType("int"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("ResovledDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("UserReportedId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Approved4K") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Available4K") + .HasColumnType("tinyint(1)"); + + b.Property("Background") + .HasColumnType("longtext"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("Denied4K") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("DeniedReason4K") + .HasColumnType("longtext"); + + b.Property("DigitalReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("Has4KRequest") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("LangCode") + .HasColumnType("longtext"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsApproved4K") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable4K") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied4K") + .HasColumnType("datetime(6)"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("PosterPath") + .HasColumnType("longtext"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedDate4k") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("RootPathOverride") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeCount") + .HasColumnType("int"); + + b.Property("RequestDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Background") + .HasColumnType("longtext"); + + b.Property("ExternalProviderId") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("LanguageProfile") + .HasColumnType("int"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("PosterPath") + .HasColumnType("longtext"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RootFolder") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TotalSeasons") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RadarrQualityProfile") + .HasColumnType("int"); + + b.Property("RadarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrQualityProfile") + .HasColumnType("int"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("int"); + + b.Property("SonarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("Deleted") + .HasColumnType("tinyint(1)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("VoteType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AirDate") + .HasColumnType("datetime(6)"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("Requested") + .HasColumnType("tinyint(1)"); + + b.Property("SeasonId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ChildRequestId") + .HasColumnType("int"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("ParentRequest"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Issues"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + + b.Navigation("IssueCategory"); + + b.Navigation("UserReported"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRequest"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Navigation("NotificationUserIds"); + + b.Navigation("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Navigation("Issues"); + + b.Navigation("SeasonRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Navigation("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Navigation("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Navigation("Episodes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20220210215019_4kMovieProperties.cs b/src/Ombi.Store/Migrations/OmbiMySql/20220210215019_4kMovieProperties.cs new file mode 100644 index 000000000..3b599c0e0 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20220210215019_4kMovieProperties.cs @@ -0,0 +1,102 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiMySql +{ + public partial class _4kMovieProperties : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Approved4K", + table: "MovieRequests", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Available4K", + table: "MovieRequests", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Denied4K", + table: "MovieRequests", + type: "tinyint(1)", + nullable: true); + + migrationBuilder.AddColumn( + name: "DeniedReason4K", + table: "MovieRequests", + type: "longtext", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "MarkedAsApproved4K", + table: "MovieRequests", + type: "datetime(6)", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.AddColumn( + name: "MarkedAsAvailable4K", + table: "MovieRequests", + type: "datetime(6)", + nullable: true); + + migrationBuilder.AddColumn( + name: "MarkedAsDenied4K", + table: "MovieRequests", + type: "datetime(6)", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.AddColumn( + name: "RequestedDate4k", + table: "MovieRequests", + type: "datetime(6)", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Approved4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "Available4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "Denied4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "DeniedReason4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "MarkedAsApproved4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "MarkedAsAvailable4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "MarkedAsDenied4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "RequestedDate4k", + table: "MovieRequests"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20220407114619_RequestSource.Designer.cs b/src/Ombi.Store/Migrations/OmbiMySql/20220407114619_RequestSource.Designer.cs new file mode 100644 index 000000000..c4d1fd2f1 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20220407114619_RequestSource.Designer.cs @@ -0,0 +1,1285 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiMySql +{ + [DbContext(typeof(OmbiMySqlContext))] + [Migration("20220407114619_RequestSource")] + partial class RequestSource + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AuditArea") + .HasColumnType("int"); + + b.Property("AuditType") + .HasColumnType("int"); + + b.Property("DateTime") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("User") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("Message") + .HasColumnType("longtext"); + + b.Property("NotificationType") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("PlayerId") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Alias") + .HasColumnType("longtext"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("int"); + + b.Property("EpisodeRequestLimitType") + .HasColumnType("int"); + + b.Property("Language") + .HasColumnType("longtext"); + + b.Property("LastLoggedIn") + .HasColumnType("datetime(6)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("MediaServerToken") + .HasColumnType("longtext"); + + b.Property("MovieRequestLimit") + .HasColumnType("int"); + + b.Property("MovieRequestLimitType") + .HasColumnType("int"); + + b.Property("MusicRequestLimit") + .HasColumnType("int"); + + b.Property("MusicRequestLimitType") + .HasColumnType("int"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("ProviderUserId") + .HasColumnType("longtext"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("StreamingCountry") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserAccessToken") + .HasColumnType("longtext"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("UserType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("AlbumId") + .HasColumnType("longtext"); + + b.Property("ContentId") + .HasColumnType("int"); + + b.Property("ContentType") + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Completed") + .HasColumnType("datetime(6)"); + + b.Property("Dts") + .HasColumnType("datetime(6)"); + + b.Property("Error") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RetryCount") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("ArtistName") + .HasColumnType("longtext"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Cover") + .HasColumnType("longtext"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("Disk") + .HasColumnType("longtext"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Rating") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("Source") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("ParentRequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("SeriesType") + .HasColumnType("int"); + + b.Property("Source") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Comment") + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("IssuesId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IssueCategoryId") + .HasColumnType("int"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("ResovledDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("UserReportedId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Approved4K") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Available4K") + .HasColumnType("tinyint(1)"); + + b.Property("Background") + .HasColumnType("longtext"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("Denied4K") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("DeniedReason4K") + .HasColumnType("longtext"); + + b.Property("DigitalReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("Has4KRequest") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("LangCode") + .HasColumnType("longtext"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsApproved4K") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable4K") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied4K") + .HasColumnType("datetime(6)"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("PosterPath") + .HasColumnType("longtext"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedDate4k") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("RootPathOverride") + .HasColumnType("int"); + + b.Property("Source") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeCount") + .HasColumnType("int"); + + b.Property("RequestDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Background") + .HasColumnType("longtext"); + + b.Property("ExternalProviderId") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("LanguageProfile") + .HasColumnType("int"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("PosterPath") + .HasColumnType("longtext"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RootFolder") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TotalSeasons") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RadarrQualityProfile") + .HasColumnType("int"); + + b.Property("RadarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrQualityProfile") + .HasColumnType("int"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("int"); + + b.Property("SonarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("Deleted") + .HasColumnType("tinyint(1)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("VoteType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AirDate") + .HasColumnType("datetime(6)"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("Requested") + .HasColumnType("tinyint(1)"); + + b.Property("SeasonId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ChildRequestId") + .HasColumnType("int"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("ParentRequest"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Issues"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + + b.Navigation("IssueCategory"); + + b.Navigation("UserReported"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRequest"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Navigation("NotificationUserIds"); + + b.Navigation("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Navigation("Issues"); + + b.Navigation("SeasonRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Navigation("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Navigation("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Navigation("Episodes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20220407114619_RequestSource.cs b/src/Ombi.Store/Migrations/OmbiMySql/20220407114619_RequestSource.cs new file mode 100644 index 000000000..1020b4d63 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20220407114619_RequestSource.cs @@ -0,0 +1,59 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiMySql +{ + public partial class RequestSource : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Source", + table: "MovieRequests", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "Source", + table: "ChildRequests", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "MediaServerToken", + table: "AspNetUsers", + type: "longtext", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "Source", + table: "AlbumRequests", + type: "int", + nullable: false, + defaultValue: 0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Source", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "Source", + table: "ChildRequests"); + + migrationBuilder.DropColumn( + name: "MediaServerToken", + table: "AspNetUsers"); + + migrationBuilder.DropColumn( + name: "Source", + table: "AlbumRequests"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs index 8fdebc4c2..e66e29521 100644 --- a/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Ombi.Store.Context.MySql; +#nullable disable + namespace Ombi.Store.Migrations.OmbiMySql { [DbContext(typeof(OmbiMySqlContext))] @@ -14,8 +16,8 @@ namespace Ombi.Store.Migrations.OmbiMySql { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("Relational:MaxIdentifierLength", 64) - .HasAnnotation("ProductVersion", "5.0.1"); + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { @@ -40,7 +42,7 @@ namespace Ombi.Store.Migrations.OmbiMySql .IsUnique() .HasDatabaseName("RoleNameIndex"); - b.ToTable("AspNetRoles"); + b.ToTable("AspNetRoles", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => @@ -63,7 +65,7 @@ namespace Ombi.Store.Migrations.OmbiMySql b.HasIndex("RoleId"); - b.ToTable("AspNetRoleClaims"); + b.ToTable("AspNetRoleClaims", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => @@ -86,7 +88,7 @@ namespace Ombi.Store.Migrations.OmbiMySql b.HasIndex("UserId"); - b.ToTable("AspNetUserClaims"); + b.ToTable("AspNetUserClaims", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => @@ -108,7 +110,7 @@ namespace Ombi.Store.Migrations.OmbiMySql b.HasIndex("UserId"); - b.ToTable("AspNetUserLogins"); + b.ToTable("AspNetUserLogins", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => @@ -123,7 +125,7 @@ namespace Ombi.Store.Migrations.OmbiMySql b.HasIndex("RoleId"); - b.ToTable("AspNetUserRoles"); + b.ToTable("AspNetUserRoles", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => @@ -142,7 +144,7 @@ namespace Ombi.Store.Migrations.OmbiMySql b.HasKey("UserId", "LoginProvider", "Name"); - b.ToTable("AspNetUserTokens"); + b.ToTable("AspNetUserTokens", (string)null); }); modelBuilder.Entity("Ombi.Store.Entities.Audit", b => @@ -281,6 +283,9 @@ namespace Ombi.Store.Migrations.OmbiMySql b.Property("LockoutEnd") .HasColumnType("datetime(6)"); + b.Property("MediaServerToken") + .HasColumnType("longtext"); + b.Property("MovieRequestLimit") .HasColumnType("int"); @@ -342,7 +347,7 @@ namespace Ombi.Store.Migrations.OmbiMySql .IsUnique() .HasDatabaseName("UserNameIndex"); - b.ToTable("AspNetUsers"); + b.ToTable("AspNetUsers", (string)null); }); modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => @@ -406,28 +411,6 @@ namespace Ombi.Store.Migrations.OmbiMySql b.ToTable("RequestQueue"); }); - modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("RequestId") - .HasColumnType("int"); - - b.Property("RequestType") - .HasColumnType("int"); - - b.Property("UserId") - .HasColumnType("varchar(255)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("RequestSubscription"); - }); - modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => { b.Property("Id") @@ -488,6 +471,9 @@ namespace Ombi.Store.Migrations.OmbiMySql b.Property("RequestedUserId") .HasColumnType("varchar(255)"); + b.Property("Source") + .HasColumnType("int"); + b.Property("Title") .HasColumnType("longtext"); @@ -546,6 +532,9 @@ namespace Ombi.Store.Migrations.OmbiMySql b.Property("SeriesType") .HasColumnType("int"); + b.Property("Source") + .HasColumnType("int"); + b.Property("Title") .HasColumnType("longtext"); @@ -661,21 +650,36 @@ namespace Ombi.Store.Migrations.OmbiMySql b.Property("Approved") .HasColumnType("tinyint(1)"); + b.Property("Approved4K") + .HasColumnType("tinyint(1)"); + b.Property("Available") .HasColumnType("tinyint(1)"); + b.Property("Available4K") + .HasColumnType("tinyint(1)"); + b.Property("Background") .HasColumnType("longtext"); b.Property("Denied") .HasColumnType("tinyint(1)"); + b.Property("Denied4K") + .HasColumnType("tinyint(1)"); + b.Property("DeniedReason") .HasColumnType("longtext"); + b.Property("DeniedReason4K") + .HasColumnType("longtext"); + b.Property("DigitalReleaseDate") .HasColumnType("datetime(6)"); + b.Property("Has4KRequest") + .HasColumnType("tinyint(1)"); + b.Property("ImdbId") .HasColumnType("longtext"); @@ -688,12 +692,21 @@ namespace Ombi.Store.Migrations.OmbiMySql b.Property("MarkedAsApproved") .HasColumnType("datetime(6)"); + b.Property("MarkedAsApproved4K") + .HasColumnType("datetime(6)"); + b.Property("MarkedAsAvailable") .HasColumnType("datetime(6)"); + b.Property("MarkedAsAvailable4K") + .HasColumnType("datetime(6)"); + b.Property("MarkedAsDenied") .HasColumnType("datetime(6)"); + b.Property("MarkedAsDenied4K") + .HasColumnType("datetime(6)"); + b.Property("Overview") .HasColumnType("longtext"); @@ -715,12 +728,18 @@ namespace Ombi.Store.Migrations.OmbiMySql b.Property("RequestedDate") .HasColumnType("datetime(6)"); + b.Property("RequestedDate4k") + .HasColumnType("datetime(6)"); + b.Property("RequestedUserId") .HasColumnType("varchar(255)"); b.Property("RootPathOverride") .HasColumnType("int"); + b.Property("Source") + .HasColumnType("int"); + b.Property("Status") .HasColumnType("longtext"); @@ -815,6 +834,28 @@ namespace Ombi.Store.Migrations.OmbiMySql b.ToTable("TvRequests"); }); + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => { b.Property("Id") @@ -1052,15 +1093,6 @@ namespace Ombi.Store.Migrations.OmbiMySql b.Navigation("User"); }); - modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => - { - b.HasOne("Ombi.Store.Entities.OmbiUser", "User") - .WithMany() - .HasForeignKey("UserId"); - - b.Navigation("User"); - }); - modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => { b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") @@ -1145,6 +1177,15 @@ namespace Ombi.Store.Migrations.OmbiMySql b.Navigation("User"); }); + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => { b.HasOne("Ombi.Store.Entities.OmbiUser", "User") diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20220210194758_Radarr4kRole.Designer.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20220210194758_Radarr4kRole.Designer.cs new file mode 100644 index 000000000..e2c442a23 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20220210194758_Radarr4kRole.Designer.cs @@ -0,0 +1,1244 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + [DbContext(typeof(OmbiSqliteContext))] + [Migration("20220210194758_Radarr4kRole")] + partial class Radarr4kRole + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuditArea") + .HasColumnType("INTEGER"); + + b.Property("AuditType") + .HasColumnType("INTEGER"); + + b.Property("DateTime") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("User") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NotificationType") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("PlayerId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("Alias") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("Language") + .HasColumnType("TEXT"); + + b.Property("LastLoggedIn") + .HasColumnType("TEXT"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("MovieRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MovieRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("ProviderUserId") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("StreamingCountry") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserAccessToken") + .HasColumnType("TEXT"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("UserType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("AlbumId") + .HasColumnType("TEXT"); + + b.Property("ContentId") + .HasColumnType("INTEGER"); + + b.Property("ContentType") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Completed") + .HasColumnType("TEXT"); + + b.Property("Dts") + .HasColumnType("TEXT"); + + b.Property("Error") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RetryCount") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Cover") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("Disk") + .HasColumnType("TEXT"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Rating") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("ParentRequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("SeriesType") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("IssuesId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDate") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IssueCategoryId") + .HasColumnType("INTEGER"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("ResovledDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("UserReportedId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("DigitalReleaseDate") + .HasColumnType("TEXT"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("LangCode") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("RootPathOverride") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeCount") + .HasColumnType("INTEGER"); + + b.Property("RequestDate") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("ExternalProviderId") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("LanguageProfile") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RootFolder") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TotalSeasons") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RadarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("RadarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("Deleted") + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("VoteType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AirDate") + .HasColumnType("TEXT"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("Requested") + .HasColumnType("INTEGER"); + + b.Property("SeasonId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChildRequestId") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("ParentRequest"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Issues"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + + b.Navigation("IssueCategory"); + + b.Navigation("UserReported"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRequest"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Navigation("NotificationUserIds"); + + b.Navigation("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Navigation("Issues"); + + b.Navigation("SeasonRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Navigation("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Navigation("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Navigation("Episodes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20220210194758_Radarr4kRole.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20220210194758_Radarr4kRole.cs new file mode 100644 index 000000000..a97de9011 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20220210194758_Radarr4kRole.cs @@ -0,0 +1,20 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Ombi.Helpers; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + public partial class Radarr4kRole : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.InsertRole(OmbiRoles.Request4KMovie); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20220210200338_MovieRequest4K.Designer.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20220210200338_MovieRequest4K.Designer.cs new file mode 100644 index 000000000..a2dee4283 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20220210200338_MovieRequest4K.Designer.cs @@ -0,0 +1,1247 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + [DbContext(typeof(OmbiSqliteContext))] + [Migration("20220210200338_MovieRequest4K")] + partial class MovieRequest4K + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuditArea") + .HasColumnType("INTEGER"); + + b.Property("AuditType") + .HasColumnType("INTEGER"); + + b.Property("DateTime") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("User") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NotificationType") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("PlayerId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("Alias") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("Language") + .HasColumnType("TEXT"); + + b.Property("LastLoggedIn") + .HasColumnType("TEXT"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("MovieRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MovieRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("ProviderUserId") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("StreamingCountry") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserAccessToken") + .HasColumnType("TEXT"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("UserType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("AlbumId") + .HasColumnType("TEXT"); + + b.Property("ContentId") + .HasColumnType("INTEGER"); + + b.Property("ContentType") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Completed") + .HasColumnType("TEXT"); + + b.Property("Dts") + .HasColumnType("TEXT"); + + b.Property("Error") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RetryCount") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Cover") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("Disk") + .HasColumnType("TEXT"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Rating") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("ParentRequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("SeriesType") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("IssuesId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDate") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IssueCategoryId") + .HasColumnType("INTEGER"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("ResovledDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("UserReportedId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("DigitalReleaseDate") + .HasColumnType("TEXT"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("Is4KRequest") + .HasColumnType("INTEGER"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("LangCode") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("RootPathOverride") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeCount") + .HasColumnType("INTEGER"); + + b.Property("RequestDate") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("ExternalProviderId") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("LanguageProfile") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RootFolder") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TotalSeasons") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RadarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("RadarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("Deleted") + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("VoteType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AirDate") + .HasColumnType("TEXT"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("Requested") + .HasColumnType("INTEGER"); + + b.Property("SeasonId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChildRequestId") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("ParentRequest"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Issues"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + + b.Navigation("IssueCategory"); + + b.Navigation("UserReported"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRequest"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Navigation("NotificationUserIds"); + + b.Navigation("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Navigation("Issues"); + + b.Navigation("SeasonRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Navigation("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Navigation("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Navigation("Episodes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20220210200338_MovieRequest4K.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20220210200338_MovieRequest4K.cs new file mode 100644 index 000000000..8d70a0358 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20220210200338_MovieRequest4K.cs @@ -0,0 +1,26 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + public partial class MovieRequest4K : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Has4KRequest", + table: "MovieRequests", + type: "INTEGER", + nullable: false, + defaultValue: false); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Has4KRequest", + table: "MovieRequests"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20220210214920_4kMovieProperties.Designer.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20220210214920_4kMovieProperties.Designer.cs new file mode 100644 index 000000000..e315e78ea --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20220210214920_4kMovieProperties.Designer.cs @@ -0,0 +1,1271 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + [DbContext(typeof(OmbiSqliteContext))] + [Migration("20220210214920_4kMovieProperties")] + partial class _4kMovieProperties + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuditArea") + .HasColumnType("INTEGER"); + + b.Property("AuditType") + .HasColumnType("INTEGER"); + + b.Property("DateTime") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("User") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NotificationType") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("PlayerId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("Alias") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("Language") + .HasColumnType("TEXT"); + + b.Property("LastLoggedIn") + .HasColumnType("TEXT"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("MovieRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MovieRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("ProviderUserId") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("StreamingCountry") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserAccessToken") + .HasColumnType("TEXT"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("UserType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("AlbumId") + .HasColumnType("TEXT"); + + b.Property("ContentId") + .HasColumnType("INTEGER"); + + b.Property("ContentType") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Completed") + .HasColumnType("TEXT"); + + b.Property("Dts") + .HasColumnType("TEXT"); + + b.Property("Error") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RetryCount") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Cover") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("Disk") + .HasColumnType("TEXT"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Rating") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("ParentRequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("SeriesType") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("IssuesId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDate") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IssueCategoryId") + .HasColumnType("INTEGER"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("ResovledDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("UserReportedId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Approved4K") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Available4K") + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("Denied4K") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("DeniedReason4K") + .HasColumnType("TEXT"); + + b.Property("DigitalReleaseDate") + .HasColumnType("TEXT"); + + b.Property("Has4KRequest") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("LangCode") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved4K") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable4K") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied4K") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedDate4k") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("RootPathOverride") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeCount") + .HasColumnType("INTEGER"); + + b.Property("RequestDate") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("ExternalProviderId") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("LanguageProfile") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RootFolder") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TotalSeasons") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RadarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("RadarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("Deleted") + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("VoteType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AirDate") + .HasColumnType("TEXT"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("Requested") + .HasColumnType("INTEGER"); + + b.Property("SeasonId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChildRequestId") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("ParentRequest"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Issues"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + + b.Navigation("IssueCategory"); + + b.Navigation("UserReported"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRequest"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Navigation("NotificationUserIds"); + + b.Navigation("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Navigation("Issues"); + + b.Navigation("SeasonRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Navigation("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Navigation("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Navigation("Episodes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20220210214920_4kMovieProperties.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20220210214920_4kMovieProperties.cs new file mode 100644 index 000000000..38f010eae --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20220210214920_4kMovieProperties.cs @@ -0,0 +1,101 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + public partial class _4kMovieProperties : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Approved4K", + table: "MovieRequests", + type: "INTEGER", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Available4K", + table: "MovieRequests", + type: "INTEGER", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Denied4K", + table: "MovieRequests", + type: "INTEGER", + nullable: true); + + migrationBuilder.AddColumn( + name: "DeniedReason4K", + table: "MovieRequests", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "MarkedAsApproved4K", + table: "MovieRequests", + type: "TEXT", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.AddColumn( + name: "MarkedAsAvailable4K", + table: "MovieRequests", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "MarkedAsDenied4K", + table: "MovieRequests", + type: "TEXT", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.AddColumn( + name: "RequestedDate4k", + table: "MovieRequests", + type: "TEXT", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Approved4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "Available4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "Denied4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "DeniedReason4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "MarkedAsApproved4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "MarkedAsAvailable4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "MarkedAsDenied4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "RequestedDate4k", + table: "MovieRequests"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20220406213123_PlexIds.Designer.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20220406213123_PlexIds.Designer.cs new file mode 100644 index 000000000..2d3d8c76c --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20220406213123_PlexIds.Designer.cs @@ -0,0 +1,1274 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + [DbContext(typeof(OmbiSqliteContext))] + [Migration("20220406213123_PlexIds")] + partial class PlexIds + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuditArea") + .HasColumnType("INTEGER"); + + b.Property("AuditType") + .HasColumnType("INTEGER"); + + b.Property("DateTime") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("User") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NotificationType") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("PlayerId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("Alias") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("Language") + .HasColumnType("TEXT"); + + b.Property("LastLoggedIn") + .HasColumnType("TEXT"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("MediaServerToken") + .HasColumnType("TEXT"); + + b.Property("MovieRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MovieRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("ProviderUserId") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("StreamingCountry") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserAccessToken") + .HasColumnType("TEXT"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("UserType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("AlbumId") + .HasColumnType("TEXT"); + + b.Property("ContentId") + .HasColumnType("INTEGER"); + + b.Property("ContentType") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Completed") + .HasColumnType("TEXT"); + + b.Property("Dts") + .HasColumnType("TEXT"); + + b.Property("Error") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RetryCount") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Cover") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("Disk") + .HasColumnType("TEXT"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Rating") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("ParentRequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("SeriesType") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("IssuesId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDate") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IssueCategoryId") + .HasColumnType("INTEGER"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("ResovledDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("UserReportedId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Approved4K") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Available4K") + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("Denied4K") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("DeniedReason4K") + .HasColumnType("TEXT"); + + b.Property("DigitalReleaseDate") + .HasColumnType("TEXT"); + + b.Property("Has4KRequest") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("LangCode") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved4K") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable4K") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied4K") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedDate4k") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("RootPathOverride") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeCount") + .HasColumnType("INTEGER"); + + b.Property("RequestDate") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("ExternalProviderId") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("LanguageProfile") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RootFolder") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TotalSeasons") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RadarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("RadarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("Deleted") + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("VoteType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AirDate") + .HasColumnType("TEXT"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("Requested") + .HasColumnType("INTEGER"); + + b.Property("SeasonId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChildRequestId") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("ParentRequest"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Issues"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + + b.Navigation("IssueCategory"); + + b.Navigation("UserReported"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRequest"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Navigation("NotificationUserIds"); + + b.Navigation("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Navigation("Issues"); + + b.Navigation("SeasonRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Navigation("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Navigation("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Navigation("Episodes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20220406213123_PlexIds.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20220406213123_PlexIds.cs new file mode 100644 index 000000000..b83d441a0 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20220406213123_PlexIds.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + public partial class PlexIds : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "MediaServerToken", + table: "AspNetUsers", + type: "TEXT", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "MediaServerToken", + table: "AspNetUsers"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20220407072656_RequestSource.Designer.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20220407072656_RequestSource.Designer.cs new file mode 100644 index 000000000..32f92ff6c --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20220407072656_RequestSource.Designer.cs @@ -0,0 +1,1283 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + [DbContext(typeof(OmbiSqliteContext))] + [Migration("20220407072656_RequestSource")] + partial class RequestSource + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuditArea") + .HasColumnType("INTEGER"); + + b.Property("AuditType") + .HasColumnType("INTEGER"); + + b.Property("DateTime") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("User") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NotificationType") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("PlayerId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("Alias") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("Language") + .HasColumnType("TEXT"); + + b.Property("LastLoggedIn") + .HasColumnType("TEXT"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("MediaServerToken") + .HasColumnType("TEXT"); + + b.Property("MovieRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MovieRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("ProviderUserId") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("StreamingCountry") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserAccessToken") + .HasColumnType("TEXT"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("UserType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("AlbumId") + .HasColumnType("TEXT"); + + b.Property("ContentId") + .HasColumnType("INTEGER"); + + b.Property("ContentType") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Completed") + .HasColumnType("TEXT"); + + b.Property("Dts") + .HasColumnType("TEXT"); + + b.Property("Error") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RetryCount") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Cover") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("Disk") + .HasColumnType("TEXT"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Rating") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("Source") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("ParentRequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("SeriesType") + .HasColumnType("INTEGER"); + + b.Property("Source") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("IssuesId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDate") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IssueCategoryId") + .HasColumnType("INTEGER"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("ResovledDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("UserReportedId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Approved4K") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Available4K") + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("Denied4K") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("DeniedReason4K") + .HasColumnType("TEXT"); + + b.Property("DigitalReleaseDate") + .HasColumnType("TEXT"); + + b.Property("Has4KRequest") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("LangCode") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved4K") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable4K") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied4K") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedDate4k") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("RootPathOverride") + .HasColumnType("INTEGER"); + + b.Property("Source") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeCount") + .HasColumnType("INTEGER"); + + b.Property("RequestDate") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("ExternalProviderId") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("LanguageProfile") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RootFolder") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TotalSeasons") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RadarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("RadarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("Deleted") + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("VoteType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AirDate") + .HasColumnType("TEXT"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("Requested") + .HasColumnType("INTEGER"); + + b.Property("SeasonId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChildRequestId") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("ParentRequest"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Issues"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + + b.Navigation("IssueCategory"); + + b.Navigation("UserReported"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRequest"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Navigation("NotificationUserIds"); + + b.Navigation("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Navigation("Issues"); + + b.Navigation("SeasonRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Navigation("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Navigation("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Navigation("Episodes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20220407072656_RequestSource.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20220407072656_RequestSource.cs new file mode 100644 index 000000000..c1a2400d0 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20220407072656_RequestSource.cs @@ -0,0 +1,48 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + public partial class RequestSource : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Source", + table: "MovieRequests", + type: "INTEGER", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "Source", + table: "ChildRequests", + type: "INTEGER", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "Source", + table: "AlbumRequests", + type: "INTEGER", + nullable: false, + defaultValue: 0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Source", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "Source", + table: "ChildRequests"); + + migrationBuilder.DropColumn( + name: "Source", + table: "AlbumRequests"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs index 46a00353e..f9ce86bae 100644 --- a/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Ombi.Store.Context.Sqlite; +#nullable disable + namespace Ombi.Store.Migrations.OmbiSqlite { [DbContext(typeof(OmbiSqliteContext))] @@ -13,8 +15,7 @@ namespace Ombi.Store.Migrations.OmbiSqlite protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "5.0.1"); + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { @@ -39,7 +40,7 @@ namespace Ombi.Store.Migrations.OmbiSqlite .IsUnique() .HasDatabaseName("RoleNameIndex"); - b.ToTable("AspNetRoles"); + b.ToTable("AspNetRoles", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => @@ -62,7 +63,7 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.HasIndex("RoleId"); - b.ToTable("AspNetRoleClaims"); + b.ToTable("AspNetRoleClaims", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => @@ -85,7 +86,7 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.HasIndex("UserId"); - b.ToTable("AspNetUserClaims"); + b.ToTable("AspNetUserClaims", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => @@ -107,7 +108,7 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.HasIndex("UserId"); - b.ToTable("AspNetUserLogins"); + b.ToTable("AspNetUserLogins", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => @@ -122,7 +123,7 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.HasIndex("RoleId"); - b.ToTable("AspNetUserRoles"); + b.ToTable("AspNetUserRoles", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => @@ -141,7 +142,7 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.HasKey("UserId", "LoginProvider", "Name"); - b.ToTable("AspNetUserTokens"); + b.ToTable("AspNetUserTokens", (string)null); }); modelBuilder.Entity("Ombi.Store.Entities.Audit", b => @@ -280,6 +281,9 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.Property("LockoutEnd") .HasColumnType("TEXT"); + b.Property("MediaServerToken") + .HasColumnType("TEXT"); + b.Property("MovieRequestLimit") .HasColumnType("INTEGER"); @@ -341,7 +345,7 @@ namespace Ombi.Store.Migrations.OmbiSqlite .IsUnique() .HasDatabaseName("UserNameIndex"); - b.ToTable("AspNetUsers"); + b.ToTable("AspNetUsers", (string)null); }); modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => @@ -405,28 +409,6 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.ToTable("RequestQueue"); }); - modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("RequestId") - .HasColumnType("INTEGER"); - - b.Property("RequestType") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("RequestSubscription"); - }); - modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => { b.Property("Id") @@ -487,6 +469,9 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.Property("RequestedUserId") .HasColumnType("TEXT"); + b.Property("Source") + .HasColumnType("INTEGER"); + b.Property("Title") .HasColumnType("TEXT"); @@ -545,6 +530,9 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.Property("SeriesType") .HasColumnType("INTEGER"); + b.Property("Source") + .HasColumnType("INTEGER"); + b.Property("Title") .HasColumnType("TEXT"); @@ -660,21 +648,36 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.Property("Approved") .HasColumnType("INTEGER"); + b.Property("Approved4K") + .HasColumnType("INTEGER"); + b.Property("Available") .HasColumnType("INTEGER"); + b.Property("Available4K") + .HasColumnType("INTEGER"); + b.Property("Background") .HasColumnType("TEXT"); b.Property("Denied") .HasColumnType("INTEGER"); + b.Property("Denied4K") + .HasColumnType("INTEGER"); + b.Property("DeniedReason") .HasColumnType("TEXT"); + b.Property("DeniedReason4K") + .HasColumnType("TEXT"); + b.Property("DigitalReleaseDate") .HasColumnType("TEXT"); + b.Property("Has4KRequest") + .HasColumnType("INTEGER"); + b.Property("ImdbId") .HasColumnType("TEXT"); @@ -687,12 +690,21 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.Property("MarkedAsApproved") .HasColumnType("TEXT"); + b.Property("MarkedAsApproved4K") + .HasColumnType("TEXT"); + b.Property("MarkedAsAvailable") .HasColumnType("TEXT"); + b.Property("MarkedAsAvailable4K") + .HasColumnType("TEXT"); + b.Property("MarkedAsDenied") .HasColumnType("TEXT"); + b.Property("MarkedAsDenied4K") + .HasColumnType("TEXT"); + b.Property("Overview") .HasColumnType("TEXT"); @@ -714,12 +726,18 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.Property("RequestedDate") .HasColumnType("TEXT"); + b.Property("RequestedDate4k") + .HasColumnType("TEXT"); + b.Property("RequestedUserId") .HasColumnType("TEXT"); b.Property("RootPathOverride") .HasColumnType("INTEGER"); + b.Property("Source") + .HasColumnType("INTEGER"); + b.Property("Status") .HasColumnType("TEXT"); @@ -814,6 +832,28 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.ToTable("TvRequests"); }); + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => { b.Property("Id") @@ -1051,15 +1091,6 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.Navigation("User"); }); - modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => - { - b.HasOne("Ombi.Store.Entities.OmbiUser", "User") - .WithMany() - .HasForeignKey("UserId"); - - b.Navigation("User"); - }); - modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => { b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") @@ -1144,6 +1175,15 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.Navigation("User"); }); + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => { b.HasOne("Ombi.Store.Entities.OmbiUser", "User") diff --git a/src/Ombi.Store/Ombi.Store.csproj b/src/Ombi.Store/Ombi.Store.csproj index f35da548f..1c145f55a 100644 --- a/src/Ombi.Store/Ombi.Store.csproj +++ b/src/Ombi.Store/Ombi.Store.csproj @@ -7,7 +7,7 @@ true - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Store/Repository/EmbyContentRepository.cs b/src/Ombi.Store/Repository/EmbyContentRepository.cs index f8743e30f..df88d8292 100644 --- a/src/Ombi.Store/Repository/EmbyContentRepository.cs +++ b/src/Ombi.Store/Repository/EmbyContentRepository.cs @@ -25,7 +25,6 @@ // ************************************************************************/ #endregion -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -35,17 +34,12 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public class EmbyContentRepository : ExternalRepository, IEmbyContentRepository + public class EmbyContentRepository : MediaServerContentRepository, IEmbyContentRepository { - public EmbyContentRepository(ExternalContext db):base(db) { - Db = db; } - private ExternalContext Db { get; } - - public async Task GetByImdbId(string imdbid) { return await Db.EmbyContent.FirstOrDefaultAsync(x => x.ImdbId == imdbid); @@ -69,20 +63,20 @@ namespace Ombi.Store.Repository return await Db.EmbyContent./*Include(x => x.Seasons).*/FirstOrDefaultAsync(x => x.EmbyId == embyId); } - public async Task Update(EmbyContent existingContent) + public override async Task Update(IMediaServerContent existingContent) { - Db.EmbyContent.Update(existingContent); + Db.EmbyContent.Update((EmbyContent)existingContent); await InternalSaveChanges(); } - public IQueryable GetAllEpisodes() + public override IQueryable GetAllEpisodes() { return Db.EmbyEpisode.AsQueryable(); } - public async Task Add(EmbyEpisode content) + public override async Task Add(IMediaServerEpisode content) { - await Db.EmbyEpisode.AddAsync(content); + await Db.EmbyEpisode.AddAsync((EmbyEpisode)content); await InternalSaveChanges(); return content; } @@ -91,16 +85,23 @@ namespace Ombi.Store.Repository return await Db.EmbyEpisode.FirstOrDefaultAsync(x => x.EmbyId == key); } - public async Task AddRange(IEnumerable content) + public override async Task AddRange(IEnumerable content) { - Db.EmbyEpisode.AddRange(content); + Db.EmbyEpisode.AddRange((IEnumerable)content); await InternalSaveChanges(); } - public void UpdateWithoutSave(EmbyContent existingContent) + public override void UpdateWithoutSave(IMediaServerContent existingContent) { - Db.EmbyContent.Update(existingContent); + Db.EmbyContent.Update((EmbyContent)existingContent); } - + + public override Task UpdateRange(IEnumerable existingContent) + { + Db.EmbyContent.UpdateRange((IEnumerable)existingContent); + return InternalSaveChanges(); + } + + public override RecentlyAddedType RecentlyAddedType => RecentlyAddedType.Emby; } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/IEmbyContentRepository.cs b/src/Ombi.Store/Repository/IEmbyContentRepository.cs index a893e9aca..c171fef20 100644 --- a/src/Ombi.Store/Repository/IEmbyContentRepository.cs +++ b/src/Ombi.Store/Repository/IEmbyContentRepository.cs @@ -6,19 +6,16 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public interface IEmbyContentRepository : IRepository + public interface IEmbyContentRepository : IMediaServerContentRepository { + Task GetByEmbyId(string embyId); + Task GetEpisodeByEmbyId(string key); + + // TODO: merge these with IJellyfinContentRepository IQueryable Get(); Task GetByTheMovieDbId(string mov); Task GetByTvDbId(string tv); Task GetByImdbId(string imdbid); - Task GetByEmbyId(string embyId); - Task Update(EmbyContent existingContent); - IQueryable GetAllEpisodes(); - Task Add(EmbyEpisode content); - Task GetEpisodeByEmbyId(string key); - Task AddRange(IEnumerable content); - void UpdateWithoutSave(EmbyContent existingContent); } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/IExternalRepository.cs b/src/Ombi.Store/Repository/IExternalRepository.cs index b22cb5ea8..ec7b27769 100644 --- a/src/Ombi.Store/Repository/IExternalRepository.cs +++ b/src/Ombi.Store/Repository/IExternalRepository.cs @@ -9,7 +9,7 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public interface IExternalRepository where T : Entity + public interface IExternalRepository where T : IEntity { Task Find(object key); IQueryable GetAll(); @@ -25,6 +25,5 @@ namespace Ombi.Store.Repository where TEntity : class; Task ExecuteSql(string sql); - DbSet _db { get; } } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/IJellyfinContentRepository.cs b/src/Ombi.Store/Repository/IJellyfinContentRepository.cs index ff1f2d7dc..30efa1a17 100644 --- a/src/Ombi.Store/Repository/IJellyfinContentRepository.cs +++ b/src/Ombi.Store/Repository/IJellyfinContentRepository.cs @@ -6,19 +6,16 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public interface IJellyfinContentRepository : IRepository + public interface IJellyfinContentRepository : IMediaServerContentRepository { + Task GetByJellyfinId(string jellyfinId); + Task GetEpisodeByJellyfinId(string key); + + // TODO: merge these with IEmbyContentRepository IQueryable Get(); Task GetByTheMovieDbId(string mov); Task GetByTvDbId(string tv); Task GetByImdbId(string imdbid); - Task GetByJellyfinId(string jellyfinId); - Task Update(JellyfinContent existingContent); - IQueryable GetAllEpisodes(); - Task Add(JellyfinEpisode content); - Task GetEpisodeByJellyfinId(string key); - Task AddRange(IEnumerable content); - void UpdateWithoutSave(JellyfinContent existingContent); } } diff --git a/src/Ombi.Store/Repository/IMediaServerContentRepository.cs b/src/Ombi.Store/Repository/IMediaServerContentRepository.cs new file mode 100644 index 000000000..db4835a16 --- /dev/null +++ b/src/Ombi.Store/Repository/IMediaServerContentRepository.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Ombi.Store.Entities; + +namespace Ombi.Store.Repository +{ + public interface IMediaServerContentRepository : IExternalRepository + where Content : IMediaServerContent + { + RecentlyAddedType RecentlyAddedType{ get; } + Task Update(IMediaServerContent existingContent); + Task UpdateRange(IEnumerable existingContent); + IQueryable GetAllEpisodes(); + Task Add(IMediaServerEpisode content); + Task AddRange(IEnumerable content); + void UpdateWithoutSave(IMediaServerContent existingContent); + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Repository/IPlexContentRepository.cs b/src/Ombi.Store/Repository/IPlexContentRepository.cs index 38c013cb1..aeb4aae0a 100644 --- a/src/Ombi.Store/Repository/IPlexContentRepository.cs +++ b/src/Ombi.Store/Repository/IPlexContentRepository.cs @@ -8,23 +8,18 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public interface IPlexContentRepository : IExternalRepository + public interface IPlexContentRepository : IMediaServerContentRepository { Task ContentExists(string providerId); Task Get(string providerId, ProviderType type); - Task GetByType(string providerId, ProviderType type, PlexMediaTypeEntity plexType); - Task GetByKey(int key); - Task Update(PlexServerContent existingContent); - IQueryable GetAllEpisodes(); - Task Add(PlexEpisode content); - Task GetEpisodeByKey(int key); - Task AddRange(IEnumerable content); + Task GetByType(string providerId, ProviderType type, MediaType mediaType); + Task GetByKey(string key); + Task GetEpisodeByKey(string key); IEnumerable GetWhereContentByCustom(Expression> predicate); Task GetFirstContentByCustom(Expression> predicate); Task DeleteEpisode(PlexEpisode content); void DeleteWithoutSave(PlexServerContent content); void DeleteWithoutSave(PlexEpisode content); Task UpdateRange(IEnumerable existingContent); - void UpdateWithoutSave(PlexServerContent existingContent); } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/IRepository.cs b/src/Ombi.Store/Repository/IRepository.cs index b93b07d45..a6142462f 100644 --- a/src/Ombi.Store/Repository/IRepository.cs +++ b/src/Ombi.Store/Repository/IRepository.cs @@ -10,7 +10,7 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public interface IRepository where T : Entity + public interface IRepository where T : IEntity { Task Find(object key); Task Find(object key, CancellationToken cancellationToken); @@ -27,6 +27,5 @@ namespace Ombi.Store.Repository where TEntity : class; Task ExecuteSql(string sql); - DbSet _db { get; } } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/JellyfinContentRepository.cs b/src/Ombi.Store/Repository/JellyfinContentRepository.cs index 2b84adb00..c3451da62 100644 --- a/src/Ombi.Store/Repository/JellyfinContentRepository.cs +++ b/src/Ombi.Store/Repository/JellyfinContentRepository.cs @@ -35,17 +35,13 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public class JellyfinContentRepository : ExternalRepository, IJellyfinContentRepository + public class JellyfinContentRepository : MediaServerContentRepository, IJellyfinContentRepository { public JellyfinContentRepository(ExternalContext db):base(db) { - Db = db; } - private ExternalContext Db { get; } - - public async Task GetByImdbId(string imdbid) { return await Db.JellyfinContent.FirstOrDefaultAsync(x => x.ImdbId == imdbid); @@ -69,20 +65,20 @@ namespace Ombi.Store.Repository return await Db.JellyfinContent./*Include(x => x.Seasons).*/FirstOrDefaultAsync(x => x.JellyfinId == jellyfinId); } - public async Task Update(JellyfinContent existingContent) + public override async Task Update(IMediaServerContent existingContent) { - Db.JellyfinContent.Update(existingContent); + Db.JellyfinContent.Update((JellyfinContent)existingContent); await InternalSaveChanges(); } - public IQueryable GetAllEpisodes() + public override IQueryable GetAllEpisodes() { return Db.JellyfinEpisode.AsQueryable(); } - public async Task Add(JellyfinEpisode content) + public override async Task Add(IMediaServerEpisode content) { - await Db.JellyfinEpisode.AddAsync(content); + await Db.JellyfinEpisode.AddAsync((JellyfinEpisode)content); await InternalSaveChanges(); return content; } @@ -91,16 +87,23 @@ namespace Ombi.Store.Repository return await Db.JellyfinEpisode.FirstOrDefaultAsync(x => x.JellyfinId == key); } - public async Task AddRange(IEnumerable content) + public override async Task AddRange(IEnumerable content) { - Db.JellyfinEpisode.AddRange(content); + Db.JellyfinEpisode.AddRange((IEnumerable)content); await InternalSaveChanges(); } - public void UpdateWithoutSave(JellyfinContent existingContent) + public override void UpdateWithoutSave(IMediaServerContent existingContent) { - Db.JellyfinContent.Update(existingContent); + Db.JellyfinContent.Update((JellyfinContent)existingContent); } - + + public override Task UpdateRange(IEnumerable existingContent) + { + Db.JellyfinContent.UpdateRange((IEnumerable)existingContent); + return InternalSaveChanges(); + } + + public override RecentlyAddedType RecentlyAddedType => RecentlyAddedType.Jellyfin; } } diff --git a/src/Ombi.Store/Repository/MediaServerRepository.cs b/src/Ombi.Store/Repository/MediaServerRepository.cs new file mode 100644 index 000000000..c1c7d4ec8 --- /dev/null +++ b/src/Ombi.Store/Repository/MediaServerRepository.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Ombi.Store.Context; +using Ombi.Store.Entities; + +namespace Ombi.Store.Repository +{ + public abstract class MediaServerContentRepository : ExternalRepository, IMediaServerContentRepository where T : MediaServerContent + { + protected ExternalContext Db { get; } + public abstract RecentlyAddedType RecentlyAddedType { get; } + + public MediaServerContentRepository(ExternalContext db) : base(db) + { + Db = db; + } + + public abstract Task Update(IMediaServerContent existingContent); + public abstract IQueryable GetAllEpisodes(); + public abstract Task Add(IMediaServerEpisode content); + public abstract Task AddRange(IEnumerable content); + public abstract void UpdateWithoutSave(IMediaServerContent existingContent); + public abstract Task UpdateRange(IEnumerable existingContent); + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Repository/PlexContentRepository.cs b/src/Ombi.Store/Repository/PlexContentRepository.cs index 31b3bad11..96dfbe8e1 100644 --- a/src/Ombi.Store/Repository/PlexContentRepository.cs +++ b/src/Ombi.Store/Repository/PlexContentRepository.cs @@ -37,17 +37,13 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public class PlexServerContentRepository : ExternalRepository, IPlexContentRepository + public class PlexServerContentRepository : MediaServerContentRepository, IPlexContentRepository { - + public override RecentlyAddedType RecentlyAddedType => RecentlyAddedType.Plex; public PlexServerContentRepository(ExternalContext db) : base(db) { - Db = db; } - private ExternalContext Db { get; } - - public async Task ContentExists(string providerId) { var any = await Db.PlexServerContent.AnyAsync(x => x.ImdbId == providerId); @@ -79,16 +75,16 @@ namespace Ombi.Store.Repository return null; } - public async Task GetByType(string providerId, ProviderType type, PlexMediaTypeEntity plexType) + public async Task GetByType(string providerId, ProviderType type, MediaType mediaType) { switch (type) { case ProviderType.ImdbId: - return await Db.PlexServerContent.FirstOrDefaultAsync(x => x.ImdbId == providerId && x.Type == plexType); + return await Db.PlexServerContent.FirstOrDefaultAsync(x => x.ImdbId == providerId && x.Type == mediaType); case ProviderType.TheMovieDbId: - return await Db.PlexServerContent.FirstOrDefaultAsync(x => x.TheMovieDbId == providerId && x.Type == plexType); + return await Db.PlexServerContent.FirstOrDefaultAsync(x => x.TheMovieDbId == providerId && x.Type == mediaType); case ProviderType.TvDbId: - return await Db.PlexServerContent.FirstOrDefaultAsync(x => x.TvDbId == providerId && x.Type == plexType); + return await Db.PlexServerContent.FirstOrDefaultAsync(x => x.TvDbId == providerId && x.Type == mediaType); default: break; } @@ -96,7 +92,7 @@ namespace Ombi.Store.Repository return null; } - public async Task GetByKey(int key) + public async Task GetByKey(string key) { return await Db.PlexServerContent.Include(x => x.Seasons).FirstOrDefaultAsync(x => x.Key == key); } @@ -114,14 +110,14 @@ namespace Ombi.Store.Repository .FirstOrDefaultAsync(predicate); } - public async Task Update(PlexServerContent existingContent) + public override async Task Update(IMediaServerContent existingContent) { - Db.PlexServerContent.Update(existingContent); + Db.PlexServerContent.Update((PlexServerContent)existingContent); await InternalSaveChanges(); } - public void UpdateWithoutSave(PlexServerContent existingContent) + public override void UpdateWithoutSave(IMediaServerContent existingContent) { - Db.PlexServerContent.Update(existingContent); + Db.PlexServerContent.Update((PlexServerContent)existingContent); } public async Task UpdateRange(IEnumerable existingContent) @@ -130,7 +126,7 @@ namespace Ombi.Store.Repository await InternalSaveChanges(); } - public IQueryable GetAllEpisodes() + public override IQueryable GetAllEpisodes() { return Db.PlexEpisode.Include(x => x.Series).AsQueryable(); } @@ -145,9 +141,9 @@ namespace Ombi.Store.Repository Db.PlexEpisode.Remove(content); } - public async Task Add(PlexEpisode content) + public override async Task Add(IMediaServerEpisode content) { - await Db.PlexEpisode.AddAsync(content); + await Db.PlexEpisode.AddAsync((PlexEpisode)content); await InternalSaveChanges(); return content; } @@ -158,14 +154,20 @@ namespace Ombi.Store.Repository await InternalSaveChanges(); } - public async Task GetEpisodeByKey(int key) + public async Task GetEpisodeByKey(string key) { return await Db.PlexEpisode.FirstOrDefaultAsync(x => x.Key == key); } - public async Task AddRange(IEnumerable content) + public override async Task AddRange(IEnumerable content) { - Db.PlexEpisode.AddRange(content); + Db.PlexEpisode.AddRange((IEnumerable)content); await InternalSaveChanges(); } + + public override Task UpdateRange(IEnumerable existingContent) + { + Db.PlexServerContent.UpdateRange((IEnumerable)existingContent); + return InternalSaveChanges(); + } } } \ No newline at end of file diff --git a/src/Ombi.Test.Common/Ombi.Test.Common.csproj b/src/Ombi.Test.Common/Ombi.Test.Common.csproj index 71b05f59c..512055143 100644 --- a/src/Ombi.Test.Common/Ombi.Test.Common.csproj +++ b/src/Ombi.Test.Common/Ombi.Test.Common.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs index eadfb3a3a..dc2e5525c 100644 --- a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs @@ -40,7 +40,7 @@ namespace Ombi.Api.TheMovieDb Task GetKeyword(int keywordId); Task GetMovieWatchProviders(int theMoviedbId, CancellationToken token); Task GetTvWatchProviders(int theMoviedbId, CancellationToken token); - Task> GetGenres(string media, CancellationToken cancellationToken); + Task> GetGenres(string media, CancellationToken cancellationToken, string languageCode); Task> SearchWatchProviders(string media, string searchTerm, CancellationToken cancellationToken); Task> AdvancedSearch(DiscoverModel model, CancellationToken cancellationToken); } diff --git a/src/Ombi.TheMovieDbApi/Ombi.Api.TheMovieDb.csproj b/src/Ombi.TheMovieDbApi/Ombi.Api.TheMovieDb.csproj index 41ac19686..ddab7e3f8 100644 --- a/src/Ombi.TheMovieDbApi/Ombi.Api.TheMovieDb.csproj +++ b/src/Ombi.TheMovieDbApi/Ombi.Api.TheMovieDb.csproj @@ -7,7 +7,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs index 0391c184a..335ea7da3 100644 --- a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs @@ -427,10 +427,11 @@ namespace Ombi.Api.TheMovieDb return keyword == null || keyword.Id == 0 ? null : keyword; } - public async Task> GetGenres(string media, CancellationToken cancellationToken) + public async Task> GetGenres(string media, CancellationToken cancellationToken, string languageCode) { var request = new Request($"genre/{media}/list", BaseUri, HttpMethod.Get); request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", languageCode); AddRetry(request); var result = await Api.Request>(request, cancellationToken); diff --git a/src/Ombi.sln b/src/Ombi.sln index 5149f020b..a92df055e 100644 --- a/src/Ombi.sln +++ b/src/Ombi.sln @@ -124,6 +124,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.CloudService", "Om EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.RottenTomatoes", "Ombi.Api.RottenTomatoes\Ombi.Api.RottenTomatoes.csproj", "{8F19C701-7881-4BC7-8BBA-B068A6B954AD}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.I18n", "Ombi.I18n\Ombi.I18n.csproj", "{6A922D57-8622-4C36-8E6E-D5BA9E8DA6C0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.MediaServer", "Ombi.Api.MediaServer\Ombi.Api.MediaServer.csproj", "{AFC0BA9B-E38D-479F-825A-2F94EE4D6120}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -431,6 +435,18 @@ Global {8F19C701-7881-4BC7-8BBA-B068A6B954AD}.NonUiBuild|Any CPU.Build.0 = NonUiBuild|Any CPU {8F19C701-7881-4BC7-8BBA-B068A6B954AD}.Release|Any CPU.ActiveCfg = Release|Any CPU {8F19C701-7881-4BC7-8BBA-B068A6B954AD}.Release|Any CPU.Build.0 = Release|Any CPU + {6A922D57-8622-4C36-8E6E-D5BA9E8DA6C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6A922D57-8622-4C36-8E6E-D5BA9E8DA6C0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6A922D57-8622-4C36-8E6E-D5BA9E8DA6C0}.NonUiBuild|Any CPU.ActiveCfg = NonUiBuild|Any CPU + {6A922D57-8622-4C36-8E6E-D5BA9E8DA6C0}.NonUiBuild|Any CPU.Build.0 = NonUiBuild|Any CPU + {6A922D57-8622-4C36-8E6E-D5BA9E8DA6C0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6A922D57-8622-4C36-8E6E-D5BA9E8DA6C0}.Release|Any CPU.Build.0 = Release|Any CPU + {AFC0BA9B-E38D-479F-825A-2F94EE4D6120}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AFC0BA9B-E38D-479F-825A-2F94EE4D6120}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AFC0BA9B-E38D-479F-825A-2F94EE4D6120}.NonUiBuild|Any CPU.ActiveCfg = NonUiBuild|Any CPU + {AFC0BA9B-E38D-479F-825A-2F94EE4D6120}.NonUiBuild|Any CPU.Build.0 = NonUiBuild|Any CPU + {AFC0BA9B-E38D-479F-825A-2F94EE4D6120}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AFC0BA9B-E38D-479F-825A-2F94EE4D6120}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -479,6 +495,7 @@ Global {E2186FDA-D827-4781-8663-130AC382F12C} = {9293CA11-360A-4C20-A674-B9E794431BF5} {5DE40A66-B369-469E-8626-ECE23D9D8034} = {9293CA11-360A-4C20-A674-B9E794431BF5} {8F19C701-7881-4BC7-8BBA-B068A6B954AD} = {9293CA11-360A-4C20-A674-B9E794431BF5} + {AFC0BA9B-E38D-479F-825A-2F94EE4D6120} = {9293CA11-360A-4C20-A674-B9E794431BF5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {192E9BF8-00B4-45E4-BCCC-4C215725C869} diff --git a/src/Ombi/.vscode/settings.json b/src/Ombi/.vscode/settings.json index f8ea48b8f..0ac92f4ba 100644 --- a/src/Ombi/.vscode/settings.json +++ b/src/Ombi/.vscode/settings.json @@ -21,6 +21,8 @@ "issues", "emby", "availability-rules", - "details" - ] + "details", + "requests" + ], + "rpc.enabled": true } diff --git a/src/Ombi/ClientApp/.gitignore b/src/Ombi/ClientApp/.gitignore index e1f679be2..043e30f6d 100644 --- a/src/Ombi/ClientApp/.gitignore +++ b/src/Ombi/ClientApp/.gitignore @@ -17,6 +17,7 @@ *.launch .settings/ *.sublime-workspace +.angular # IDE - VSCode .vscode/* diff --git a/src/Ombi/ClientApp/package.json b/src/Ombi/ClientApp/package.json index 7ee4f64e5..80a9842b4 100644 --- a/src/Ombi/ClientApp/package.json +++ b/src/Ombi/ClientApp/package.json @@ -9,35 +9,34 @@ }, "private": true, "dependencies": { - "@angular/animations": "^12.2.10", - "@angular/cdk": "^12.2.9", - "@angular/common": "^12.2.10", - "@angular/compiler": "^12.2.10", - "@angular/core": "^12.2.10", - "@angular/forms": "^12.2.10", - "@angular/localize": "^12.2.10", - "@angular/material": "^12.2.9", - "@angular/platform-browser": "^12.2.10", - "@angular/platform-browser-dynamic": "^12.2.10", - "@angular/platform-server": "^12.2.10", - "@angular/router": "^12.2.10", + "@angular/animations": "^13.2.0", + "@angular/cdk": "^13.2.0", + "@angular/common": "^13.2.0", + "@angular/compiler": "^13.2.0", + "@angular/core": "^13.2.0", + "@angular/forms": "^13.2.0", + "@angular/localize": "^13.2.0", + "@angular/material": "^13.2.0", + "@angular/platform-browser": "^13.2.0", + "@angular/platform-browser-dynamic": "^13.2.0", + "@angular/platform-server": "^13.2.0", + "@angular/router": "^13.2.0", "@angularclass/hmr": "^3.0.0", "@aspnet/signalr": "^1.1.0", "@auth0/angular-jwt": "^5.0.2", - "@fortawesome/fontawesome-free": "^5.15.4", + "@fortawesome/fontawesome-free": "^6.0.0", "@fullcalendar/core": "^4.2.0", "@fullcalendar/daygrid": "^4.4.0", "@fullcalendar/interaction": "^4.2.0", - "@ngu/carousel": "^3.0.2", - "@ngx-translate/core": "^13.0.0", - "@ngx-translate/http-loader": "^6.0.0", - "@ngxs/devtools-plugin": "^3.7.2", - "@ngxs/store": "^3.7.2", - "@types/jquery": "^3.3.29", - "@yellowspot/ng-truncate": "^1.4.0", + "@ngx-translate/core": "^14.0.0", + "@ngx-translate/http-loader": "^7.0.0", + "@ngxs/devtools-plugin": "^3.7.3", + "@ngxs/store": "^3.7.3", + "@types/jquery": "^3.5.13", + "@yellowspot/ng-truncate": "^2.0.0", "angular-bootstrap-md": "^7.5.4", "angular-router-loader": "^0.8.5", - "angularx-qrcode": "^11.0.0", + "angularx-qrcode": "^13.0.3", "bootstrap": "^4.2.1", "chart.js": "2.9.4", "core-js": "^2.5.4", @@ -51,11 +50,11 @@ "ngx-clipboard": "^12.1.0", "ngx-infinite-scroll": "^9.0.0", "ngx-moment": "^3.0.1", - "ngx-order-pipe": "^2.1.1", + "ngx-order-pipe": "^2.2.0", "popper.js": "^1.14.3", - "primeicons": "^4.1.0", - "primeng": "^12.2.0", - "rxjs": "^7.4.0", + "primeicons": "^5.0.0", + "primeng": "^13.2.0", + "rxjs": "^7.5.4", "sass-recursive-map-merge": "^1.0.1", "store": "^2.0.12", "ts-md5": "^1.2.7", @@ -64,15 +63,15 @@ "zone.js": "~0.11.4" }, "devDependencies": { - "@angular-devkit/build-angular": "~12.2.10", - "@angular/cli": "~12.2.10", - "@angular/compiler-cli": "^12.2.10", - "@angular/language-service": "^12.2.10", + "@angular-devkit/build-angular": "~13.2.0", + "@angular/cli": "~13.2.0", + "@angular/compiler-cli": "^13.2.0", + "@angular/language-service": "^13.2.0", "@types/jasmine": "~3.6.7", "@types/jasminewd2": "~2.0.8", "@types/node": "^16.10.9", "codelyzer": "^6.0.1", - "typescript": "~4.3.4" + "typescript": "~4.5.5" }, "optionalDependencies": { "protractor": "~5.4.0", diff --git a/src/Ombi/ClientApp/src/app/app.component.ts b/src/Ombi/ClientApp/src/app/app.component.ts index 2c543606b..720ec22a2 100644 --- a/src/Ombi/ClientApp/src/app/app.component.ts +++ b/src/Ombi/ClientApp/src/app/app.component.ts @@ -51,9 +51,9 @@ export class AppComponent implements OnInit { private signalrNotification: SignalRNotificationService, private readonly snackBar: MatSnackBar, private readonly identity: IdentityService, - @Inject(DOCUMENT) private document: HTMLDocument) { + @Inject(DOCUMENT) private document: Document) { - this.translate.addLangs(["da", "de", "en", "es", "fr", "it", "hu", "nl", "no", "pl", "pt", "sk", "sv", "bg", "ru"]); + this.translate.addLangs(["da", "de", "en", "es", "fr", "it", "hu", "nl", "no", "pl", "pt", "sk", "sv", "bg", "ru", "cs", "zh"]); if (this.authService.loggedIn()) { this.identity.getAccessToken().subscribe(x => this.accessToken = x); @@ -81,7 +81,7 @@ export class AppComponent implements OnInit { // See if we can match the supported langs with the current browser lang const browserLang: string = translate.getBrowserLang(); - this.translate.use(browserLang.match(/da|de|en|es|fr|it|hu|nl|no|pl|pt|sk|sv|bg|ru/) ? browserLang : "en"); + this.translate.use(browserLang.match(/da|de|en|es|fr|it|hu|nl|no|pl|pt|sk|sv|bg|ru|cs|zh/) ? browserLang : "en"); } diff --git a/src/Ombi/ClientApp/src/app/app.module.ts b/src/Ombi/ClientApp/src/app/app.module.ts index 082ce80d2..735dce36b 100644 --- a/src/Ombi/ClientApp/src/app/app.module.ts +++ b/src/Ombi/ClientApp/src/app/app.module.ts @@ -21,6 +21,8 @@ import { CustomPageComponent } from "./custompage/custompage.component"; import { CustomizationState } from "./state/customization/customization.state"; import { DataViewModule } from "primeng/dataview"; import { DialogModule } from "primeng/dialog"; +import { FEATURES_INITIALIZER } from "./state/features/features-initializer"; +import { FeatureState } from "./state/features"; import { JwtModule } from "@auth0/angular-jwt"; import { LandingPageComponent } from "./landingpage/landingpage.component"; import { LandingPageService } from "./services"; @@ -38,6 +40,8 @@ import { MatInputModule } from "@angular/material/input"; import { MatListModule } from '@angular/material/list'; import { MatMenuModule } from "@angular/material/menu"; import { MatNativeDateModule } from '@angular/material/core'; +import { MatPaginatorI18n } from "./localization/MatPaginatorI18n"; +import { MatPaginatorIntl } from "@angular/material/paginator"; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatSidenavModule } from '@angular/material/sidenav'; import { MatSlideToggleModule } from "@angular/material/slide-toggle"; @@ -63,11 +67,9 @@ import { StorageService } from "./shared/storage/storage-service"; import { TokenResetPasswordComponent } from "./login/tokenresetpassword.component"; import { TooltipModule } from "primeng/tooltip"; import { TranslateHttpLoader } from "@ngx-translate/http-loader"; +import { TranslateService } from "@ngx-translate/core"; import { UnauthorizedInterceptor } from "./auth/unauthorized.interceptor"; import { environment } from "../environments/environment"; -import { MatPaginatorIntl } from "@angular/material/paginator"; -import { TranslateService } from "@ngx-translate/core"; -import { MatPaginatorI18n } from "./localization/MatPaginatorI18n"; const routes: Routes = [ { path: "*", component: PageNotFoundComponent }, @@ -162,10 +164,10 @@ export function JwtTokenGetter() { }), SidebarModule, MatNativeDateModule, MatIconModule, MatSidenavModule, MatListModule, MatToolbarModule, LayoutModule, MatSlideToggleModule, - NgxsModule.forRoot([CustomizationState], { + NgxsModule.forRoot([CustomizationState, FeatureState], { developmentMode: !environment.production, }), - ...environment.production ? [] : + ...environment.production ? [] : [ NgxsReduxDevtoolsPluginModule.forRoot(), ] @@ -205,6 +207,7 @@ export function JwtTokenGetter() { StorageService, RequestService, SignalRNotificationService, + FEATURES_INITIALIZER, CUSTOMIZATION_INITIALIZER, { provide: APP_BASE_HREF, diff --git a/src/Ombi/ClientApp/src/app/auth/auth.service.ts b/src/Ombi/ClientApp/src/app/auth/auth.service.ts index afc0a2491..ad1ff32ac 100644 --- a/src/Ombi/ClientApp/src/app/auth/auth.service.ts +++ b/src/Ombi/ClientApp/src/app/auth/auth.service.ts @@ -28,6 +28,10 @@ export class AuthService extends ServiceHelpers { return this.http.post(`${this.url}/requirePassword`, JSON.stringify(login), { headers: this.headers }); } + public headerAuth(): Observable { + return this.http.post(`${this.url}/header_auth`, {}, { headers: this.headers }); + } + public getToken() { return this.jwtHelperService.tokenGetter(); } diff --git a/src/Ombi/ClientApp/src/app/discover/components/actor/discover-actor.component.html b/src/Ombi/ClientApp/src/app/discover/components/actor/discover-actor.component.html index 67f243503..87db00955 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/actor/discover-actor.component.html +++ b/src/Ombi/ClientApp/src/app/discover/components/actor/discover-actor.component.html @@ -5,7 +5,7 @@
- +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/discover/components/actor/discover-actor.component.ts b/src/Ombi/ClientApp/src/app/discover/components/actor/discover-actor.component.ts index 290042d87..5c333522c 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/actor/discover-actor.component.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/actor/discover-actor.component.ts @@ -1,4 +1,4 @@ -import { Component } from "@angular/core"; +import { Component, OnInit } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { SearchV2Service } from "../../../services"; import { IActorCredits, IActorCast } from "../../../interfaces/ISearchTvResultV2"; @@ -6,30 +6,31 @@ import { IDiscoverCardResult } from "../../interfaces"; import { RequestType } from "../../../interfaces"; import { AuthService } from "../../../auth/auth.service"; import { forkJoin } from "rxjs"; -import { isEqual } from "lodash"; +import { FeaturesFacade } from "../../../state/features/features.facade"; @Component({ templateUrl: "./discover-actor.component.html", styleUrls: ["./discover-actor.component.scss"], }) -export class DiscoverActorComponent { +export class DiscoverActorComponent implements OnInit { public actorId: number; public loadingFlag: boolean; public isAdmin: boolean; + public is4kEnabled = false; public discoverResults: IDiscoverCardResult[] = []; constructor(private searchService: SearchV2Service, private route: ActivatedRoute, - private auth: AuthService) { + private auth: AuthService, + private featureService: FeaturesFacade) { this.route.params.subscribe((params: any) => { this.actorId = params.actorId; - this.isAdmin = this.auth.isAdmin(); - this.search(); }); } - - private search() { + ngOnInit() { + this.isAdmin = this.auth.isAdmin(); + this.is4kEnabled = this.featureService.is4kEnabled(); this.discoverResults = []; this.loading(); diff --git a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.html b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.html index 5a6993e44..9ca607082 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.html +++ b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.html @@ -6,7 +6,7 @@ {{ 'Common.' + RequestType[result.type] | translate }}
- {{getAvailbilityStatus()}} + {{getAvailabilityStatus()}}
-
- -
+ +
+ +
+ + + + + +
+
+ +
+ +
+
+ + +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.scss b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.scss index 6bf6748bf..5fe422fd7 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.scss +++ b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.scss @@ -201,31 +201,31 @@ small { margin-right:5px; } -.top-right.available span.indicator, span.indicator-text{ +.top-right span.indicator, span.indicator-text{ display:block; } +.top-right span.indicator:before{ + display: inline-block; +} .top-right.available span.indicator:before{ - display: inline-block; background-color: #1DE9B6; } -.top-right.approved span.indicator, span.indicator-text { - display: block; -} - .top-right.approved span.indicator:before{ - display: inline-block; - background-color: #ff5722; + background-color: #ffd740; } -.top-right.requested span.indicator, span.indicator-text { - display: block; +.top-right.denied span.indicator:before{ + background-color: #660202; +} + +.top-right.partly-available span.indicator:before{ + background-color: #ffd740; } .top-right.requested span.indicator:before{ - display: inline-block; - background-color: #ffd740; + background-color: #ff5722; } ::ng-deep a.poster-overlay{ @@ -292,4 +292,8 @@ a.poster-overlay:hover{ .btn-ombi{ background-color:#293a4c; +} + +::ng-deep .mat-menu-panel { + min-width: 190px !important; } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts index 4de883256..559a962b5 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts @@ -21,10 +21,12 @@ export class DiscoverCardComponent implements OnInit { @Input() public discoverType: DiscoverType; @Input() public result: IDiscoverCardResult; @Input() public isAdmin: boolean; + @Input() public is4kEnabled: boolean = false; public RequestType = RequestType; public hide: boolean; public fullyLoaded = false; public loading: boolean; + public allow4KButton: boolean = false; public requestable: boolean; @@ -40,6 +42,7 @@ export class DiscoverCardComponent implements OnInit { this.getExtraTvInfo(); } if (this.result.type == RequestType.movie) { + this.allow4KButton = true; this.getExtraMovieInfo(); } if (this.result.type == RequestType.album) { @@ -89,29 +92,41 @@ export class DiscoverCardComponent implements OnInit { if (this.result.available) { return "available"; } + if (this.tvSearchResult?.partlyAvailable) { + return "partly-available"; + } if (this.result.approved) { return "approved"; } + if (this.result.denied) { + return "denied"; + } if (this.result.requested) { return "requested"; } return ""; } - public getAvailbilityStatus(): string { + public getAvailabilityStatus(): string { if (this.result.available) { return this.translate.instant("Common.Available"); } + if (this.tvSearchResult?.partlyAvailable) { + return this.translate.instant("Common.PartlyAvailable"); + } if (this.result.approved) { return this.translate.instant("Common.Approved"); } + if (this.result.denied) { + return this.translate.instant("Common.Denied"); + } if (this.result.requested) { return this.translate.instant("Common.Pending"); } return ""; } - public request(event: any) { + public request(event: any, is4k: boolean) { event.preventDefault(); this.loading = true; switch (this.result.type) { @@ -121,14 +136,15 @@ export class DiscoverCardComponent implements OnInit { return; case RequestType.movie: if (this.isAdmin) { - const dialog = this.dialog.open(AdminRequestDialogComponent, { width: "700px", data: { type: RequestType.movie, id: this.result.id }, panelClass: 'modal-panel' }); + const dialog = this.dialog.open(AdminRequestDialogComponent, { width: "700px", data: { type: RequestType.movie, id: this.result.id, }, panelClass: 'modal-panel' }); dialog.afterClosed().subscribe((result) => { if (result) { this.requestService.requestMovie({ theMovieDbId: +this.result.id, languageCode: this.translate.currentLang, qualityPathOverride: result.radarrPathId, requestOnBehalf: result.username?.id, - rootFolderOverride: result.radarrFolderId, }).subscribe(x => { + rootFolderOverride: result.radarrFolderId, + is4KRequest: is4k }).subscribe(x => { if (x.result) { this.result.requested = true; this.messageService.send(this.translate.instant("Requests.RequestAddedSuccessfully", { title: this.result.title }), "Ok"); @@ -139,7 +155,7 @@ export class DiscoverCardComponent implements OnInit { } }); } else { - this.requestService.requestMovie({ theMovieDbId: +this.result.id, languageCode: this.translate.currentLang, requestOnBehalf: null, qualityPathOverride: null, rootFolderOverride: null }).subscribe(x => { + this.requestService.requestMovie({ theMovieDbId: +this.result.id, languageCode: this.translate.currentLang, requestOnBehalf: null, qualityPathOverride: null, rootFolderOverride: null, is4KRequest: is4k }).subscribe(x => { if (x.result) { this.result.requested = true; this.messageService.send(this.translate.instant("Requests.RequestAddedSuccessfully", { title: this.result.title }), "Ok"); @@ -167,9 +183,10 @@ export class DiscoverCardComponent implements OnInit { private updateMovieItem(updated: ISearchMovieResultV2) { this.result.url = "http://www.imdb.com/title/" + updated.imdbId + "/"; - this.result.available = updated.available; - this.result.requested = updated.requested; - this.result.approved = updated.approved; + this.result.available = updated.available || updated.available4K; + this.result.requested = updated.requested || updated.has4KRequest; + this.result.approved = updated.approved || updated.available4K; + this.result.denied = updated.denied || updated.denied4K; this.result.rating = updated.voteAverage; this.result.overview = updated.overview; this.result.imdbid = updated.imdbId; @@ -196,6 +213,7 @@ export class DiscoverCardComponent implements OnInit { this.result.overview = updated.overview; this.result.approved = updated.approved; this.result.available = updated.fullyAvailable; + this.result.denied = updated.denied; this.fullyLoaded = true; } diff --git a/src/Ombi/ClientApp/src/app/discover/components/carousel-list/carousel-list.component.html b/src/Ombi/ClientApp/src/app/discover/components/carousel-list/carousel-list.component.html index aa9ffc5f2..5be2aa1ad 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/carousel-list/carousel-list.component.html +++ b/src/Ombi/ClientApp/src/app/discover/components/carousel-list/carousel-list.component.html @@ -8,6 +8,6 @@ - + \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/discover/components/carousel-list/carousel-list.component.ts b/src/Ombi/ClientApp/src/app/discover/components/carousel-list/carousel-list.component.ts index a00146ad5..9617c993e 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/carousel-list/carousel-list.component.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/carousel-list/carousel-list.component.ts @@ -5,6 +5,7 @@ import { SearchV2Service } from "../../../services"; import { StorageService } from "../../../shared/storage/storage-service"; import { MatButtonToggleChange } from '@angular/material/button-toggle'; import { Carousel } from 'primeng/carousel'; +import { FeaturesFacade } from "../../../state/features/features.facade"; export enum DiscoverType { Upcoming, @@ -36,6 +37,7 @@ export class CarouselListComponent implements OnInit { public RequestType = RequestType; public loadingFlag: boolean; public DiscoverType = DiscoverType; + public is4kEnabled = false; get mediaTypeStorageKey() { return "DiscoverOptions" + this.discoverType.toString(); @@ -44,7 +46,8 @@ export class CarouselListComponent implements OnInit { private currentlyLoaded = 0; constructor(private searchService: SearchV2Service, - private storageService: StorageService) { + private storageService: StorageService, + private featureFacade: FeaturesFacade) { this.responsiveOptions = [ { breakpoint: '4000px', @@ -135,6 +138,7 @@ export class CarouselListComponent implements OnInit { } public async ngOnInit() { + this.is4kEnabled = this.featureFacade.is4kEnabled(); this.currentlyLoaded = 0; const localDiscoverOptions = +this.storageService.get(this.mediaTypeStorageKey); if (localDiscoverOptions) { diff --git a/src/Ombi/ClientApp/src/app/discover/components/collections/discover-collections.component.html b/src/Ombi/ClientApp/src/app/discover/components/collections/discover-collections.component.html index 23a7791f0..0750a12c0 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/collections/discover-collections.component.html +++ b/src/Ombi/ClientApp/src/app/discover/components/collections/discover-collections.component.html @@ -16,7 +16,7 @@
- +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/discover/components/collections/discover-collections.component.ts b/src/Ombi/ClientApp/src/app/discover/components/collections/discover-collections.component.ts index 9e84ea7d0..d643c52af 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/collections/discover-collections.component.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/collections/discover-collections.component.ts @@ -8,6 +8,7 @@ import { IDiscoverCardResult } from "../../interfaces"; import { IMovieCollectionsViewModel } from "../../../interfaces/ISearchTvResultV2"; import { RequestServiceV2 } from "../../../services/requestV2.service"; import { RequestType } from "../../../interfaces"; +import { FeaturesFacade } from "../../../state/features/features.facade"; @Component({ templateUrl: "./discover-collections.component.html", @@ -19,6 +20,7 @@ export class DiscoverCollectionsComponent implements OnInit { public collection: IMovieCollectionsViewModel; public loadingFlag: boolean; public isAdmin: boolean; + public is4kEnabled = false; public discoverResults: IDiscoverCardResult[] = []; @@ -27,13 +29,15 @@ export class DiscoverCollectionsComponent implements OnInit { private requestServiceV2: RequestServiceV2, private messageService: MessageService, private auth: AuthService, - private translate: TranslateService) { + private translate: TranslateService, + private featureFacade: FeaturesFacade) { this.route.params.subscribe((params: any) => { this.collectionId = params.collectionId; }); } public async ngOnInit() { + this.is4kEnabled = this.featureFacade.is4kEnabled(); this.loadingFlag = true; this.isAdmin = this.auth.isAdmin(); this.collection = await this.searchService.getMovieCollections(this.collectionId); diff --git a/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.html b/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.html index 4ef9255fb..b1911ceee 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.html +++ b/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.html @@ -4,7 +4,7 @@
- +
diff --git a/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.ts b/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.ts index f0258b97d..a8544365d 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.ts @@ -10,6 +10,7 @@ import { SearchFilter } from "../../../my-nav/SearchFilter"; import { SearchV2Service } from "../../../services"; import { StorageService } from "../../../shared/storage/storage-service"; import { isEqual } from "lodash"; +import { FeaturesFacade } from "../../../state/features/features.facade"; @Component({ templateUrl: "./search-results.component.html", @@ -21,6 +22,7 @@ export class DiscoverSearchResultsComponent implements OnInit { public searchTerm: string; public results: IMultiSearchResult[]; public isAdmin: boolean; + public is4kEnabled = false; public discoverResults: IDiscoverCardResult[] = []; @@ -34,7 +36,8 @@ export class DiscoverSearchResultsComponent implements OnInit { private router: Router, private advancedDataService: AdvancedSearchDialogDataService, private store: StorageService, - private authService: AuthService) { + private authService: AuthService, + private featureFacade: FeaturesFacade) { this.route.params.subscribe((params: any) => { this.isAdvancedSearch = this.router.url === '/discover/advanced/search'; if (this.isAdvancedSearch) { @@ -53,6 +56,7 @@ export class DiscoverSearchResultsComponent implements OnInit { } public async ngOnInit() { + this.is4kEnabled = this.featureFacade.is4kEnabled(); this.isAdmin = this.authService.isAdmin(); this.filterService.onFilterChange.subscribe(async x => { if (!isEqual(this.filter, x)) { diff --git a/src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts b/src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts index f2efc3f6f..460a970fe 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts @@ -12,7 +12,6 @@ export interface IEmailNotificationSettings extends INotificationSettings { senderName: string; username: string; authentication: boolean; - adminEmail: string; disableTLS: boolean; disableCertificateChecking: boolean; notificationTemplates: INotificationTemplates[]; diff --git a/src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts b/src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts index 440e0d5b2..36b75adb6 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts @@ -16,6 +16,13 @@ export interface IMovieRequests extends IFullBaseRequest { subscribed: boolean; showSubscribe: boolean; requestStatus: string; + has4KRequest: boolean; + approved4K: boolean; + available4K: boolean; + denied4K: boolean; + deniedReason4K: string; + requestedDate4k: Date; + requestedDate: Date; // For the UI rootPathOverrideTitle: string; @@ -53,6 +60,7 @@ export interface IRequestsViewModel { export interface IMovieUpdateModel { id: number; + is4K: boolean; } export interface IDenyMovieModel extends IMovieUpdateModel { @@ -96,6 +104,13 @@ export interface IBaseRequest { canApprove: boolean; title: string; requestedByAlias: string; + source: RequestSource; +} + +export enum RequestSource +{ + Ombi = 0, + PlexWatchlist = 1 } export interface ITvRequests { @@ -176,6 +191,7 @@ export interface IEpisodesRequests { export interface IMovieRequestModel extends BaseRequestOptions { theMovieDbId: number; languageCode: string | undefined; + is4KRequest?: boolean; } export interface IFilter { diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResultV2.ts b/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResultV2.ts index da4b27f32..937234c42 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResultV2.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResultV2.ts @@ -23,6 +23,8 @@ homepage: string; imdbId: string; approved: boolean; + denied: boolean; + deniedReason: string; requested: boolean; requestId: number; available: boolean; @@ -42,6 +44,11 @@ externalIds: IExternalIds; keywords: IKeywords; belongsToCollection: ICollectionsModel; + has4KRequest: boolean; + approved4K: boolean; + available4K: boolean; + denied4K: boolean; + deniedReason4K: string; // for the UI requestProcessing: boolean; diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISearchTvResultV2.ts b/src/Ombi/ClientApp/src/app/interfaces/ISearchTvResultV2.ts index 8ea7bacc5..78958a02e 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISearchTvResultV2.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISearchTvResultV2.ts @@ -25,6 +25,8 @@ export interface ISearchTvResultV2 { seasonRequests: INewSeasonRequests[]; requestAll: boolean; approved: boolean; + denied: boolean; + deniedReason: string; requested: boolean; available: boolean; plexUrl: string; diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts index c7990215f..95b1fba00 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts @@ -112,6 +112,7 @@ export interface IPublicInfo { export interface IPlexSettings extends ISettings { enable: boolean; + enableWatchlistImport: boolean; servers: IPlexServer[]; } @@ -158,6 +159,11 @@ export interface IRadarrSettings extends IExternalSettings { scanForAvailability: boolean; } +export interface IRadarrCombined { + radarr: IRadarrSettings; + radarr4K: IRadarrSettings; +} + export interface ILidarrSettings extends IExternalSettings { enabled: boolean; apiKey: string; @@ -214,6 +220,7 @@ export interface IJobSettings { mediaDatabaseRefresh: string; autoDeleteRequests: string; embyRecentlyAddedSync: string; + plexWatchlistImport: string; } export interface IIssueSettings extends ISettings { @@ -233,6 +240,8 @@ export interface IAuthenticationSettings extends ISettings { requireNonAlphanumeric: boolean; requireUppercase: boolean; enableOAuth: boolean; + enableHeaderAuth: boolean; + headerAuthVariable: string; } export interface ICustomPage extends ISettings { diff --git a/src/Ombi/ClientApp/src/app/interfaces/IUser.ts b/src/Ombi/ClientApp/src/app/interfaces/IUser.ts index 97882e783..069b1e506 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/IUser.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/IUser.ts @@ -146,3 +146,8 @@ export enum INotificationAgent { Webhook = 9, WhatsApp = 10 } + +export interface IFeatureEnablement { + name: string; + enabled: boolean; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/login/login.component.ts b/src/Ombi/ClientApp/src/app/login/login.component.ts index 235e31a8e..f6f519191 100644 --- a/src/Ombi/ClientApp/src/app/login/login.component.ts +++ b/src/Ombi/ClientApp/src/app/login/login.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy, OnInit, Inject } from "@angular/core"; +import { Component, OnDestroy, OnInit, Inject } from "@angular/core"; import { FormBuilder, FormGroup, Validators } from "@angular/forms"; import { ActivatedRoute, Router } from "@angular/router"; import { TranslateService } from "@ngx-translate/core"; @@ -106,7 +106,10 @@ export class LoginComponent implements OnDestroy, OnInit { this.settingsService .getAuthentication() - .subscribe((x) => (this.authenticationSettings = x)); + .subscribe((x) => { + this.authenticationSettings = x; + this.headerAuth(); + }); this.settingsService.getClientId().subscribe((x) => (this.clientId = x)); this.images.getRandomBackground().subscribe((x) => { this.background = this.sanitizer.bypassSecurityTrustStyle( @@ -121,7 +124,6 @@ export class LoginComponent implements OnDestroy, OnInit { if (base.length > 1) { this.baseUrl = base; } - this.translate .get("Login.Errors.IncorrectCredentials") .subscribe((x) => (this.errorBody = x)); @@ -255,6 +257,32 @@ export class LoginComponent implements OnDestroy, OnInit { ); } + public headerAuth() { + if (this.authenticationSettings.enableHeaderAuth) { + this.authService.headerAuth().subscribe({ + next: (x) => { + this.store.save("id_token", x.access_token); + + if (this.authService.loggedIn()) { + this.ngOnDestroy(); + this.router.navigate(["/"]); + } else { + this.notify.open(this.errorBody, "OK", { + duration: 3000, + }); + } + }, + error: (e) => { + this.notify.open(this.errorBody, "OK", { + duration: 3000000, + }); + console.error(e); + } + } + ); + } + } + public ngOnDestroy() { clearInterval(this.timer); clearInterval(this.pinTimer); diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html index 2e807547c..2207ea323 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html @@ -4,28 +4,18 @@
- + @@ -40,73 +30,148 @@
- - + + {{'Search.ViewOnPlex' | translate}} - + {{'Search.ViewOnEmby' | translate}} - + {{'Search.ViewOnJellyfin' | translate}} - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + - + - - + + - - + + + + + + + - - + + + +
@@ -115,7 +180,8 @@
- + @@ -151,9 +217,14 @@ {{'MediaDetails.Trailers' | translate}} - + - + @@ -181,7 +252,9 @@ @@ -201,7 +274,9 @@ diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts index 68e329f78..c040fe4e0 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component, ViewChild, ViewEncapsulation } from "@angular/core"; +import { AfterViewInit, Component, OnInit, ViewChild, ViewEncapsulation } from "@angular/core"; import { ImageService, SearchV2Service, RequestService, MessageService, RadarrService, SettingsStateService } from "../../../services"; import { ActivatedRoute } from "@angular/router"; import { DomSanitizer } from "@angular/platform-browser"; @@ -13,15 +13,16 @@ import { TranslateService } from "@ngx-translate/core"; import { MovieAdvancedOptionsComponent } from "./panels/movie-advanced-options/movie-advanced-options.component"; import { RequestServiceV2 } from "../../../services/requestV2.service"; import { RequestBehalfComponent } from "../shared/request-behalf/request-behalf.component"; -import { forkJoin } from "rxjs"; +import { firstValueFrom, forkJoin } from "rxjs"; import { AdminRequestDialogComponent } from "../../../shared/admin-request-dialog/admin-request-dialog.component"; +import { FeaturesFacade } from "../../../state/features/features.facade"; @Component({ templateUrl: "./movie-details.component.html", styleUrls: ["../../media-details.component.scss"], encapsulation: ViewEncapsulation.None }) -export class MovieDetailsComponent { +export class MovieDetailsComponent implements OnInit{ public movie: ISearchMovieResultV2; public hasRequest: boolean; public movieRequest: IMovieRequests; @@ -29,6 +30,8 @@ export class MovieDetailsComponent { public advancedOptions: IAdvancedData; public showAdvanced: boolean; // Set on the UI public issuesEnabled: boolean; + public roleName4k = "Request4KMovie"; + public is4KEnabled = false; public requestType = RequestType.movie; @@ -41,7 +44,7 @@ export class MovieDetailsComponent { public dialog: MatDialog, private requestService: RequestService, private requestService2: RequestServiceV2, private radarrService: RadarrService, public messageService: MessageService, private auth: AuthService, private settingsState: SettingsStateService, - private translate: TranslateService) { + private translate: TranslateService, private featureFacade: FeaturesFacade) { this.route.params.subscribe(async (params: any) => { if (typeof params.movieDbId === 'string' || params.movieDbId instanceof String) { if (params.movieDbId.startsWith("tt")) { @@ -49,12 +52,12 @@ export class MovieDetailsComponent { } } this.theMovidDbId = params.movieDbId; - await this.load(); }); } - public async load() { + async ngOnInit() { + this.is4KEnabled = this.featureFacade.is4kEnabled(); this.issuesEnabled = this.settingsState.getIssue(); this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); @@ -86,18 +89,26 @@ export class MovieDetailsComponent { } } - public async request(userId?: string) { + public async request(is4K: boolean, userId?: string) { + if (!this.is4KEnabled) { + is4K = false; + } if (this.isAdmin) { const dialog = this.dialog.open(AdminRequestDialogComponent, { width: "700px", data: { type: RequestType.movie, id: this.movie.id }, panelClass: 'modal-panel' }); dialog.afterClosed().subscribe(async (result) => { if (result) { - const requestResult = await this.requestService.requestMovie({ theMovieDbId: this.theMovidDbId, + const requestResult = await firstValueFrom(this.requestService.requestMovie({ theMovieDbId: this.theMovidDbId, languageCode: this.translate.currentLang, qualityPathOverride: result.radarrPathId, requestOnBehalf: result.username?.id, - rootFolderOverride: result.radarrFolderId, }).toPromise(); + rootFolderOverride: result.radarrFolderId, + is4KRequest: is4K })); if (requestResult.result) { - this.movie.requested = true; + if (is4K) { + this.movie.has4KRequest = true; + } else { + this.movie.requested = true; + } this.movie.requestId = requestResult.requestId; this.messageService.send(this.translate.instant("Requests.RequestAddedSuccessfully", { title: this.movie.title }), "Ok"); this.movieRequest = await this.requestService.getMovieRequest(this.movie.requestId); @@ -107,9 +118,13 @@ export class MovieDetailsComponent { } }); } else { - const result = await this.requestService.requestMovie({ theMovieDbId: this.theMovidDbId, languageCode: this.translate.currentLang, requestOnBehalf: userId, qualityPathOverride: undefined, rootFolderOverride: undefined }).toPromise(); + const result = await firstValueFrom(this.requestService.requestMovie({ theMovieDbId: this.theMovidDbId, languageCode: this.translate.currentLang, requestOnBehalf: userId, qualityPathOverride: undefined, rootFolderOverride: undefined, is4KRequest: is4K })); if (result.result) { - this.movie.requested = true; + if (is4K) { + this.movie.has4KRequest = true; + } else { + this.movie.requested = true; + } this.movie.requestId = result.requestId; this.movieRequest = await this.requestService.getMovieRequest(this.movie.requestId); this.messageService.send(this.translate.instant("Requests.RequestAddedSuccessfully", { title: this.movie.title }), "Ok"); @@ -149,21 +164,28 @@ export class MovieDetailsComponent { }); } - public async approve() { - this.movie.approved = true; - const result = await this.requestService.approveMovie({ id: this.movieRequest.id }).toPromise(); + public async approve(is4K: boolean) { + const result = await firstValueFrom(this.requestService.approveMovie({ id: this.movieRequest.id, is4K })); if (result.result) { + if (is4K) { + this.movie.approved4K = true; + } else { + this.movie.approved = true; + } this.messageService.send(this.translate.instant("Requests.SuccessfullyApproved"), "Ok"); } else { - this.movie.approved = false; this.messageService.sendRequestEngineResultError(result); } } - public async markAvailable() { - const result = await this.requestService.markMovieAvailable({ id: this.movieRequest.id }).toPromise(); + public async markAvailable(is4K: boolean) { + const result = await firstValueFrom(this.requestService.markMovieAvailable({ id: this.movieRequest.id, is4K })) if (result.result) { - this.movie.available = true; + if (is4K) { + this.movie.available4K = true; + } else { + this.movie.available = true; + } this.messageService.send(this.translate.instant("Requests.NowAvailable"), "Ok"); } else { this.messageService.sendRequestEngineResultError(result); @@ -171,10 +193,14 @@ export class MovieDetailsComponent { } - public async markUnavailable() { - const result = await this.requestService.markMovieUnavailable({ id: this.movieRequest.id }).toPromise(); + public async markUnavailable(is4K: boolean) { + const result = await firstValueFrom(this.requestService.markMovieUnavailable({ id: this.movieRequest.id, is4K })); if (result.result) { - this.movie.available = false; + if (is4K) { + this.movie.available4K = false; + } else { + this.movie.available = false; + } this.messageService.send(this.translate.instant("Requests.NowUnavailable"), "Ok"); } else { this.messageService.sendRequestEngineResultError(result); @@ -203,8 +229,8 @@ export class MovieDetailsComponent { }); } - public reProcessRequest() { - this.requestService2.reprocessRequest(this.movieRequest.id, RequestType.movie).subscribe(result => { + public reProcessRequest(is4K: boolean) { + this.requestService2.reprocessRequest(this.movieRequest.id, RequestType.movie, is4K).subscribe(result => { if (result.result) { this.messageService.send(result.message ? result.message : this.translate.instant("Requests.SuccessfullyReprocessed"), "Ok"); } else { diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html index 1fa528159..7fd3ce0ea 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html @@ -36,10 +36,11 @@
{{'MediaDetails.RequestStatus' | translate }} -
{{'Common.ProcessingRequest' | translate}}
-
{{'Common.PendingApproval' | translate}} +
{{'Common.Denied' | translate}}
+
{{'Common.ProcessingRequest' | translate}}
+
{{'Common.PendingApproval' | translate}}
-
{{'Common.NotRequested' | translate}} +
{{'Common.NotRequested' | translate}}
@@ -53,6 +54,11 @@ {{request.requestedDate | amUserLocale | amDateFormat: 'LL'}}
+
+ {{'MediaDetails.RequestSource' | translate }} + {{RequestSource[request.source]}} +
+
{{'MediaDetails.DeniedReason' | translate }} {{request.deniedReason}} @@ -64,6 +70,11 @@
{{movie.quality | quality}}
+
+ {{'MediaDetails.Quality' | translate }}  + {{"4K" | quality}} +
+
{{'MediaDetails.RootFolderOverride' | translate }}
{{request.rootPathOverrideTitle}}
diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.ts index c11a0f61c..ade256a82 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.ts @@ -1,6 +1,6 @@ import { Component, ViewEncapsulation, Input, OnInit, Inject } from "@angular/core"; import { ISearchMovieResultV2 } from "../../../../interfaces/ISearchMovieResultV2"; -import { IMovieRequests } from "../../../../interfaces"; +import { IMovieRequests, RequestSource } from "../../../../interfaces"; import { SearchV2Service } from "../../../../services/searchV2.service"; import { IMovieRatings } from "../../../../interfaces/IRatings"; import { APP_BASE_HREF } from "@angular/common"; @@ -21,6 +21,7 @@ export class MovieInformationPanelComponent implements OnInit { public ratings: IMovieRatings; public streams: IStreamingData[]; + public RequestSource = RequestSource; public baseUrl: string; diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.ts index 3132ac84f..caa799794 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.ts @@ -4,6 +4,7 @@ import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog"; import { RequestService, MessageService } from "../../../../services"; import { TranslateService } from "@ngx-translate/core"; import { RequestType, IRequestEngineResult } from "../../../../interfaces"; +import { firstValueFrom } from "rxjs"; @Component({ selector: "deny-dialog", @@ -22,13 +23,13 @@ export class DenyDialogComponent { public async deny() { let result: IRequestEngineResult; if(this.data.requestType == RequestType.movie) { - result = await this.requestService.denyMovie({id: this.data.requestId, reason: this.denyReason }).toPromise(); + result = await firstValueFrom(this.requestService.denyMovie({id: this.data.requestId, reason: this.denyReason, is4K: this.data.is4K })); } if(this.data.requestType == RequestType.tvShow) { - result = await this.requestService.denyChild({id: this.data.requestId, reason: this.denyReason }).toPromise(); + result = await firstValueFrom(this.requestService.denyChild({id: this.data.requestId, reason: this.denyReason })); } if(this.data.requestType == RequestType.album) { - result = await this.requestService.denyAlbum({id: this.data.requestId, reason: this.denyReason }).toPromise(); + result = await firstValueFrom(this.requestService.denyAlbum({id: this.data.requestId, reason: this.denyReason })); } if (result.result) { diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/interfaces/interfaces.ts b/src/Ombi/ClientApp/src/app/media-details/components/shared/interfaces/interfaces.ts index 4237386c4..215a82ace 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/interfaces/interfaces.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/interfaces/interfaces.ts @@ -4,6 +4,7 @@ export interface IDenyDialogData { requestType: RequestType; requestId: number; denied: boolean; + is4K: boolean; } export interface IIssueDialogData { diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html index f05792aa9..d97bb4c02 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html @@ -17,6 +17,9 @@ + + + @@ -35,9 +38,13 @@ {{ 'MediaDetails.RadarrConfiguration' | translate}} {{ 'MediaDetails.SonarrConfiguration' | translate}} - +
diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.scss b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.scss index 1da3e6841..fd31c4b6f 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.scss +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.scss @@ -4,6 +4,16 @@ a.media-icons:hover{ color:$ombi-active; } +a.media-icons:hover img{ + filter: sepia(100%) hue-rotate(190deg) saturate(500%) brightness(190%); +} + +a.media-icons img{ + filter: contrast(0) brightness(3); + height: 2em; + padding: 0; +} + button.admin-cog{ margin-left:40px; color:$ombi-active; diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.ts index bc504347b..9215c1464 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.ts @@ -23,10 +23,12 @@ export class SocialIconsComponent { @Input() isAdmin: boolean; @Input() canShowAdvanced: boolean; + @Input() has4KRequest: boolean; @Output() openTrailer: EventEmitter = new EventEmitter(); @Output() onAdvancedOptions: EventEmitter = new EventEmitter(); @Output() onReProcessRequest: EventEmitter = new EventEmitter(); + @Output() onReProcess4KRequest: EventEmitter = new EventEmitter(); public RequestType = RequestType; @@ -39,7 +41,11 @@ export class SocialIconsComponent { this.onAdvancedOptions.emit(); } - public reProcessRequest() { - this.onReProcessRequest.emit(); + public reProcessRequest(is4K: boolean) { + if (is4K) { + this.onReProcess4KRequest.emit(); + } else { + this.onReProcessRequest.emit(); + } } } diff --git a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-request-grid/tv-request-grid.component.scss b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-request-grid/tv-request-grid.component.scss index b585dc939..adfd31a1e 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-request-grid/tv-request-grid.component.scss +++ b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-request-grid/tv-request-grid.component.scss @@ -31,7 +31,7 @@ .top-right.approved span:before{ display: inline-block; - background-color: #ff5722; + background-color: #ffd740; } .top-right.requested span { @@ -40,10 +40,10 @@ .top-right.requested span:before{ display: inline-block; - background-color: #ffd740; + background-color: #ff5722; } .top-right.denied span:before{ display: inline-block; - background-color: #ff4040; + background-color: #660202; } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.html b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.html index 4098bb748..ea34849d0 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.html @@ -9,6 +9,7 @@ user: request.requestedUser.userAlias, date: request.requestedDate | amLocal | amUserLocale | amDateFormat: 'LL' } }} - {{request.deniedReason}} +  {{'MediaDetails.RequestSource' | translate }} {{RequestSource[request.source]}} diff --git a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.ts index 10eee3989..e397e60ea 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.ts @@ -1,5 +1,5 @@ import { Component, Input } from "@angular/core"; -import { IChildRequests, RequestType } from "../../../../../interfaces"; +import { IChildRequests, RequestSource, RequestType } from "../../../../../interfaces"; import { DenyDialogComponent } from "../../../shared/deny-dialog/deny-dialog.component"; import { MatDialog } from "@angular/material/dialog"; @@ -17,6 +17,8 @@ export class TvRequestsPanelComponent { @Input() public isAdmin: boolean; @Input() public manageOwnRequests: boolean; + public RequestSource = RequestSource; + public displayedColumns: string[] = ['number', 'title', 'airDate', 'status']; constructor(private requestService: RequestService, @@ -100,7 +102,7 @@ export class TvRequestsPanelComponent { } public reProcessRequest(request: IChildRequests) { - this.requestService2.reprocessRequest(request.id, RequestType.tvShow).subscribe(result => { + this.requestService2.reprocessRequest(request.id, RequestType.tvShow, false).subscribe(result => { if (result.result) { this.messageService.send(result.message ? result.message : "Successfully Re-processed the request", "Ok"); } else { diff --git a/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.html b/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.html index 9397e07b8..cb1ec6ffb 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.html @@ -65,7 +65,7 @@ (click)="request()"> {{ 'Common.Request' | translate }} - @@ -82,6 +82,10 @@ class="btn-spacing" color="accent" [disabled]> {{'Common.PartiallyAvailable' | translate }} + +
- + @@ -66,6 +66,14 @@ + + + + + @@ -90,6 +98,9 @@ - + + + + \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts index 111c299c5..ca36a5d62 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts @@ -5,6 +5,7 @@ import { Observable, combineLatest, forkJoin, merge, of as observableOf } from ' import { catchError, map, startWith, switchMap } from 'rxjs/operators'; import { AuthService } from "../../../auth/auth.service"; +import { FeaturesFacade } from "../../../state/features/features.facade"; import { MatPaginator } from "@angular/material/paginator"; import { MatSort } from "@angular/material/sort"; import { MatTableDataSource } from "@angular/material/table"; @@ -26,6 +27,7 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { public displayedColumns: string[] = ['title', 'requestedUser.requestedBy', 'status', 'requestStatus','requestedDate', 'actions']; public gridCount: string = "15"; public isAdmin: boolean; + public is4kEnabled = false; public manageOwnRequests: boolean; public defaultSort: string = "requestedDate"; public defaultOrder: string = "desc"; @@ -41,7 +43,7 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { private storageKeyGridCount = "Movie_DefaultGridCount"; private storageKeyCurrentFilter = "Movie_DefaultFilter"; - @Output() public onOpenOptions = new EventEmitter<{ request: any, filter: any, onChange: any, manageOwnRequests: boolean, isAdmin: boolean }>(); + @Output() public onOpenOptions = new EventEmitter<{ request: any, filter: any, onChange: any, manageOwnRequests: boolean, isAdmin: boolean, has4kRequest: boolean, hasRegularRequest: boolean }>(); @ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatSort) sort: MatSort; @@ -49,7 +51,8 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { constructor(private requestService: RequestServiceV2, private ref: ChangeDetectorRef, private auth: AuthService, private storageService: StorageService, private requestServiceV1: RequestService, private notification: NotificationService, - private translateService: TranslateService) { + private translateService: TranslateService, + private featureFacade: FeaturesFacade) { this.userName = auth.claims().name; } @@ -60,6 +63,13 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { if (this.isAdmin) { this.displayedColumns.unshift('select'); } + + this.is4kEnabled = this.featureFacade.is4kEnabled(); + if ((this.isAdmin || this.auth.hasRole("Request4KMovie")) + && this.is4kEnabled) { + this.displayedColumns.splice(4, 0, 'has4kRequest'); + } + const defaultCount = this.storageService.get(this.storageKeyGridCount); const defaultSort = this.storageService.get(this.storageKey); const defaultOrder = this.storageService.get(this.storageKeyOrder); @@ -139,10 +149,20 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { this.ref.detectChanges(); }; - const data = { request: request, filter: filter, onChange: onChange, manageOwnRequests: this.manageOwnRequests, isAdmin: this.isAdmin }; + const data = { request: request, filter: filter, onChange: onChange, manageOwnRequests: this.manageOwnRequests, isAdmin: this.isAdmin, has4kRequest: request.has4KRequest, hasRegularRequest: this.checkDate(request.requestedDate) }; this.onOpenOptions.emit(data); } + private checkDate(date: Date|string): boolean { + if (typeof date === 'string') { + return new Date(date).getFullYear() > 1; + } + if (date instanceof Date) { + return date.getFullYear() > 1; + } + return false; + } + public switchFilter(type: RequestFilterType) { this.currentFilter = type; this.ngAfterViewInit(); @@ -152,15 +172,15 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { const numSelected = this.selection.selected.length; const numRows = this.dataSource.data.length; return numSelected === numRows; - } + } - public masterToggle() { + public masterToggle() { this.isAllSelected() ? this.selection.clear() : this.dataSource.data.forEach(row => this.selection.select(row)); - } + } - public async bulkDelete() { + public async bulkDelete() { if (this.selection.isEmpty()) { return; } @@ -174,15 +194,19 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { this.selection.clear(); this.ngAfterViewInit(); }); - } + } - public bulkApprove() { + public bulkApprove = () => this.bulkApproveInternal(false); + + public bulkApprove4K = () => this.bulkApproveInternal(true); + + private bulkApproveInternal(is4k: boolean) { if (this.selection.isEmpty()) { return; } let tasks = new Array>(); this.selection.selected.forEach((selected) => { - tasks.push(this.requestServiceV1.approveMovie({ id: selected.id })); + tasks.push(this.requestServiceV1.approveMovie({ id: selected.id, is4K: is4k })); }); this.isLoadingResults = true; @@ -198,5 +222,45 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { this.selection.clear(); this.ngAfterViewInit(); }) - } + } + + public bulkDeny = () => this.bulkDenyInternal(false); + + public bulkDeny4K = () => this.bulkDenyInternal(true); + + private bulkDenyInternal(is4k: boolean) { + if (this.selection.isEmpty()) { + return; + } + let tasks = new Array>(); + this.selection.selected.forEach((selected) => { + + tasks.push(this.requestServiceV1.denyMovie({ + id: selected.id, + is4K: is4k, + reason: `` // TOOD: reuse DenyDialog to allow for a reason to be entered + })); + }); + + this.isLoadingResults = true; + forkJoin(tasks).subscribe((result: IRequestEngineResult[]) => { + this.isLoadingResults = false; + const failed = result.filter(x => !x.result); + if (failed.length > 0) { + this.notification.error("Some requests failed to deny: " + failed[0].errorMessage); + this.selection.clear(); + return; + } + this.notification.success(this.translateService.instant('Requests.RequestPanel.Denied')); + this.selection.clear(); + this.ngAfterViewInit(); + }) + } + + public getRequestDate(request: IMovieRequests): Date { + if (new Date(request.requestedDate).getFullYear() === 1) { + return request.requestedDate4k; + } + return request.requestedDate; + } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html index ac974ece8..b32c872ac 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html +++ b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html @@ -1,11 +1,20 @@ - - {{'Requests.RequestPanel.Delete' | translate}} - - + {{'Requests.RequestPanel.Approve' | translate}} + + {{'Requests.RequestPanel.Deny' | translate}} + + + {{'Requests.RequestPanel.Approve4K' | translate}} + + + {{'Requests.RequestPanel.Deny4K' | translate}} + {{'Requests.RequestPanel.ChangeAvailability' | translate}} + + {{'Requests.RequestPanel.Delete' | translate}} + \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts index aa98943ca..909c34544 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts @@ -4,7 +4,9 @@ import { MessageService, RequestService } from '../../../services'; import { IRequestEngineResult, RequestType } from '../../../interfaces'; import { UpdateType } from '../../models/UpdateType'; import { TranslateService } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; +import { firstValueFrom, Observable } from 'rxjs'; +import { DenyDialogComponent } from '../../../media-details/components/shared/deny-dialog/deny-dialog.component'; +import { MatDialog } from '@angular/material/dialog'; @Component({ selector: 'request-options', @@ -15,8 +17,9 @@ export class RequestOptionsComponent { public RequestType = RequestType; constructor(@Inject(MAT_BOTTOM_SHEET_DATA) public data: any, - private requestService: RequestService, + private requestService: RequestService, private messageService: MessageService, + public dialog: MatDialog, private bottomSheetRef: MatBottomSheetRef, private translate: TranslateService) { } @@ -33,36 +36,64 @@ export class RequestOptionsComponent { } request.subscribe(result => { if (result.result) { - this.messageService.send(this.translate.instant("Requests.SuccessfullyDeleted")); - this.bottomSheetRef.dismiss({type: UpdateType.Delete}); - return; + this.messageService.send(this.translate.instant("Requests.SuccessfullyDeleted")); + this.bottomSheetRef.dismiss({type: UpdateType.Delete}); + return; } else { - this.messageService.sendRequestEngineResultError(result); + this.messageService.sendRequestEngineResultError(result); } }); } public async approve() { if (this.data.type === RequestType.movie) { - await this.requestService.approveMovie({id: this.data.id}).toPromise(); + await firstValueFrom(this.requestService.approveMovie({id: this.data.id, is4K: false})); } if (this.data.type === RequestType.tvShow) { - await this.requestService.approveChild({id: this.data.id}).toPromise(); + await firstValueFrom(this.requestService.approveChild({id: this.data.id})); } if (this.data.type === RequestType.album) { - await this.requestService.approveAlbum({id: this.data.id}).toPromise(); + await firstValueFrom(this.requestService.approveAlbum({id: this.data.id})); } this.bottomSheetRef.dismiss({type: UpdateType.Approve}); return; } + public deny = () => this.denyInternal(false); + + public deny4K = () => this.denyInternal(true); + + private async denyInternal(is4K: boolean) { + const dialogRef = this.dialog.open(DenyDialogComponent, { + width: '250px', + data: { requestId: this.data.id, is4K: is4K, requestType: this.data.type } + }); + + dialogRef.afterClosed().subscribe(result => { + if (result.denied) { + this.bottomSheetRef.dismiss({ type: UpdateType.Deny }); + + } + }); + } + + public async approve4K() { + if (this.data.type != RequestType.movie) { + return; + } + + await firstValueFrom(this.requestService.approveMovie({id: this.data.id, is4K: true})); + this.bottomSheetRef.dismiss({type: UpdateType.Approve}); + return; + } + public async changeAvailability() { if (this.data.type === RequestType.movie) { - await this.requestService.markMovieAvailable({id: this.data.id}).toPromise(); + await firstValueFrom(this.requestService.markMovieAvailable({id: this.data.id, is4K: false})) } if (this.data.type === RequestType.album) { - await this.requestService.markAlbumAvailable({id: this.data.id}).toPromise(); + await firstValueFrom(this.requestService.markAlbumAvailable({id: this.data.id})); } this.bottomSheetRef.dismiss({type: UpdateType.Availability}); diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.ts index 351c5a794..4ea6e4886 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.ts @@ -1,7 +1,6 @@ import { Component, ViewChild } from "@angular/core"; import { MatBottomSheet } from "@angular/material/bottom-sheet"; -import { MoviesGridComponent } from "./movies-grid/movies-grid.component"; import { RequestOptionsComponent } from "./options/request-options.component"; import { UpdateType } from "../models/UpdateType"; @@ -13,8 +12,8 @@ export class RequestsListComponent { constructor(private bottomSheet: MatBottomSheet) { } - public onOpenOptions(event: { request: any, filter: any, onChange: any, manageOwnRequests: boolean, isAdmin: boolean }) { - const ref = this.bottomSheet.open(RequestOptionsComponent, { data: { id: event.request.id, type: event.request.requestType, canApprove: event.request.canApprove, manageOwnRequests: event.manageOwnRequests, isAdmin: event.isAdmin } }); + public onOpenOptions(event: { request: any, filter: any, onChange: any, manageOwnRequests: boolean, isAdmin: boolean, has4kRequest: boolean, hasRegularRequest: boolean }) { + const ref = this.bottomSheet.open(RequestOptionsComponent, { data: { id: event.request.id, type: event.request.requestType, canApprove: event.request.canApprove, manageOwnRequests: event.manageOwnRequests, isAdmin: event.isAdmin, has4kRequest: event.has4kRequest, hasRegularRequest: event.hasRegularRequest } }); ref.afterDismissed().subscribe((result) => { if(!result) { @@ -36,6 +35,11 @@ export class RequestsListComponent { event.onChange(); return; } + if (result.type == UpdateType.Deny) { + event.request.requestStatus = 'Common.Denied'; + event.onChange(); + return; + } }); } } diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.ts index 5e8521302..25c552924 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.ts @@ -1,14 +1,14 @@ -import { Component, AfterViewInit, ViewChild, Output, EventEmitter, ChangeDetectorRef, OnInit } from "@angular/core"; -import { IRequestsViewModel, IChildRequests } from "../../../interfaces"; -import { MatPaginator } from "@angular/material/paginator"; -import { MatSort } from "@angular/material/sort"; -import { merge, of as observableOf, Observable } from 'rxjs'; +import { AfterViewInit, ChangeDetectorRef, Component, EventEmitter, OnInit, Output, ViewChild } from "@angular/core"; +import { IChildRequests, IRequestsViewModel } from "../../../interfaces"; +import { Observable, merge, of as observableOf } from 'rxjs'; import { catchError, map, startWith, switchMap } from 'rxjs/operators'; -import { RequestServiceV2 } from "../../../services/requestV2.service"; import { AuthService } from "../../../auth/auth.service"; -import { StorageService } from "../../../shared/storage/storage-service"; +import { MatPaginator } from "@angular/material/paginator"; +import { MatSort } from "@angular/material/sort"; import { RequestFilterType } from "../../models/RequestFilterType"; +import { RequestServiceV2 } from "../../../services/requestV2.service"; +import { StorageService } from "../../../shared/storage/storage-service"; @Component({ templateUrl: "./tv-grid.component.html", @@ -34,7 +34,7 @@ export class TvGridComponent implements OnInit, AfterViewInit { private storageKeyGridCount = "Tv_DefaultGridCount"; private storageKeyCurrentFilter = "Tv_DefaultFilter"; - @Output() public onOpenOptions = new EventEmitter<{request: any, filter: any, onChange: any}>(); + @Output() public onOpenOptions = new EventEmitter<{ request: any, filter: any, onChange: any, manageOwnRequests: boolean, isAdmin: boolean, has4kRequest: boolean, hasRegularRequest: boolean }>(); @ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatSort) sort: MatSort; @@ -108,7 +108,7 @@ export class TvGridComponent implements OnInit, AfterViewInit { this.ref.detectChanges(); }; - const data = { request: request, filter: filter, onChange: onChange, manageOwnRequests: this.manageOwnRequests, isAdmin: this.isAdmin }; + const data = { request: request, filter: filter, onChange: onChange, manageOwnRequests: this.manageOwnRequests, isAdmin: this.isAdmin, has4kRequest: false, hasRegularRequest: true }; this.onOpenOptions.emit(data); } diff --git a/src/Ombi/ClientApp/src/app/requests-list/models/UpdateType.ts b/src/Ombi/ClientApp/src/app/requests-list/models/UpdateType.ts index 3a0f690db..9e54b1114 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/models/UpdateType.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/models/UpdateType.ts @@ -1,5 +1,6 @@ export enum UpdateType { Delete, Approve, - Availability + Availability, + Deny } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/services/applications/themoviedb.service.ts b/src/Ombi/ClientApp/src/app/services/applications/themoviedb.service.ts index a49fb4146..d2c5b6122 100644 --- a/src/Ombi/ClientApp/src/app/services/applications/themoviedb.service.ts +++ b/src/Ombi/ClientApp/src/app/services/applications/themoviedb.service.ts @@ -25,10 +25,6 @@ export class TheMovieDbService extends ServiceHelpers { .pipe(catchError((error: HttpErrorResponse) => error.status === 404 ? empty() : throwError(error))); } - public getGenres(media: string): Observable { - return this.http.get(`${this.url}/Genres/${media}`, { headers: this.headers }) - } - public getWatchProviders(media: string): Observable { return this.http.get(`${this.url}/WatchProviders/${media}`, {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/src/app/services/feature.service.ts b/src/Ombi/ClientApp/src/app/services/feature.service.ts new file mode 100644 index 000000000..18a9cf86f --- /dev/null +++ b/src/Ombi/ClientApp/src/app/services/feature.service.ts @@ -0,0 +1,27 @@ +import { APP_BASE_HREF } from "@angular/common"; +import { Injectable, Inject } from "@angular/core"; + +import { HttpClient } from "@angular/common/http"; +import { Observable } from "rxjs"; + +import { IFeatureEnablement } from "../interfaces"; +import { ServiceHelpers } from "./service.helpers"; + +@Injectable({ providedIn: "root" }) +export class FeatureService extends ServiceHelpers { + constructor(http: HttpClient, @Inject(APP_BASE_HREF) href:string) { + super(http, "/api/v2/Features/", href); + } + + public getFeatures(): Observable { + return this.http.get(this.url, {headers: this.headers}); + } + + public enable(feature: IFeatureEnablement): Observable { + return this.http.post(`${this.url}enable`, JSON.stringify(feature), {headers: this.headers}); + } + + public disable(feature: IFeatureEnablement): Observable { + return this.http.post(`${this.url}disable`, JSON.stringify(feature), {headers: this.headers}); + } +} diff --git a/src/Ombi/ClientApp/src/app/services/filedownload.service.ts b/src/Ombi/ClientApp/src/app/services/filedownload.service.ts index 59cc00def..88e7cd441 100644 --- a/src/Ombi/ClientApp/src/app/services/filedownload.service.ts +++ b/src/Ombi/ClientApp/src/app/services/filedownload.service.ts @@ -1,3 +1,9 @@ +// https://github.com/microsoft/TypeScript/issues/45612 +declare global { + interface Navigator { + msSaveOrOpenBlob: (blob: Blob) => void + } +} import { APP_BASE_HREF } from "@angular/common"; import { Injectable, Inject } from "@angular/core"; diff --git a/src/Ombi/ClientApp/src/app/services/job.service.ts b/src/Ombi/ClientApp/src/app/services/job.service.ts index 8bd08c4f5..6cece68d9 100644 --- a/src/Ombi/ClientApp/src/app/services/job.service.ts +++ b/src/Ombi/ClientApp/src/app/services/job.service.ts @@ -27,6 +27,10 @@ export class JobService extends ServiceHelpers { return this.http.post(`${this.url}plexUserImporter/`, {headers: this.headers}); } + public runPlexWatchlistImport(): Observable { + return this.http.post(`${this.url}plexwatchlist/`, {headers: this.headers}); + } + public runEmbyImporter(): Observable { return this.http.post(`${this.url}embyUserImporter/`, {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/src/app/services/requestV2.service.ts b/src/Ombi/ClientApp/src/app/services/requestV2.service.ts index 433547b8f..62ff11aef 100644 --- a/src/Ombi/ClientApp/src/app/services/requestV2.service.ts +++ b/src/Ombi/ClientApp/src/app/services/requestV2.service.ts @@ -93,8 +93,8 @@ export class RequestServiceV2 extends ServiceHelpers { return this.http.post(`${this.url}TV/`, JSON.stringify(tv), {headers: this.headers}); } - public reprocessRequest(requestId: number, type: RequestType): Observable { - return this.http.post(`${this.url}reprocess/${type}/${requestId}`, undefined, { headers: this.headers }); + public reprocessRequest(requestId: number, type: RequestType, is4K: boolean): Observable { + return this.http.post(`${this.url}reprocess/${type}/${requestId}/${is4K}`, undefined, { headers: this.headers }); } public requestMovieCollection(collectionId: number): Observable { diff --git a/src/Ombi/ClientApp/src/app/services/searchV2.service.ts b/src/Ombi/ClientApp/src/app/services/searchV2.service.ts index 9e065ea97..c80655370 100644 --- a/src/Ombi/ClientApp/src/app/services/searchV2.service.ts +++ b/src/Ombi/ClientApp/src/app/services/searchV2.service.ts @@ -4,7 +4,7 @@ import { Injectable, Inject } from "@angular/core"; import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; -import { IDiscoverModel, IMultiSearchResult, ISearchMovieResult, ISearchTvResult } from "../interfaces"; +import { IDiscoverModel, IMovieDbKeyword, IMultiSearchResult, ISearchMovieResult, ISearchTvResult } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; import { ISearchMovieResultV2 } from "../interfaces/ISearchMovieResultV2"; @@ -23,6 +23,11 @@ export class SearchV2Service extends ServiceHelpers { public multiSearch(searchTerm: string, filter: SearchFilter): Observable { return this.http.post(`${this.url}/multi/${encodeURIComponent(searchTerm)}`, filter); } + + public getGenres(media: string): Observable { + return this.http.get(`${this.url}/Genres/${media}`, { headers: this.headers }) + } + public getFullMovieDetails(theMovieDbId: number): Observable { return this.http.get(`${this.url}/Movie/${theMovieDbId}`); } diff --git a/src/Ombi/ClientApp/src/app/services/settings.service.ts b/src/Ombi/ClientApp/src/app/services/settings.service.ts index 3f4409d0c..4758c8382 100644 --- a/src/Ombi/ClientApp/src/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/src/app/services/settings.service.ts @@ -39,6 +39,7 @@ import { IVoteSettings, ITwilioSettings, IWebhookNotificationSettings, + IRadarrCombined, } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; @@ -101,11 +102,11 @@ export class SettingsService extends ServiceHelpers { return this.http.post(`${this.url}/Sonarr`, JSON.stringify(settings), {headers: this.headers}); } - public getRadarr(): Observable { - return this.http.get(`${this.url}/Radarr`, {headers: this.headers}); + public getRadarr(): Observable { + return this.http.get(`${this.url}/Radarr`, {headers: this.headers}); } - public saveRadarr(settings: IRadarrSettings): Observable { + public saveRadarr(settings: IRadarrCombined): Observable { return this.http.post(`${this.url}/Radarr`, JSON.stringify(settings), {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.html b/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.html index 7bc6a4e80..5960c79f7 100644 --- a/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.html +++ b/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.html @@ -1,66 +1,46 @@ - +
Authentication
-
-
- - Allow users to login without a password -
-
+
+
+ + Allow users to login without a password + +
+
-
-
- Enable Plex OAuth -
-
+
+
+ Enable Plex OAuth +
+
- - -
-
-
-
-
- +
+
+
+
+
+
-
\ No newline at end of file + diff --git a/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.ts b/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.ts index 6f140f8af..100a502b3 100644 --- a/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.ts @@ -1,5 +1,5 @@ -import { Component, OnInit } from "@angular/core"; -import { FormBuilder, FormGroup } from "@angular/forms"; +import { Component, OnInit } from "@angular/core"; +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; import { NotificationService } from "../../services"; import { SettingsService } from "../../services"; @@ -26,8 +26,20 @@ export class AuthenticationComponent implements OnInit { requireNonAlphanumeric: [x.requireNonAlphanumeric], requireUppercase: [x.requireUppercase], enableOAuth: [x.enableOAuth], + enableHeaderAuth: [x.enableHeaderAuth], + headerAuthVariable: [x.headerAuthVariable], + }); + this.form.controls.enableHeaderAuth.valueChanges.subscribe(x => { + if (x) { + this.form.get("headerAuthVariable").setValidators(Validators.required); + } else { + this.form.get("headerAuthVariable").clearValidators(); + } + this.form.get("headerAuthVariable").updateValueAndValidity(); }); }); + + } public onSubmit(form: FormGroup) { diff --git a/src/Ombi/ClientApp/src/app/settings/features/features.component.html b/src/Ombi/ClientApp/src/app/settings/features/features.component.html new file mode 100644 index 000000000..4eb975cfe --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/features/features.component.html @@ -0,0 +1,20 @@ + + +
+ Features + +
+
+
+
+
+ +
+
+

{{feature.name}}

+
+
+
+
+
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/features/features.component.scss b/src/Ombi/ClientApp/src/app/settings/features/features.component.scss new file mode 100644 index 000000000..658d13101 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/features/features.component.scss @@ -0,0 +1,5 @@ +.small-middle-container { + margin: auto; + width: 95%; + margin-top: 10px; +} diff --git a/src/Ombi/ClientApp/src/app/settings/features/features.component.ts b/src/Ombi/ClientApp/src/app/settings/features/features.component.ts new file mode 100644 index 000000000..75a155b6c --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/features/features.component.ts @@ -0,0 +1,32 @@ +import { Component, OnInit } from "@angular/core"; + +import { FeaturesFacade } from "../../state/features"; +import { IFeatureEnablement } from "../../interfaces"; +import { MatSlideToggleChange } from "@angular/material/slide-toggle"; +import { firstValueFrom } from "rxjs"; + +@Component({ + templateUrl: "./features.component.html", + styleUrls: ["./features.component.scss"] +}) +export class FeaturesComponent implements OnInit { + + public features: IFeatureEnablement[]; + + constructor(private readonly featuresFacade: FeaturesFacade) { } + + public async ngOnInit() { + this.featuresFacade.features$().subscribe(x => { + this.features = x; + }); + + } + + public updateFeature(change: MatSlideToggleChange, feature: IFeatureEnablement) { + if (change.checked) { + firstValueFrom(this.featuresFacade.enable(feature)); + } else { + firstValueFrom(this.featuresFacade.disable(feature)); + } + } +} diff --git a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.html b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.html index e15a88b7f..47e7ef1cd 100644 --- a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.html +++ b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.html @@ -77,6 +77,13 @@ The Plex Sync is required +
+ + Plex Watchlist Import + + The Plex Watchlist Import is required + +
diff --git a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.ts b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.ts index 47d05776b..89131bc42 100644 --- a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.ts @@ -37,6 +37,7 @@ export class JobsComponent implements OnInit { mediaDatabaseRefresh: [x.mediaDatabaseRefresh, Validators.required], autoDeleteRequests: [x.autoDeleteRequests, Validators.required], embyRecentlyAddedSync: [x.embyRecentlyAddedSync, Validators.required], + plexWatchlistImport: [x.plexWatchlistImport, Validators.required], }); }); } diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.html index 5c24d21f2..7e95b0dfd 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.html +++ b/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.html @@ -57,21 +57,6 @@
- -
- - Admin Email - - - Admin Email is required - - - Admin Email needs to be a valid email address - - -
- -
Username diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.ts b/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.ts index f880891a5..7673e2e1d 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.ts @@ -35,7 +35,6 @@ export class EmailNotificationComponent implements OnInit { senderAddress: [x.senderAddress, [Validators.required, Validators.email]], senderName: [x.senderName], username: [x.username], - adminEmail: [x.adminEmail, [Validators.required, Validators.email]], disableTLS: [x.disableTLS], disableCertificateChecking: [x.disableCertificateChecking], }); diff --git a/src/Ombi/ClientApp/src/app/settings/plex/plex.component.html b/src/Ombi/ClientApp/src/app/settings/plex/plex.component.html index f84395043..858a94358 100644 --- a/src/Ombi/ClientApp/src/app/settings/plex/plex.component.html +++ b/src/Ombi/ClientApp/src/app/settings/plex/plex.component.html @@ -9,6 +9,12 @@ Enable
+
+ Enable User Watchlist Requests + +

When a Plex User adds something to their watchlist in Plex, it will turn up in Ombi as a Request if enabled. This only applies to users that are logging in with their Plex Account

+

Request limits if set are all still applied etc.

+
Advanced
@@ -183,6 +189,12 @@ Clear Data And Resync +
+ +
diff --git a/src/Ombi/ClientApp/src/app/settings/plex/plex.component.ts b/src/Ombi/ClientApp/src/app/settings/plex/plex.component.ts index 8d42419fe..d7c977b7b 100644 --- a/src/Ombi/ClientApp/src/app/settings/plex/plex.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/plex/plex.component.ts @@ -172,6 +172,14 @@ export class PlexComponent implements OnInit, OnDestroy { }); } + public runWatchlistImport(): void { + this.jobService.runPlexWatchlistImport().subscribe(x => { + if (x) { + this.notificationService.success("Triggered the Watchlist Import"); + } + }); + } + public ngOnDestroy() { this.subscriptions.next(); this.subscriptions.complete(); diff --git a/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.html b/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.html new file mode 100644 index 000000000..2dbf6869d --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.html @@ -0,0 +1,101 @@ +
+
+
+
+
+ Enable +
+
+ Scan for Availability +
+
+ + Do not search for Movies + +
+
+
+
+
+
+
+ +
+ + Hostname or IP + + + + Port + + + + SSL + +
+
+
+ + API key + + +
+
+ + Base URL + + +
+
+
+ +
+
+ +
+
+ + Quality Profiles + + + {{quality.name}} + + + + +
+
+
+ +
+
+ + Default Root Folder + + + {{folder.path}} + + + + +
+
+ + Default Minimum Availability + + + {{min.name}} + + + +
+
+
+
+
+
+ +
+
+
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.scss b/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.scss new file mode 100644 index 000000000..bf4c9e420 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.scss @@ -0,0 +1,21 @@ +@import "~styles/shared.scss"; +.small-middle-container { + margin: auto; + width: 95%; + margin-top: 10px; +} + +.col-8 { + display: inline-table; +} +.col-md-5 { + display: inline-table; +} + +.row { + display: block; +} + +.top-spacing { + margin-top: 10px; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.ts b/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.ts new file mode 100644 index 000000000..e85bfc08b --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.ts @@ -0,0 +1,100 @@ +import { ChangeDetectionStrategy, Component, OnInit } from "@angular/core"; +import { ControlContainer, FormGroup, Validators } from "@angular/forms"; + +import { IMinimumAvailability, IRadarrProfile, IRadarrRootFolder, IRadarrSettings } from "../../../interfaces"; +import { TesterService, NotificationService, RadarrService } from "../../../services"; + + +@Component({ + selector: "ombi-settings-radarr-form", + templateUrl: "./radarr-form.component.html", + styleUrls: ["./radarr-form.component.scss"], + // changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RadarrFormComponent implements OnInit { + + public qualities: IRadarrProfile[]; + public rootFolders: IRadarrRootFolder[]; + public minimumAvailabilityOptions: IMinimumAvailability[]; + public profilesRunning: boolean; + public rootFoldersRunning: boolean; + public form: FormGroup; + + constructor(private radarrService: RadarrService, + private notificationService: NotificationService, + private testerService: TesterService, + private controlContainer: ControlContainer) { } + + public ngOnInit() { + this.form = this.controlContainer.control; + // this.toggleValidators(); + + this.qualities = []; + this.qualities.push({ name: "Please Select", id: -1 }); + + this.rootFolders = []; + this.rootFolders.push({ path: "Please Select", id: -1 }); + this.minimumAvailabilityOptions = [ + { name: "Announced", value: "Announced" }, + { name: "In Cinemas", value: "InCinemas" }, + { name: "Physical / Web", value: "Released" }, + ]; + + if (this.form.controls.defaultQualityProfile.value) { + this.getProfiles(this.form); + } + + if (this.form.controls.defaultRootPath.value) { + this.getRootFolders(this.form); + } + } + + public toggleValidators() { + const enabled = this.form.controls.enabled.value as boolean; + this.form.controls.apiKey.setValidators(enabled ? [Validators.required] : null); + this.form.controls.defaultQualityProfile.setValidators(enabled ? [Validators.required] : null); + this.form.controls.defaultRootPath.setValidators(enabled ? [Validators.required] : null); + this.form.controls.ip.setValidators(enabled ? [Validators.required] : null); + this.form.controls.port.setValidators(enabled ? [Validators.required] : null); + this.form.controls.minimumAvailability.setValidators(enabled ? [Validators.required] : null); + } + + public getProfiles(form: FormGroup) { + this.profilesRunning = true; + this.radarrService.getQualityProfiles(form.value).subscribe(x => { + this.qualities = x; + this.qualities.unshift({ name: "Please Select", id: -1 }); + + this.profilesRunning = false; + this.notificationService.success("Successfully retrieved the Quality Profiles"); + }); + } + + public getRootFolders(form: FormGroup) { + this.rootFoldersRunning = true; + this.radarrService.getRootFolders(form.value).subscribe(x => { + this.rootFolders = x; + this.rootFolders.unshift({ path: "Please Select", id: -1 }); + + this.rootFoldersRunning = false; + this.notificationService.success("Successfully retrieved the Root Folders"); + }); + } + + public test(form: FormGroup) { + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + const settings = form.value; + this.testerService.radarrTest(settings).subscribe(result => { + if (result.isValid) { + this.notificationService.success("Successfully connected to Radarr!"); + } else if (result.expectedSubDir) { + this.notificationService.error("Your Radarr Base URL must be set to " + result.expectedSubDir); + } else { + this.notificationService.error("We could not connect to Radarr!"); + } + }); + } +} diff --git a/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.html b/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.html index b6d30998a..724beccf1 100644 --- a/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.html +++ b/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.html @@ -4,107 +4,30 @@ Radarr Settings
-
-
-
-
- Enable -
-
- Scan for Availability -
-
- - Do not search for Movies - -
-
-
-
-
-
-
- -
- - Hostname or IP - - - - Port - - - - SSL - -
-
-
- - API key - - -
-
- - Base URL - - -
-
-
- -
-
- -
-
- - Quality Profiles - - - {{quality.name}} - - - -
-
-
- -
-
- - Default Root Folder - - - {{folder.path}} - - - + + + + + + + + + + -
-
- - Default Minimum Availability - - - {{min.name}} - - - -
-
-
-
-
-
- -
-
- -
-
+ + +
+
diff --git a/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.ts b/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.ts index 9e787b406..1e2925f13 100644 --- a/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.ts @@ -1,12 +1,9 @@ import { Component, OnInit } from "@angular/core"; -import { FormBuilder, FormGroup, Validators } from "@angular/forms"; +import { FormBuilder, FormGroup } from "@angular/forms"; -import { IMinimumAvailability, IRadarrProfile, IRadarrRootFolder } from "../../interfaces"; -import { IRadarrSettings } from "../../interfaces"; -import { RadarrService } from "../../services"; -import { TesterService } from "../../services"; -import { NotificationService } from "../../services"; -import { SettingsService } from "../../services"; +import { IMinimumAvailability, IRadarrCombined, IRadarrProfile, IRadarrRootFolder } from "../../interfaces"; +import { NotificationService, SettingsService } from "../../services"; +import { FeaturesFacade } from "../../state/features/features.facade"; @Component({ templateUrl: "./radarr.component.html", @@ -20,102 +17,67 @@ export class RadarrComponent implements OnInit { public profilesRunning: boolean; public rootFoldersRunning: boolean; public form: FormGroup; + public is4kEnabled: boolean = false; constructor(private settingsService: SettingsService, - private radarrService: RadarrService, private notificationService: NotificationService, - private fb: FormBuilder, - private testerService: TesterService) { } + private featureFacade: FeaturesFacade, + private fb: FormBuilder) { } public ngOnInit() { + this.is4kEnabled = this.featureFacade.is4kEnabled(); this.settingsService.getRadarr() .subscribe(x => { - this.form = this.fb.group({ - enabled: [x.enabled], - apiKey: [x.apiKey, [Validators.required]], - defaultQualityProfile: [+x.defaultQualityProfile, [Validators.required]], - defaultRootPath: [x.defaultRootPath, [Validators.required]], - ssl: [x.ssl], - subDir: [x.subDir], - ip: [x.ip, [Validators.required]], - port: [x.port, [Validators.required]], - addOnly: [x.addOnly], - minimumAvailability: [x.minimumAvailability, [Validators.required]], - scanForAvailability: [x.scanForAvailability] + radarr: this.fb.group({ + enabled: [x.radarr.enabled], + apiKey: [x.radarr.apiKey], + defaultQualityProfile: [+x.radarr.defaultQualityProfile], + defaultRootPath: [x.radarr.defaultRootPath], + ssl: [x.radarr.ssl], + subDir: [x.radarr.subDir], + ip: [x.radarr.ip], + port: [x.radarr.port], + addOnly: [x.radarr.addOnly], + minimumAvailability: [x.radarr.minimumAvailability], + scanForAvailability: [x.radarr.scanForAvailability] + }), + radarr4K: this.fb.group({ + enabled: [x.radarr4K.enabled], + apiKey: [x.radarr4K.apiKey], + defaultQualityProfile: [+x.radarr4K.defaultQualityProfile], + defaultRootPath: [x.radarr4K.defaultRootPath], + ssl: [x.radarr4K.ssl], + subDir: [x.radarr4K.subDir], + ip: [x.radarr4K.ip], + port: [x.radarr4K.port], + addOnly: [x.radarr4K.addOnly], + minimumAvailability: [x.radarr4K.minimumAvailability], + scanForAvailability: [x.radarr4K.scanForAvailability] + }), }); - - if (x.defaultQualityProfile) { - this.getProfiles(this.form); - } - if (x.defaultRootPath) { - this.getRootFolders(this.form); - } }); - - this.qualities = []; - this.qualities.push({ name: "Please Select", id: -1 }); - - this.rootFolders = []; - this.rootFolders.push({ path: "Please Select", id: -1 }); - this.minimumAvailabilityOptions = [ - { name: "Announced", value: "Announced" }, - { name: "In Cinemas", value: "InCinemas" }, - { name: "Physical / Web", value: "Released" }, - ]; - } - public getProfiles(form: FormGroup) { - this.profilesRunning = true; - this.radarrService.getQualityProfiles(form.value).subscribe(x => { - this.qualities = x; - this.qualities.unshift({ name: "Please Select", id: -1 }); - this.profilesRunning = false; - this.notificationService.success("Successfully retrieved the Quality Profiles"); - }); - } - - public getRootFolders(form: FormGroup) { - this.rootFoldersRunning = true; - this.radarrService.getRootFolders(form.value).subscribe(x => { - this.rootFolders = x; - this.rootFolders.unshift({ path: "Please Select", id: -1 }); - - this.rootFoldersRunning = false; - this.notificationService.success("Successfully retrieved the Root Folders"); - }); - } - - public test(form: FormGroup) { + public onSubmit(form: FormGroup) { if (form.invalid) { this.notificationService.error("Please check your entered values"); return; } - const settings = form.value; - this.testerService.radarrTest(settings).subscribe(result => { - if (result.isValid) { - this.notificationService.success("Successfully connected to Radarr!"); - } else if (result.expectedSubDir) { - this.notificationService.error("Your Radarr Base URL must be set to " + result.expectedSubDir); - } else { - this.notificationService.error("We could not connect to Radarr!"); - } - }); - } + const radarrForm = form.controls.radarr as FormGroup; + const radarr4KForm = form.controls.radarr4K as FormGroup; -public onSubmit(form: FormGroup) { - if (form.invalid) { - this.notificationService.error("Please check your entered values"); + if (radarrForm.controls.enabled.value && (radarrForm.controls.defaultQualityProfile.value === -1 || radarrForm.controls.defaultRootPath.value === "Please Select")) { + this.notificationService.error("Please check your entered values for Radarr"); return; } - if (form.controls.defaultQualityProfile.value === "-1" || form.controls.defaultRootPath.value === "Please Select") { - this.notificationService.error("Please check your entered values"); + if (radarr4KForm.controls.enabled.value && (radarr4KForm.controls.defaultQualityProfile.value === -1 || radarr4KForm.controls.defaultRootPath.value === "Please Select")) { + this.notificationService.error("Please check your entered values for Radarr 4K"); return; } - const settings = form.value; + const settings = form.value; this.settingsService.saveRadarr(settings).subscribe(x => { if (x) { this.notificationService.success("Successfully saved Radarr settings"); diff --git a/src/Ombi/ClientApp/src/app/settings/settings.module.ts b/src/Ombi/ClientApp/src/app/settings/settings.module.ts index b486e5b26..144322194 100644 --- a/src/Ombi/ClientApp/src/app/settings/settings.module.ts +++ b/src/Ombi/ClientApp/src/app/settings/settings.module.ts @@ -1,76 +1,88 @@ -import { CommonModule } from "@angular/common"; -import { NgModule } from "@angular/core"; +import { + CouchPotatoService, + EmbyService, + FileDownloadService, + IssuesService, + JellyfinService, + JobService, + LidarrService, + MobileService, + NotificationMessageService, + PlexService, + RadarrService, + RequestRetryService, + SonarrService, + SystemService, + TesterService, + TheMovieDbService, + ValidationService +} from "../services"; import { FormsModule, ReactiveFormsModule } from "@angular/forms"; import { RouterModule, Routes } from "@angular/router"; -// import { TagInputModule } from "ngx-chips"; -import { ClipboardModule } from "ngx-clipboard"; +import { AboutComponent } from "./about/about.component"; import { AuthGuard } from "../auth/auth.guard"; import { AuthService } from "../auth/auth.service"; -import { - CouchPotatoService, EmbyService, JellyfinService, IssuesService, JobService, LidarrService, MobileService, NotificationMessageService, PlexService, RadarrService, - RequestRetryService, SonarrService, TesterService, ValidationService, SystemService, FileDownloadService, TheMovieDbService -} from "../services"; - -import { PipeModule } from "../pipes/pipe.module"; -import { AboutComponent } from "./about/about.component"; import { AuthenticationComponent } from "./authentication/authentication.component"; +import {AutoCompleteModule} from "primeng/autocomplete"; +import {CalendarModule} from "primeng/calendar"; +import { ClipboardModule } from "ngx-clipboard"; +import { CloudMobileComponent } from "./notifications/cloudmobile.coponent"; +import { CloudMobileService } from "../services/cloudmobile.service"; +import { CommonModule } from "@angular/common"; import { CouchPotatoComponent } from "./couchpotato/couchpotato.component"; import { CustomizationComponent } from "./customization/customization.component"; +import {DialogModule} from "primeng/dialog"; +import { DiscordComponent } from "./notifications/discord.component"; import { DogNzbComponent } from "./dognzb/dognzb.component"; +import { EmailNotificationComponent } from "./notifications/emailnotification.component"; import { EmbyComponent } from "./emby/emby.component"; -import { JellyfinComponent } from "./jellyfin/jellyfin.component"; import { FailedRequestsComponent } from "./failedrequests/failedrequests.component"; +import { FeaturesComponent } from "./features/features.component"; +import { GotifyComponent } from "./notifications/gotify.component"; +import { HubService } from "../services/hub.service"; +import {InputSwitchModule} from "primeng/inputswitch"; +import {InputTextModule} from "primeng/inputtext"; import { IssuesComponent } from "./issues/issues.component"; +import { JellyfinComponent } from "./jellyfin/jellyfin.component"; import { JobsComponent } from "./jobs/jobs.component"; import { LandingPageComponent } from "./landingpage/landingpage.component"; import { LidarrComponent } from "./lidarr/lidarr.component"; +import { LogsComponent } from "./logs/logs.component"; import { MassEmailComponent } from "./massemail/massemail.component"; -import { DiscordComponent } from "./notifications/discord.component"; -import { EmailNotificationComponent } from "./notifications/emailnotification.component"; -import { GotifyComponent } from "./notifications/gotify.component"; +import { MatDialogModule } from "@angular/material/dialog"; +import { MatMenuModule } from "@angular/material/menu"; import { MattermostComponent } from "./notifications/mattermost.component"; +import {MenuModule} from "primeng/menu"; import { MobileComponent } from "./notifications/mobile.component"; import { NewsletterComponent } from "./notifications/newsletter.component"; +import { NgModule } from "@angular/core"; import { NotificationTemplate } from "./notifications/notificationtemplate.component"; +import { OmbiComponent } from "./ombi/ombi.component"; +import { PipeModule } from "../pipes/pipe.module"; +import { PlexComponent } from "./plex/plex.component"; import { PushbulletComponent } from "./notifications/pushbullet.component"; import { PushoverComponent } from "./notifications/pushover.component"; -import { SlackComponent } from "./notifications/slack.component"; -import { TelegramComponent } from "./notifications/telegram.component"; -import { WebhookComponent } from "./notifications/webhook.component"; -import { OmbiComponent } from "./ombi/ombi.component"; -import { PlexComponent } from "./plex/plex.component"; import { RadarrComponent } from "./radarr/radarr.component"; +import { RadarrFormComponent } from "./radarr/components/radarr-form.component"; +import {RadioButtonModule} from "primeng/radiobutton"; +import { SettingsMenuComponent } from "./settingsmenu.component"; +import { SharedModule } from "../shared/shared.module"; import { SickRageComponent } from "./sickrage/sickrage.component"; +import { SlackComponent } from "./notifications/slack.component"; import { SonarrComponent } from "./sonarr/sonarr.component"; +import { TelegramComponent } from "./notifications/telegram.component"; import { TheMovieDbComponent } from "./themoviedb/themoviedb.component"; +import {TooltipModule} from "primeng/tooltip"; +import { TwilioComponent } from "./notifications/twilio/twilio.component"; import { UpdateComponent } from "./update/update.component"; +import { UpdateDialogComponent } from "./about/update-dialog.component"; +import { UpdateService } from "../services/update.service"; import { UserManagementComponent } from "./usermanagement/usermanagement.component"; import { VoteComponent } from "./vote/vote.component"; -import { WikiComponent } from "./wiki.component"; - -import { SettingsMenuComponent } from "./settingsmenu.component"; - -import {AutoCompleteModule } from "primeng/autocomplete"; -import {CalendarModule } from "primeng/calendar"; -import {InputSwitchModule } from "primeng/inputswitch"; -import {InputTextModule } from "primeng/inputtext"; -import {DialogModule } from "primeng/dialog"; -import {MenuModule } from "primeng/menu"; -import {RadioButtonModule } from "primeng/radiobutton"; -import {TooltipModule } from "primeng/tooltip"; - -import { MatMenuModule } from "@angular/material/menu"; -import { SharedModule } from "../shared/shared.module"; -import { HubService } from "../services/hub.service"; -import { LogsComponent } from "./logs/logs.component"; -import { TwilioComponent } from "./notifications/twilio/twilio.component"; +import { WebhookComponent } from "./notifications/webhook.component"; import { WhatsAppComponent } from "./notifications/twilio/whatsapp.component"; -import { CloudMobileComponent } from "./notifications/cloudmobile.coponent"; -import { CloudMobileService } from "../services/cloudmobile.service"; -import { UpdateService } from "../services/update.service"; -import { MatDialogModule } from "@angular/material/dialog"; -import { UpdateDialogComponent } from "./about/update-dialog.component"; +import { WikiComponent } from "./wiki.component"; const routes: Routes = [ { path: "Ombi", component: OmbiComponent, canActivate: [AuthGuard] }, @@ -109,6 +121,7 @@ const routes: Routes = [ { path: "FailedRequests", component: FailedRequestsComponent, canActivate: [AuthGuard] }, { path: "Logs", component: LogsComponent, canActivate: [AuthGuard] }, { path: "CloudMobile", component: CloudMobileComponent, canActivate: [AuthGuard] }, + { path: "Features", component: FeaturesComponent, canActivate: [AuthGuard] }, ]; @NgModule({ @@ -145,6 +158,7 @@ const routes: Routes = [ SonarrComponent, SlackComponent, RadarrComponent, + RadarrFormComponent, EmailNotificationComponent, NotificationTemplate, PushoverComponent, @@ -172,6 +186,7 @@ const routes: Routes = [ LogsComponent, TwilioComponent, WhatsAppComponent, + FeaturesComponent, CloudMobileComponent, UpdateDialogComponent, ], diff --git a/src/Ombi/ClientApp/src/app/settings/settingsmenu.component.html b/src/Ombi/ClientApp/src/app/settings/settingsmenu.component.html index bd6949ebb..bcbe7bd3a 100644 --- a/src/Ombi/ClientApp/src/app/settings/settingsmenu.component.html +++ b/src/Ombi/ClientApp/src/app/settings/settingsmenu.component.html @@ -2,6 +2,7 @@ + diff --git a/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts b/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts index 008e2dfab..512f60363 100644 --- a/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts @@ -5,7 +5,7 @@ import { IMovieDbKeyword, ITheMovieDbSettings } from "../../interfaces"; import { debounceTime, switchMap } from "rxjs/operators"; import { MatAutocomplete } from "@angular/material/autocomplete"; -import { NotificationService } from "../../services"; +import { NotificationService, SearchV2Service } from "../../services"; import { SettingsService } from "../../services"; import { TheMovieDbService } from "../../services"; @@ -33,6 +33,7 @@ export class TheMovieDbComponent implements OnInit { constructor(private settingsService: SettingsService, private notificationService: NotificationService, private tmdbService: TheMovieDbService, + private searchService: SearchV2Service, private fb: FormBuilder) { } public ngOnInit() { @@ -55,9 +56,10 @@ export class TheMovieDbComponent implements OnInit { this.excludedKeywords.forEach(key => { this.tmdbService.getKeyword(key.id).subscribe(keyResult => { - this.excludedKeywords.filter((val, idx) => { - val.name = keyResult.name; - }) + var keyToUpdate = this.excludedKeywords.filter((val) => { + return val.id == key.id; + })[0]; + keyToUpdate.name = keyResult.name; }); }); @@ -70,7 +72,7 @@ export class TheMovieDbComponent implements OnInit { })) : []; - this.tmdbService.getGenres("movie").subscribe(results => { + this.searchService.getGenres("movie").subscribe(results => { this.filteredMovieGenres = results; this.excludedMovieGenres.forEach(genre => { @@ -91,7 +93,7 @@ export class TheMovieDbComponent implements OnInit { })) : []; - this.tmdbService.getGenres("tv").subscribe(results => { + this.searchService.getGenres("tv").subscribe(results => { this.filteredTvGenres = results; this.excludedTvGenres.forEach(genre => { @@ -112,6 +114,7 @@ export class TheMovieDbComponent implements OnInit { if (value) { return this.tmdbService.getKeywords(value); } + return []; }) ) .subscribe((r) => (this.filteredTags = r)); diff --git a/src/Ombi/ClientApp/src/app/shared/admin-request-dialog/admin-request-dialog.component.ts b/src/Ombi/ClientApp/src/app/shared/admin-request-dialog/admin-request-dialog.component.ts index acf6560b9..d495a88e7 100644 --- a/src/Ombi/ClientApp/src/app/shared/admin-request-dialog/admin-request-dialog.component.ts +++ b/src/Ombi/ClientApp/src/app/shared/admin-request-dialog/admin-request-dialog.component.ts @@ -1,7 +1,7 @@ import { Component, Inject, OnInit } from "@angular/core"; import { FormBuilder, FormGroup } from "@angular/forms"; import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog"; -import { Observable } from "rxjs"; +import { firstValueFrom, Observable } from "rxjs"; import { startWith, map } from "rxjs/operators"; import { ILanguageProfiles, IRadarrProfile, IRadarrRootFolder, ISonarrProfile, ISonarrRootFolder, ISonarrSettings, IUserDropdown, RequestType } from "../../interfaces"; import { IdentityService, MessageService, RadarrService, RequestService, SettingsService, SonarrService } from "../../services"; @@ -55,7 +55,7 @@ export class AdminRequestDialogComponent implements OnInit { radarrFolderId: [null] }) - this.options = await this.identityService.getUsersDropdown().toPromise(); + this.options = await firstValueFrom(this.identityService.getUsersDropdown()); this.filteredOptions = this.form.controls['username'].valueChanges.pipe( startWith(""), @@ -96,7 +96,10 @@ export class AdminRequestDialogComponent implements OnInit { public displayFn(user: IUserDropdown): string { const username = user?.username ? user.username : ""; const email = user?.email ? `(${user.email})` : ""; - return `${username} ${email}`; + if (username && email) { + return `${username} ${email}`; + } + return ''; } private _filter(value: string | IUserDropdown): IUserDropdown[] { diff --git a/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.html b/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.html index 39e87c48b..a8fc88578 100644 --- a/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.html +++ b/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.html @@ -1,7 +1,7 @@
-

{{ "Issues.UserManagement" | translate }}

+

{{ "NavigationBar.UserManagement" | translate }}

{{user}}

diff --git a/src/Ombi/ClientApp/src/app/shared/components/genre-select/genre-select.component.ts b/src/Ombi/ClientApp/src/app/shared/components/genre-select/genre-select.component.ts index 06c92e4cf..839b8169c 100644 --- a/src/Ombi/ClientApp/src/app/shared/components/genre-select/genre-select.component.ts +++ b/src/Ombi/ClientApp/src/app/shared/components/genre-select/genre-select.component.ts @@ -5,7 +5,7 @@ import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from "r import { IMovieDbKeyword } from "../../../interfaces"; import { MatAutocompleteSelectedEvent } from "@angular/material/autocomplete"; import { Observable } from "rxjs"; -import { TheMovieDbService } from "../../../services"; +import { SearchV2Service } from "../../../services"; @Component({ selector: "genre-select", @@ -13,7 +13,7 @@ import { TheMovieDbService } from "../../../services"; }) export class GenreSelectComponent { constructor( - private tmdbService: TheMovieDbService + private searchService: SearchV2Service ) {} @Input() public form: FormGroup; @@ -21,7 +21,7 @@ export class GenreSelectComponent { private _mediaType: string; @Input() set mediaType(type: string) { this._mediaType = type; - this.tmdbService.getGenres(this._mediaType).subscribe((res) => { + this.searchService.getGenres(this._mediaType).subscribe((res) => { this.genres = res; this.filteredKeywords = this.control.valueChanges.pipe( startWith(''), diff --git a/src/Ombi/ClientApp/src/app/shared/role-directive/role-directive.ts b/src/Ombi/ClientApp/src/app/shared/role-directive/role-directive.ts new file mode 100644 index 000000000..3fa4cad56 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/shared/role-directive/role-directive.ts @@ -0,0 +1,36 @@ +import { Directive, Input, OnInit, TemplateRef, ViewContainerRef } from "@angular/core"; +import { AuthService } from "../../auth/auth.service"; + +@Directive({ + selector: '[permission]', +}) +export class RoleDirective implements OnInit { + private roleName: string; + + private isHidden = true; + + @Input() public set permission(val: string) { + if (val) { + this.roleName = val; + this.updateView(); + } + } + + public constructor(private templateRef: TemplateRef, private viewContainer: ViewContainerRef, private auth: AuthService) {} + + public ngOnInit(): void { + this.updateView(); + } + + private updateView(): void { + if (this.auth.hasRole(this.roleName) || this.auth.hasRole("admin")) { + if (this.isHidden) { + this.viewContainer.createEmbeddedView(this.templateRef); + this.isHidden = false; + } + } else { + this.viewContainer.clear(); + this.isHidden = true; + } + } +} diff --git a/src/Ombi/ClientApp/src/app/shared/role-directive/role.module.ts b/src/Ombi/ClientApp/src/app/shared/role-directive/role.module.ts new file mode 100644 index 000000000..15cea8923 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/shared/role-directive/role.module.ts @@ -0,0 +1,8 @@ +import { NgModule } from '@angular/core'; +import { RoleDirective } from './role-directive'; + +@NgModule({ + declarations: [RoleDirective], + exports: [RoleDirective], +}) +export class RoleModule {} diff --git a/src/Ombi/ClientApp/src/app/shared/shared.module.ts b/src/Ombi/ClientApp/src/app/shared/shared.module.ts index 01d70f1c6..87ea0051c 100644 --- a/src/Ombi/ClientApp/src/app/shared/shared.module.ts +++ b/src/Ombi/ClientApp/src/app/shared/shared.module.ts @@ -37,9 +37,9 @@ import { MatTooltipModule } from '@angular/material/tooltip'; import { MatTreeModule } from '@angular/material/tree'; import { MomentModule } from "ngx-moment"; import { NgModule } from "@angular/core"; -import { SidebarModule } from "primeng/sidebar"; import { PipeModule } from "../pipes/pipe.module"; -import { TheMovieDbService } from "../services"; +import { RoleModule } from "./role-directive/role.module"; +import { SidebarModule } from "primeng/sidebar"; import { TranslateModule } from "@ngx-translate/core"; import { TruncateModule } from "@yellowspot/ng-truncate"; import { WatchProvidersSelectComponent } from "./components/watch-providers-select/watch-providers-select.component"; @@ -56,6 +56,7 @@ import { WatchProvidersSelectComponent } from "./components/watch-providers-sele WatchProvidersSelectComponent, ], imports: [ + RoleModule, SidebarModule, ReactiveFormsModule, FormsModule, @@ -91,6 +92,7 @@ import { WatchProvidersSelectComponent } from "./components/watch-providers-sele PipeModule, ], exports: [ + RoleModule, TranslateModule, CommonModule, FormsModule, diff --git a/src/Ombi/ClientApp/src/app/state/customization/customization.state.ts b/src/Ombi/ClientApp/src/app/state/customization/customization.state.ts index 57b3f5908..5261183c3 100644 --- a/src/Ombi/ClientApp/src/app/state/customization/customization.state.ts +++ b/src/Ombi/ClientApp/src/app/state/customization/customization.state.ts @@ -6,7 +6,6 @@ import { ICustomizationSettings } from "../../interfaces"; import { Injectable } from "@angular/core"; import { Observable } from "rxjs"; import { SettingsService } from "../../services"; -import { produce } from 'immer'; import { tap } from "rxjs/operators"; @State({ diff --git a/src/Ombi/ClientApp/src/app/state/features/features-initializer.ts b/src/Ombi/ClientApp/src/app/state/features/features-initializer.ts new file mode 100644 index 000000000..2324259f3 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/state/features/features-initializer.ts @@ -0,0 +1,10 @@ +import { APP_INITIALIZER } from "@angular/core"; +import { FeaturesFacade } from "./features.facade"; +import { Observable } from "rxjs"; + +export const FEATURES_INITIALIZER = { + provide: APP_INITIALIZER, + useFactory: (featureFacade: FeaturesFacade) => (): Observable => featureFacade.loadFeatures(), + multi: true, + deps: [FeaturesFacade], +}; \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/state/features/features.actions.ts b/src/Ombi/ClientApp/src/app/state/features/features.actions.ts new file mode 100644 index 000000000..fcb517828 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/state/features/features.actions.ts @@ -0,0 +1,15 @@ +import { IFeatureEnablement } from "../../interfaces"; + +export class LoadFeatures { + public static readonly type = '[Features] LoadAll'; +} +export class EnableFeature { + public static readonly type = '[Features] Enable'; + + constructor(public feature: IFeatureEnablement) { } +} +export class DisableFeature { + public static readonly type = '[Features] Disable'; + + constructor(public feature: IFeatureEnablement) { } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/state/features/features.facade.ts b/src/Ombi/ClientApp/src/app/state/features/features.facade.ts new file mode 100644 index 000000000..10e229eba --- /dev/null +++ b/src/Ombi/ClientApp/src/app/state/features/features.facade.ts @@ -0,0 +1,26 @@ +import { DisableFeature, EnableFeature, LoadFeatures } from "./features.actions"; + +import { FeaturesSelectors } from "./features.selectors"; +import { IFeatureEnablement } from "../../interfaces"; +import { Injectable } from "@angular/core"; +import { Observable } from "rxjs"; +import { Store } from "@ngxs/store"; + +@Injectable({ + providedIn: 'root', +}) +export class FeaturesFacade { + + public constructor(private store: Store) {} + + public features$ = (): Observable => this.store.select(FeaturesSelectors.features); + + public enable = (feature: IFeatureEnablement): Observable => this.store.dispatch(new EnableFeature(feature)); + + public disable = (feature: IFeatureEnablement): Observable => this.store.dispatch(new DisableFeature(feature)); + + public loadFeatures = (): Observable => this.store.dispatch(new LoadFeatures()); + + public is4kEnabled = (): boolean => this.store.selectSnapshot(FeaturesSelectors.is4kEnabled); + +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/state/features/features.selectors.ts b/src/Ombi/ClientApp/src/app/state/features/features.selectors.ts new file mode 100644 index 000000000..143dfb875 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/state/features/features.selectors.ts @@ -0,0 +1,18 @@ +import { ICustomizationSettings, IFeatureEnablement } from "../../interfaces"; + +import { FEATURES_STATE_TOKEN } from "./types"; +import { Selector } from "@ngxs/store"; + +export class FeaturesSelectors { + + @Selector([FEATURES_STATE_TOKEN]) + public static features(features: IFeatureEnablement[]): IFeatureEnablement[] { + return features; + } + + @Selector([FeaturesSelectors.features]) + public static is4kEnabled(features: IFeatureEnablement[]): boolean { + return features.filter(x => x.name === "Movie4KRequests")[0].enabled; + } + +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/state/features/features.state.ts b/src/Ombi/ClientApp/src/app/state/features/features.state.ts new file mode 100644 index 000000000..4e014db7c --- /dev/null +++ b/src/Ombi/ClientApp/src/app/state/features/features.state.ts @@ -0,0 +1,40 @@ +import { Action, State, StateContext } from "@ngxs/store"; +import { DisableFeature, EnableFeature, LoadFeatures } from "./features.actions"; + +import { FEATURES_STATE_TOKEN } from "./types"; +import { FeatureService } from "../../services/feature.service"; +import { IFeatureEnablement } from "../../interfaces"; +import { Injectable } from "@angular/core"; +import { Observable } from "rxjs"; +import { tap } from "rxjs/operators"; + +@State({ + name: FEATURES_STATE_TOKEN +}) +@Injectable() +export class FeatureState { + constructor(private featuresService: FeatureService) { } + + @Action(LoadFeatures) + public load({ setState }: StateContext): Observable { + return this.featuresService.getFeatures().pipe( + tap(features => + setState(features) + ) + ); + } + + @Action(EnableFeature) + public enable({ setState }: StateContext, { feature }: EnableFeature): Observable { + return this.featuresService.enable(feature).pipe( + tap((result) => setState(result)) + ); + } + + @Action(DisableFeature) + public disable({ setState }: StateContext, { feature }: DisableFeature): Observable { + return this.featuresService.disable(feature).pipe( + tap((result) => setState(result)) + ); + } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/state/features/index.ts b/src/Ombi/ClientApp/src/app/state/features/index.ts new file mode 100644 index 000000000..e0fec5274 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/state/features/index.ts @@ -0,0 +1,4 @@ +export * from './features.state'; +export * from './features.actions'; +export * from './features.facade'; +export * from './features.selectors'; diff --git a/src/Ombi/ClientApp/src/app/state/features/types.ts b/src/Ombi/ClientApp/src/app/state/features/types.ts new file mode 100644 index 000000000..d8fdc09a1 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/state/features/types.ts @@ -0,0 +1,4 @@ +import { IFeatureEnablement } from "../../interfaces"; +import { StateToken } from "@ngxs/store"; + +export const FEATURES_STATE_TOKEN = new StateToken('featureEnablement'); \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/user-preferences/components/user-preference/user-preference.constants.ts b/src/Ombi/ClientApp/src/app/user-preferences/components/user-preference/user-preference.constants.ts index 21416d056..d5101fa52 100644 --- a/src/Ombi/ClientApp/src/app/user-preferences/components/user-preference/user-preference.constants.ts +++ b/src/Ombi/ClientApp/src/app/user-preferences/components/user-preference/user-preference.constants.ts @@ -14,6 +14,8 @@ export const AvailableLanguages: ILanguage[] = [ { display: 'Svenska', value: 'sv' }, { display: 'Български', value: 'bg' }, { display: 'Русский', value: 'ru' }, + { display: 'čeština', value: 'cs' }, + { display: '简体中文', value: 'zh' }, ]; export interface ILanguage { diff --git a/src/Ombi/ClientApp/src/app/usermanagement/usermanagement-user.component.ts b/src/Ombi/ClientApp/src/app/usermanagement/usermanagement-user.component.ts index c772b86aa..bc6319198 100644 --- a/src/Ombi/ClientApp/src/app/usermanagement/usermanagement-user.component.ts +++ b/src/Ombi/ClientApp/src/app/usermanagement/usermanagement-user.component.ts @@ -6,6 +6,7 @@ import { IdentityService, MessageService, RadarrService, SettingsService, Sonarr import { Clipboard } from '@angular/cdk/clipboard'; import { CustomizationFacade } from "../state/customization"; import { Location } from "@angular/common"; +import { FeaturesFacade } from "../state/features/features.facade"; @Component({ templateUrl: "./usermanagement-user.component.html", @@ -36,7 +37,6 @@ export class UserManagementUserComponent implements OnInit { constructor(private identityService: IdentityService, private notificationService: MessageService, - private readonly settingsService: SettingsService, private router: Router, private route: ActivatedRoute, private sonarrService: SonarrService, @@ -44,23 +44,33 @@ export class UserManagementUserComponent implements OnInit { private clipboard: Clipboard, private location: Location, private customizationFacade: CustomizationFacade, + private featureFacade: FeaturesFacade, ) { this.route.params.subscribe((params: any) => { if(params.id) { this.userId = params.id; this.edit = true; - this.identityService.getUserById(this.userId).subscribe(x => { - this.user = x; - }); } }); } public ngOnInit() { + const is4KEnabled = this.featureFacade.is4kEnabled(); + this.identityService.getUserById(this.userId).subscribe(x => { + this.user = x; + if (!is4KEnabled) { + this.user.claims = this.user.claims.filter(x => x.value !== "Request4KMovie"); + } + }); this.requestLimitTypes = [RequestLimitType.Day, RequestLimitType.Week, RequestLimitType.Month]; this.identityService.getSupportedStreamingCountries().subscribe(x => this.countries = x); - this.identityService.getAllAvailableClaims().subscribe(x => this.availableClaims = x); + this.identityService.getAllAvailableClaims().subscribe(x => { + this.availableClaims = x; + if (!is4KEnabled) { + this.availableClaims = this.availableClaims.filter(y => y.value !== "Request4KMovie"); + } + }); if(this.edit) { this.identityService.getNotificationPreferencesForUser(this.userId).subscribe(x => this.notificationPreferences = x); } else { diff --git a/src/Ombi/ClientApp/src/app/wizard/createadmin/createadmin.component.html b/src/Ombi/ClientApp/src/app/wizard/createadmin/createadmin.component.html index ff44f7093..5d79f5ebd 100644 --- a/src/Ombi/ClientApp/src/app/wizard/createadmin/createadmin.component.html +++ b/src/Ombi/ClientApp/src/app/wizard/createadmin/createadmin.component.html @@ -1,6 +1,6 @@ 
- +
diff --git a/src/Ombi/ClientApp/src/app/wizard/ombiconfig/ombiconfig.component.html b/src/Ombi/ClientApp/src/app/wizard/ombiconfig/ombiconfig.component.html index 33d15bb58..a8d7d212e 100644 --- a/src/Ombi/ClientApp/src/app/wizard/ombiconfig/ombiconfig.component.html +++ b/src/Ombi/ClientApp/src/app/wizard/ombiconfig/ombiconfig.component.html @@ -1,6 +1,6 @@ 
- +
diff --git a/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.html b/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.html index 7ca3de4ce..f32e59b8d 100644 --- a/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.html +++ b/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.html @@ -67,7 +67,7 @@ Done
- +
diff --git a/src/Ombi/ClientApp/src/typings/globals.d.ts b/src/Ombi/ClientApp/src/typings/globals.d.ts index a52f87871..e30f97cb1 100644 --- a/src/Ombi/ClientApp/src/typings/globals.d.ts +++ b/src/Ombi/ClientApp/src/typings/globals.d.ts @@ -3,4 +3,5 @@ declare var __webpack_public_path__: any; // declare module "*.json" { // const value: any; // export default value; -// } \ No newline at end of file +// } + diff --git a/src/Ombi/ClientApp/yarn.lock b/src/Ombi/ClientApp/yarn.lock index 5cff8378d..0d40276b0 100644 --- a/src/Ombi/ClientApp/yarn.lock +++ b/src/Ombi/ClientApp/yarn.lock @@ -2,286 +2,277 @@ # yarn lockfile v1 -"@ampproject/remapping@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-1.0.1.tgz#1398e73e567c2a7992df6554c15bb94a89b68ba2" - integrity sha512-Ta9bMA3EtUHDaZJXqUoT5cn/EecwOp+SXpKJqxDbDuMbLvEMu6YTyDDuvTWeStODfdmXyfMo7LymQyPkN3BicA== +"@ampproject/remapping@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-1.1.1.tgz#e220d0a5288b07afd6392a584d15921839e9da32" + integrity sha512-YVAcA4DKLOj296CF5SrQ8cYiMRiUGc2sqFpLxsDGWE34suHqhGP/5yMsDHKsrh8hs8I5TiRVXNwKPWQpX3iGjw== dependencies: - "@jridgewell/resolve-uri" "1.0.0" + "@jridgewell/resolve-uri" "^3.0.3" sourcemap-codec "1.4.8" -"@angular-devkit/architect@0.1202.10": - version "0.1202.10" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1202.10.tgz#6aae8e97ea209949507443cd9c414be94d258813" - integrity sha512-/sLgtXaFsNouxub5M/bQ2sBkiMIlPubuz6QMh+pA2jia82vJ3hcRMt4AnJTXuXpVY+aew4FiG0i9nt/8HETQsw== +"@ampproject/remapping@^2.1.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" + integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== dependencies: - "@angular-devkit/core" "12.2.10" + "@jridgewell/trace-mapping" "^0.3.0" + +"@angular-devkit/architect@0.1302.3": + version "0.1302.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1302.3.tgz#0e71cc2d737be6828d4072f53872aa2b17940870" + integrity sha512-0m8jMKrFfIqsYt33zTUwSmyekyfuS67hna08RQ6USjzWQSE3z4S8ulCUARSjM6AzdMblX+whfy56nJUpT17NSA== + dependencies: + "@angular-devkit/core" "13.2.3" rxjs "6.6.7" -"@angular-devkit/build-angular@~12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-12.2.10.tgz#aef9d1ab44e9f83dd8cd5625d7d10eaf81dd0e74" - integrity sha512-MuViuSmXmB67Wge3NpyfY2aAU4O4K+BbcHj1W1k1A9WTx/Hyh6jR6Zgwy/EsNh64zjdUg/Jlg/oHxIVabsWfvQ== +"@angular-devkit/build-angular@~13.2.0": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-13.2.3.tgz#03d9bb0f3a620a9125c2794e801c7071a9fea7e7" + integrity sha512-cZ2gRcMRgW3t1WCeP+2D/wmr2M+BR/RICAh0wL9irIdypWAzIFt3Z2+2R/HmgAAxoEkdUMIfB9AnkYmwRVgFeA== dependencies: - "@ampproject/remapping" "1.0.1" - "@angular-devkit/architect" "0.1202.10" - "@angular-devkit/build-optimizer" "0.1202.10" - "@angular-devkit/build-webpack" "0.1202.10" - "@angular-devkit/core" "12.2.10" - "@babel/core" "7.14.8" - "@babel/generator" "7.14.8" - "@babel/helper-annotate-as-pure" "7.14.5" - "@babel/plugin-proposal-async-generator-functions" "7.14.7" - "@babel/plugin-transform-async-to-generator" "7.14.5" - "@babel/plugin-transform-runtime" "7.14.5" - "@babel/preset-env" "7.14.8" - "@babel/runtime" "7.14.8" - "@babel/template" "7.14.5" - "@discoveryjs/json-ext" "0.5.3" - "@jsdevtools/coverage-istanbul-loader" "3.0.5" - "@ngtools/webpack" "12.2.10" + "@ampproject/remapping" "1.1.1" + "@angular-devkit/architect" "0.1302.3" + "@angular-devkit/build-webpack" "0.1302.3" + "@angular-devkit/core" "13.2.3" + "@babel/core" "7.16.12" + "@babel/generator" "7.16.8" + "@babel/helper-annotate-as-pure" "7.16.7" + "@babel/plugin-proposal-async-generator-functions" "7.16.8" + "@babel/plugin-transform-async-to-generator" "7.16.8" + "@babel/plugin-transform-runtime" "7.16.10" + "@babel/preset-env" "7.16.11" + "@babel/runtime" "7.16.7" + "@babel/template" "7.16.7" + "@discoveryjs/json-ext" "0.5.6" + "@ngtools/webpack" "13.2.3" ansi-colors "4.1.1" - babel-loader "8.2.2" + babel-loader "8.2.3" + babel-plugin-istanbul "6.1.1" browserslist "^4.9.1" - cacache "15.2.0" - caniuse-lite "^1.0.30001032" + cacache "15.3.0" circular-dependency-plugin "5.2.2" - copy-webpack-plugin "9.0.1" - core-js "3.16.0" - critters "0.0.10" - css-loader "6.2.0" - css-minimizer-webpack-plugin "3.0.2" - esbuild-wasm "0.13.4" - find-cache-dir "3.3.1" - glob "7.1.7" + copy-webpack-plugin "10.2.1" + core-js "3.20.3" + critters "0.0.16" + css-loader "6.5.1" + esbuild-wasm "0.14.14" + glob "7.2.0" https-proxy-agent "5.0.0" - inquirer "8.1.2" + inquirer "8.2.0" + jsonc-parser "3.0.0" karma-source-map-support "1.4.0" - less "4.1.1" - less-loader "10.0.1" - license-webpack-plugin "2.3.20" - loader-utils "2.0.0" - mini-css-extract-plugin "2.2.1" + less "4.1.2" + less-loader "10.2.0" + license-webpack-plugin "4.0.1" + loader-utils "3.2.0" + mini-css-extract-plugin "2.5.3" minimatch "3.0.4" - open "8.2.1" + open "8.4.0" ora "5.4.1" parse5-html-rewriting-stream "6.0.1" - piscina "3.1.0" - postcss "8.3.6" + piscina "3.2.0" + postcss "8.4.5" postcss-import "14.0.2" - postcss-loader "6.1.1" - postcss-preset-env "6.7.0" + postcss-loader "6.2.1" + postcss-preset-env "7.2.3" regenerator-runtime "0.13.9" - resolve-url-loader "4.0.0" + resolve-url-loader "5.0.0" rxjs "6.6.7" - sass "1.36.0" - sass-loader "12.1.0" + sass "1.49.0" + sass-loader "12.4.0" semver "7.3.5" - source-map-loader "3.0.0" - source-map-support "0.5.19" - style-loader "3.2.1" - stylus "0.54.8" - stylus-loader "6.1.0" - terser "5.7.1" - terser-webpack-plugin "5.1.4" + source-map-loader "3.0.1" + source-map-support "0.5.21" + stylus "0.56.0" + stylus-loader "6.2.0" + terser "5.10.0" text-table "0.2.0" tree-kill "1.2.2" - tslib "2.3.0" - webpack "5.50.0" - webpack-dev-middleware "5.0.0" - webpack-dev-server "3.11.2" + tslib "2.3.1" + webpack "5.67.0" + webpack-dev-middleware "5.3.0" + webpack-dev-server "4.7.3" webpack-merge "5.8.0" - webpack-subresource-integrity "1.5.2" + webpack-subresource-integrity "5.1.0" optionalDependencies: - esbuild "0.13.4" + esbuild "0.14.14" -"@angular-devkit/build-optimizer@0.1202.10": - version "0.1202.10" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.1202.10.tgz#f72c76e873e10139e95633d0ac3c4c8112d3f40b" - integrity sha512-NcFEtj4Vfc7gXJtXEVf1mnpk0CJ0htlkm/LbidPcs1PEQbJ/yDgZ44fO+53Pt6NzLmsmPHXOmRzN7O6HkxolPA== +"@angular-devkit/build-webpack@0.1302.3": + version "0.1302.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1302.3.tgz#a1b43f0d61048e91d25f43e2ec14c1545b070655" + integrity sha512-+JYH1lWU0UOjaWYxpoR2VLsdcb6nG9Gv+M1gH+kT0r2sAKOFaHnrksbOvca3EhDoaMa2b9LSGEE0OcSHWnN+eQ== dependencies: - source-map "0.7.3" - tslib "2.3.0" - typescript "4.3.5" - -"@angular-devkit/build-webpack@0.1202.10": - version "0.1202.10" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1202.10.tgz#ad92b8865623092951b4fddf6f603661f7910865" - integrity sha512-xGSy12g+wa/qeYOaPGkeoJp3zatlS+HZxECtw0Up3ES85Ewrx9PvraexHSuRxnkuBQykRORKf6WbPt/WYIAVGQ== - dependencies: - "@angular-devkit/architect" "0.1202.10" + "@angular-devkit/architect" "0.1302.3" rxjs "6.6.7" -"@angular-devkit/core@12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-12.2.10.tgz#3da62eceef3904f92cd3f860618b4ae513029ce2" - integrity sha512-0qhmS7Qvl0hiRVTHxEC/ipFAfzYofPstw0ZITDpEMw+pgHlOZolOlnFrv8LyOXWNqlSIH5fS9D3WF7Hpm7ApYA== +"@angular-devkit/core@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-13.2.3.tgz#a5770c7a5e50d1b09e5a41ccb7cf0af140a9e168" + integrity sha512-/47RA8qmWzeS60xSdaprIn1MiSv0Iw83t0M9/ENH7irFS5vMAq62NCcwiWXH59pZmvvLbF+7xy/RgYUZLr4nHQ== dependencies: - ajv "8.6.2" - ajv-formats "2.1.0" + ajv "8.9.0" + ajv-formats "2.1.1" fast-json-stable-stringify "2.1.0" magic-string "0.25.7" rxjs "6.6.7" source-map "0.7.3" -"@angular-devkit/schematics@12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-12.2.10.tgz#b8d4031053fd76d93caa7f33aeeb67383e37f0ab" - integrity sha512-oQ2EWdkEDE+eAttHeviXsvBi85PsntQT+IffjKUZdbQU+Leuk/pKUpTeea1YosU1p4Cz3PKYF+P/Nl5Jy3B7IQ== +"@angular-devkit/schematics@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-13.2.3.tgz#c2acb68ba798f4ab115bee73f078d98f5b20d21c" + integrity sha512-+dyC4iKV0huvpjiuz4uyjLNK3FsCIp/Ghv5lXvhG6yok/dCAubsJItJOxi6G16aVCzG/E9zbsDfm9fNMyVOkgQ== dependencies: - "@angular-devkit/core" "12.2.10" + "@angular-devkit/core" "13.2.3" + jsonc-parser "3.0.0" + magic-string "0.25.7" ora "5.4.1" rxjs "6.6.7" -"@angular/animations@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-12.2.10.tgz#c6610fc7b2021451c46dcfe27bd4fcc8e3789e08" - integrity sha512-K1WT3m/StW5a4SE9wKT+D7eteyWK+MW3pAwFPaKH8EU9k6dItlLr3jWZsve5w2u/GLSnrOMGJNU/JmTfskV9LA== +"@angular/animations@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-13.2.2.tgz#b6af6962a721d73a3832d6f4891dc644bee50ed7" + integrity sha512-qX8LAMuCJaueHBVyuwKtqunx96G0Dr26k7y5Z03VTcscYst4Ib4V2d4i5dwn3HS82DehFdO86cm3Hi2PqE/qww== dependencies: - tslib "^2.2.0" + tslib "^2.3.0" -"@angular/cdk@^12.2.9": - version "12.2.9" - resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-12.2.9.tgz#f39e4d7cdb3568ad8e1d412e3500772e2d4c605c" - integrity sha512-9Wgj69iGAZ4teQqW/zPbVg2RGna+m9i3v0zkWGx/+Uo95rikJCUZBQM4bfeOe+bSJrS77jV5EisBWG7ayNUSzQ== +"@angular/cdk@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-13.2.2.tgz#4d41b1da6e92e3bc80d28aabe2049fa7ca40f5b1" + integrity sha512-cT5DIaz+NI9IGb3X61Wh26+L6zdRcOXT1BP37iRbK2Qa2qM8/0VNeK6hrBBIblyoHKR/WUmRlS8XYf6mmArpZw== dependencies: - tslib "^2.2.0" + tslib "^2.3.0" optionalDependencies: parse5 "^5.0.0" -"@angular/cli@~12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-12.2.10.tgz#73062d433434b7b25073863940d82e4e6f7fa924" - integrity sha512-gx2XlOUjAAYyJBBIz4QkgsLLRMdFTQbcOR41/Yv0kgpR6AStrOWhz7tpYPbU6vWMjehpuTaWv4NE5eGjwVTZqg== +"@angular/cli@~13.2.0": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-13.2.3.tgz#4a1694025bf0ac589aeaec17a6ba560647cf07b0" + integrity sha512-QsakxpdQuO67u4fQNuOASqabYUO9gJb/5CpUGpWbuBzru0/9CMEF1CtXoF4EoDiwa5sJMirz3SJMKhtzFlv1cQ== dependencies: - "@angular-devkit/architect" "0.1202.10" - "@angular-devkit/core" "12.2.10" - "@angular-devkit/schematics" "12.2.10" - "@schematics/angular" "12.2.10" + "@angular-devkit/architect" "0.1302.3" + "@angular-devkit/core" "13.2.3" + "@angular-devkit/schematics" "13.2.3" + "@schematics/angular" "13.2.3" "@yarnpkg/lockfile" "1.1.0" ansi-colors "4.1.1" - debug "4.3.2" + debug "4.3.3" ini "2.0.0" - inquirer "8.1.2" + inquirer "8.2.0" jsonc-parser "3.0.0" npm-package-arg "8.1.5" npm-pick-manifest "6.1.1" - open "8.2.1" + open "8.4.0" ora "5.4.1" - pacote "11.3.5" - resolve "1.20.0" + pacote "12.0.3" + resolve "1.22.0" semver "7.3.5" symbol-observable "4.0.0" uuid "8.3.2" -"@angular/common@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/common/-/common-12.2.10.tgz#1298fc0d7becfdf5368676ceb01a7df97331d412" - integrity sha512-7IjD0frrKG/nt3/fo4mKDH0Tx5Nn8f2G8Ks/aq6xnJssy/V841COjua0ZyfPOkPS1r0VEaQJB5ieqMrp2T6MWg== +"@angular/common@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/common/-/common-13.2.2.tgz#3c787a53acf69633902e804c141c39a3455d85d3" + integrity sha512-56C/bheNLKtTCyQUZCiYtKbBIZN9jj6rjFILPtJCGls3cBCxp7t9tIdoLiQG/wVQRmaxdj1ioLT+sCWz7mLtQw== dependencies: - tslib "^2.2.0" + tslib "^2.3.0" -"@angular/compiler-cli@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-12.2.10.tgz#c6b19af123d5772a8a53ac7872401fdc726f7b57" - integrity sha512-cPWxNMwPTM7IsEBxMrh4yY9XZi4gZRv7EmKWOfBw6hiW0SEmthIQWOvCaoL5CPsdUhInNxXWvwAoFggk/tfJ5g== +"@angular/compiler-cli@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-13.2.2.tgz#f2c4c207fdbcc274c7a153b3506c3b8f99fc6f59" + integrity sha512-tuOIcEEKVIht+mKrj0rtX3I8gc+ByPjzpCZhFQRggxM6xbKJIToO1zERbEGKrZ+sUJ6BB5KLvscDy+Pddy3b8w== dependencies: "@babel/core" "^7.8.6" - "@babel/types" "^7.8.6" - canonical-path "1.0.0" chokidar "^3.0.0" convert-source-map "^1.5.1" dependency-graph "^0.11.0" magic-string "^0.25.0" - minimist "^1.2.0" reflect-metadata "^0.1.2" semver "^7.0.0" - source-map "^0.6.1" sourcemap-codec "^1.4.8" - tslib "^2.2.0" - yargs "^17.0.0" + tslib "^2.3.0" + yargs "^17.2.1" "@angular/compiler@9.0.0": version "9.0.0" resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-9.0.0.tgz#87e0bef4c369b6cadae07e3a4295778fc93799d5" integrity sha512-ctjwuntPfZZT2mNj2NDIVu51t9cvbhl/16epc5xEwyzyDt76pX9UgwvY+MbXrf/C/FWwdtmNtfP698BKI+9leQ== -"@angular/compiler@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-12.2.10.tgz#7da81b341f90e779d29f7f96c82c93e57f84c02e" - integrity sha512-5fuzX8P74z28CRYTamsZgsdUyh0c53shytZYfa0cGFXyV8VD/r8AMIyQ4y7Y5Fmt4Nr+65EVeYb3sI7IzYiueg== +"@angular/compiler@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-13.2.2.tgz#89999576906f4d65b58ecff38666c71809ddee45" + integrity sha512-XXQtB0/e7pR2LPrHmpEiTU72SX4xxHGy91vYWIj1JCjSn0fYF7vtHzSJPXDvkbnkNow/PXXzJJYaU1ctdMZPcA== dependencies: - tslib "^2.2.0" + tslib "^2.3.0" "@angular/core@9.0.0": version "9.0.0" resolved "https://registry.yarnpkg.com/@angular/core/-/core-9.0.0.tgz#227dc53e1ac81824f998c6e76000b7efc522641e" integrity sha512-6Pxgsrf0qF9iFFqmIcWmjJGkkCaCm6V5QNnxMy2KloO3SDq6QuMVRbN9RtC8Urmo25LP+eZ6ZgYqFYpdD8Hd9w== -"@angular/core@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/core/-/core-12.2.10.tgz#899f5b6e44c33790640d04df2a6981b622a9e6d7" - integrity sha512-xG1IbmEAV7gWpiY2MSFc87MlmB3yff8/TAlSE8Tj2ZFzb1lFjeFnrZ1y50Hi2AcVyX/KA1mx/RyJ0M7fmQ1ayw== +"@angular/core@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/core/-/core-13.2.2.tgz#30d2cd6ed3d74d90071c135def7163b12137eb7f" + integrity sha512-zpctw0BxIVOsRFnckchK15SD1L8tzhf5GzwIDaM6+VylDQj1uYkm8mvAjJTQZyUuApomoFet2Rfj7XQPV+cNSQ== dependencies: - tslib "^2.2.0" + tslib "^2.3.0" -"@angular/forms@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-12.2.10.tgz#c1a2f6f07354d56d78dc1dfc1f9ff92750ea4daa" - integrity sha512-ntTJOaLeH+7th5W4LEm3/yHsBvaFpfRgn0Uc88Th8p2gvorqCgpJMWogJIx/yESNolSFItY6k/x7kjuMBgm9mA== +"@angular/forms@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-13.2.2.tgz#cdc4f249a85160eab003104d7050f8797a2038a7" + integrity sha512-T61W4Ay9X9qhxjc6lLqpNFeHrGKwg2mqdsZ3zIm/c7oKo37mgl9TB5kkrtnS+205r3N2hF4ICnGFZ4a/egUP/g== dependencies: - tslib "^2.2.0" + tslib "^2.3.0" -"@angular/language-service@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-12.2.10.tgz#051d92813185535c7b1c496f4306f10a729b335e" - integrity sha512-o9KY39+1bw9xB6vsMWAbcPFWNdTQ/6TSKyQkmAyYca7T6LlNOe/qWln2655ZFPhyG6d9R8nbTi3X0MhMP+H7xQ== +"@angular/language-service@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-13.2.2.tgz#4de8742dc7603a331cb39be065f5a30d0bdc0fad" + integrity sha512-2P5+wRsbHgpI2rVeFwnsLWxyntUiw8kG9Tqh5BkVDqtQovbYtzFiaMkf5TFz/g938JBBgeRQzvXr1kQhEidAWQ== -"@angular/localize@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/localize/-/localize-12.2.10.tgz#25bab8bc6e8b247e83a7146df4dbf39b73d0ecfe" - integrity sha512-YTvDYvhjo+qakuLdyWTpgz7Hd4nzmCLdzk/P2a46SiYWG4i/ShBmfkhJNAgZfVnnM6oSt15z/VCgB31lS7JrYg== +"@angular/localize@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/localize/-/localize-13.2.2.tgz#a19ee864e362baf1d538d56b9021e7d71d7293c9" + integrity sha512-W/deDIxAFlv0euq7hxYPRCvj2DtDTsid5mRqyjEaVr+eYaLPnD8EElZuKuQEDeo7rWkCjljEpBrFsXwC5FZ8cw== dependencies: - "@babel/core" "7.8.3" - glob "7.1.7" - yargs "^17.0.0" + "@babel/core" "7.8.6" + glob "7.2.0" + yargs "^17.2.1" -"@angular/material@^12.2.9": - version "12.2.9" - resolved "https://registry.yarnpkg.com/@angular/material/-/material-12.2.9.tgz#b4a1e138c7fd2341bd27aa6012b4738f61b5ad2d" - integrity sha512-+eM67RF038S56m3wsj37h0PyyRD18cQ8V2zmKG1UezH0nnosbmCAwzH9BfcNiIB+/V+k5QMJ/JVu5MjDQqX37w== +"@angular/material@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/material/-/material-13.2.2.tgz#d673f68b0c9357ada2ee82ffeaf11f10f5d49b27" + integrity sha512-YAjPp2+/wuEOPfkAxdRVdbWHiK4P3DgMZa9qP/NizN2lTXNrftEfD09ZlPIFMZRnnExezJ2LnO7eyELpc1VSKg== dependencies: - tslib "^2.2.0" + tslib "^2.3.0" -"@angular/platform-browser-dynamic@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-12.2.10.tgz#c30ef29587a09fbcfd0d9921b64ce264e6650893" - integrity sha512-CLYHCdTCzpxvMwITRBLlUoa44orDdogMaQfKIMEQsWrynf+zGZKYe5chAut9P/A54PVPUtKeQrfEVFjmbdYR2w== +"@angular/platform-browser-dynamic@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-13.2.2.tgz#9a50fb79b96b62c13e65c996727542c5174e9246" + integrity sha512-lj6xwat0StLp+ROFqXU62upwHQhlxaQi0djhrS+DGKUK0Xu9bkBeaSCfBFgS78jPm1SwL8Xztu9/vuDAHLRrqw== dependencies: - tslib "^2.2.0" + tslib "^2.3.0" -"@angular/platform-browser@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-12.2.10.tgz#402132b528f6dc0235c5571cdf0f29ef1a79277a" - integrity sha512-2pYoscOJijbqFsnYpKX6o4ojt4XfZiNhODTf9RDOPVKjVqFsRNVThg76kdKtN+N8q6N1z4I01x6aX4EeWqQqIA== +"@angular/platform-browser@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-13.2.2.tgz#e603c32c3550970211b004df3e227e0d2b5088cd" + integrity sha512-M7gWC8fFCPc/CRcHCzqe/j7WzwAUMeKt9vwlK633XnesHBoqZdYgbb3YHHc6WPVU0YI09Nb/Hm5sezEKmjUmPg== dependencies: - tslib "^2.2.0" + tslib "^2.3.0" -"@angular/platform-server@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-12.2.10.tgz#8e11dea472db244c2fa71ec0d08911d52151b3b5" - integrity sha512-g2m2/+e+6mxbvMYICe+1zDP/KGMwmf9gu/fz+I9UFpGuAx4S7eBL/GCII2gnrrbavZ2vxczY0Ff4JU7AEBrGug== +"@angular/platform-server@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-13.2.2.tgz#706c9cef4cec156f3e9874963f868530e67e6d3d" + integrity sha512-v17/E9hWY5/MgUjk+E+aNUNZ/wmhHb08RyeKvvUKhx8Xb24hRiMdjA9yMkt1UsjOGJUIeZ8s5nn6xRiRc3t+9A== dependencies: domino "^2.1.2" - tslib "^2.2.0" + tslib "^2.3.0" xhr2 "^0.2.0" -"@angular/router@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/router/-/router-12.2.10.tgz#53d64ce59a65cde096e4a0125b117b6040d08fa8" - integrity sha512-e9sqOdLNF3pVRZPZtD6OdvERdTWKP7Et8Mz4OSNT8GEe6SctRAaptTAqY09AGpi4BO2+LsxVBERYfhZw9bZ2bA== +"@angular/router@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/router/-/router-13.2.2.tgz#ba637da8963e5905520622f02357c4eda2f3da68" + integrity sha512-dt2b9/kGJAkmOqUmUD3aKlp4pGpdqLwB0zmhUYF3ktNEcQaPf4ZjWT/4jhy09gFL+TKOHG5OQW9GxBbhWI4bSg== dependencies: - tslib "^2.2.0" + tslib "^2.3.0" "@angularclass/hmr@^3.0.0": version "3.0.0" @@ -316,25 +307,37 @@ dependencies: "@babel/highlight" "^7.14.5" -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.14.7", "@babel/compat-data@^7.15.0": +"@babel/code-frame@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" + integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== + dependencies: + "@babel/highlight" "^7.16.7" + +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.15.0": version "7.15.0" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176" integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA== -"@babel/core@7.14.8": - version "7.14.8" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.14.8.tgz#20cdf7c84b5d86d83fac8710a8bc605a7ba3f010" - integrity sha512-/AtaeEhT6ErpDhInbXmjHcUQXH0L0TEgscfcxk1qbOvLuKCa5aZT0SOOtDKFY96/CLROwbLSKyFor6idgNaU4Q== +"@babel/compat-data@^7.16.4", "@babel/compat-data@^7.16.8", "@babel/compat-data@^7.17.0": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.0.tgz#86850b8597ea6962089770952075dcaabb8dba34" + integrity sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng== + +"@babel/core@7.16.12": + version "7.16.12" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.12.tgz#5edc53c1b71e54881315923ae2aedea2522bb784" + integrity sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg== dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/generator" "^7.14.8" - "@babel/helper-compilation-targets" "^7.14.5" - "@babel/helper-module-transforms" "^7.14.8" - "@babel/helpers" "^7.14.8" - "@babel/parser" "^7.14.8" - "@babel/template" "^7.14.5" - "@babel/traverse" "^7.14.8" - "@babel/types" "^7.14.8" + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.16.8" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helpers" "^7.16.7" + "@babel/parser" "^7.16.12" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.10" + "@babel/types" "^7.16.8" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -342,18 +345,18 @@ semver "^6.3.0" source-map "^0.5.0" -"@babel/core@7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.3.tgz#30b0ebb4dd1585de6923a0b4d179e0b9f5d82941" - integrity sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA== +"@babel/core@7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.6.tgz#27d7df9258a45c2e686b6f18b6c659e563aa4636" + integrity sha512-Sheg7yEJD51YHAvLEV/7Uvw95AeWqYPL3Vk3zGujJKIhJ+8oLw2ALaf3hbucILhKsgSoADOvtKRJuNVdcJkOrg== dependencies: "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.8.3" - "@babel/helpers" "^7.8.3" - "@babel/parser" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" + "@babel/generator" "^7.8.6" + "@babel/helpers" "^7.8.4" + "@babel/parser" "^7.8.6" + "@babel/template" "^7.8.6" + "@babel/traverse" "^7.8.6" + "@babel/types" "^7.8.6" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" @@ -363,7 +366,28 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.7.5", "@babel/core@^7.8.6": +"@babel/core@^7.12.3": + version "7.17.4" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.4.tgz#a22f1ae8999122873b3d18865e98c7a3936b8c8b" + integrity sha512-R9x5r4t4+hBqZTmioSnkrW+I6NmbojwjGT8p4G2Gw1thWbXIHGDnmGdLdFw0/7ljucdIrNRp7Npgb4CyBYzzJg== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.17.3" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helpers" "^7.17.2" + "@babel/parser" "^7.17.3" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.3" + "@babel/types" "^7.17.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + +"@babel/core@^7.8.6": version "7.15.8" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.8.tgz#195b9f2bffe995d2c6c159e72fe525b4114e8c10" integrity sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og== @@ -384,16 +408,16 @@ semver "^6.3.0" source-map "^0.5.0" -"@babel/generator@7.14.8": - version "7.14.8" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.14.8.tgz#bf86fd6af96cf3b74395a8ca409515f89423e070" - integrity sha512-cYDUpvIzhBVnMzRoY1fkSEhK/HmwEVwlyULYgn/tMQYd6Obag3ylCjONle3gdErfXBW61SVTlR9QR7uWlgeIkg== +"@babel/generator@7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.8.tgz#359d44d966b8cd059d543250ce79596f792f2ebe" + integrity sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw== dependencies: - "@babel/types" "^7.14.8" + "@babel/types" "^7.16.8" jsesc "^2.5.1" source-map "^0.5.0" -"@babel/generator@^7.14.8", "@babel/generator@^7.15.4", "@babel/generator@^7.15.8", "@babel/generator@^7.8.3": +"@babel/generator@^7.15.4", "@babel/generator@^7.15.8": version "7.15.8" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.8.tgz#fa56be6b596952ceb231048cf84ee499a19c0cd1" integrity sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g== @@ -402,29 +426,38 @@ jsesc "^2.5.1" source-map "^0.5.0" -"@babel/helper-annotate-as-pure@7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz#7bf478ec3b71726d56a8ca5775b046fc29879e61" - integrity sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA== +"@babel/generator@^7.16.8", "@babel/generator@^7.17.3", "@babel/generator@^7.8.6": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.3.tgz#a2c30b0c4f89858cb87050c3ffdfd36bdf443200" + integrity sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg== dependencies: - "@babel/types" "^7.14.5" + "@babel/types" "^7.17.0" + jsesc "^2.5.1" + source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.14.5", "@babel/helper-annotate-as-pure@^7.15.4": +"@babel/helper-annotate-as-pure@7.16.7", "@babel/helper-annotate-as-pure@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862" + integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-annotate-as-pure@^7.14.5": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.15.4.tgz#3d0e43b00c5e49fdb6c57e421601a7a658d5f835" integrity sha512-QwrtdNvUNsPCj2lfNQacsGSQvGX8ee1ttrBrcozUP2Sv/jylewBP/8QFe6ZkBsC8T/GYWonNAWJV4aRR9AL2DA== dependencies: "@babel/types" "^7.15.4" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.14.5": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.15.4.tgz#21ad815f609b84ee0e3058676c33cf6d1670525f" - integrity sha512-P8o7JP2Mzi0SdC6eWr1zF+AEYvrsZa7GSY1lTayjF5XJhVH0kjLYUZPvTMflP7tBgZoe9gIhTa60QwFpqh/E0Q== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz#38d138561ea207f0f69eb1626a418e4f7e6a580b" + integrity sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA== dependencies: - "@babel/helper-explode-assignable-expression" "^7.15.4" - "@babel/types" "^7.15.4" + "@babel/helper-explode-assignable-expression" "^7.16.7" + "@babel/types" "^7.16.7" -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.14.5", "@babel/helper-compilation-targets@^7.15.4": +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz#cf6d94f30fbefc139123e27dd6b02f65aeedb7b9" integrity sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ== @@ -434,17 +467,28 @@ browserslist "^4.16.6" semver "^6.3.0" -"@babel/helper-create-class-features-plugin@^7.14.5", "@babel/helper-create-class-features-plugin@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.4.tgz#7f977c17bd12a5fba363cb19bea090394bf37d2e" - integrity sha512-7ZmzFi+DwJx6A7mHRwbuucEYpyBwmh2Ca0RvI6z2+WLZYCqV0JOaLb+u0zbtmDicebgKBZgqbYfLaKNqSgv5Pw== +"@babel/helper-compilation-targets@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b" + integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA== dependencies: - "@babel/helper-annotate-as-pure" "^7.15.4" - "@babel/helper-function-name" "^7.15.4" - "@babel/helper-member-expression-to-functions" "^7.15.4" - "@babel/helper-optimise-call-expression" "^7.15.4" - "@babel/helper-replace-supers" "^7.15.4" - "@babel/helper-split-export-declaration" "^7.15.4" + "@babel/compat-data" "^7.16.4" + "@babel/helper-validator-option" "^7.16.7" + browserslist "^4.17.5" + semver "^6.3.0" + +"@babel/helper-create-class-features-plugin@^7.16.10", "@babel/helper-create-class-features-plugin@^7.16.7": + version "7.17.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.1.tgz#9699f14a88833a7e055ce57dcd3ffdcd25186b21" + integrity sha512-JBdSr/LtyYIno/pNnJ75lBcqc3Z1XXujzPanHqjvvrhOA+DTceTFuJi8XjmWTZh4r3fsdfqaCMN0iZemdkxZHQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" "@babel/helper-create-regexp-features-plugin@^7.14.5": version "7.14.5" @@ -454,10 +498,18 @@ "@babel/helper-annotate-as-pure" "^7.14.5" regexpu-core "^4.7.1" -"@babel/helper-define-polyfill-provider@^0.2.2": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz#0525edec5094653a282688d34d846e4c75e9c0b6" - integrity sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew== +"@babel/helper-create-regexp-features-plugin@^7.16.7": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz#1dcc7d40ba0c6b6b25618997c5dbfd310f186fe1" + integrity sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + regexpu-core "^5.0.1" + +"@babel/helper-define-polyfill-provider@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz#52411b445bdb2e676869e5a74960d2d3826d2665" + integrity sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA== dependencies: "@babel/helper-compilation-targets" "^7.13.0" "@babel/helper-module-imports" "^7.12.13" @@ -468,14 +520,21 @@ resolve "^1.14.2" semver "^6.1.2" -"@babel/helper-explode-assignable-expression@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.15.4.tgz#f9aec9d219f271eaf92b9f561598ca6b2682600c" - integrity sha512-J14f/vq8+hdC2KoWLIQSsGrC9EFBKE4NFts8pfMpymfApds+fPqR30AOUWc4tyr56h9l/GA1Sxv2q3dLZWbQ/g== +"@babel/helper-environment-visitor@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" + integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== dependencies: - "@babel/types" "^7.15.4" + "@babel/types" "^7.16.7" -"@babel/helper-function-name@^7.14.5", "@babel/helper-function-name@^7.15.4": +"@babel/helper-explode-assignable-expression@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz#12a6d8522fdd834f194e868af6354e8650242b7a" + integrity sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-function-name@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz#845744dafc4381a4a5fb6afa6c3d36f98a787ebc" integrity sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw== @@ -484,6 +543,15 @@ "@babel/template" "^7.15.4" "@babel/types" "^7.15.4" +"@babel/helper-function-name@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" + integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== + dependencies: + "@babel/helper-get-function-arity" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/types" "^7.16.7" + "@babel/helper-get-function-arity@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz#098818934a137fce78b536a3e015864be1e2879b" @@ -491,6 +559,13 @@ dependencies: "@babel/types" "^7.15.4" +"@babel/helper-get-function-arity@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419" + integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-hoist-variables@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz#09993a3259c0e918f99d104261dfdfc033f178df" @@ -498,6 +573,13 @@ dependencies: "@babel/types" "^7.15.4" +"@babel/helper-hoist-variables@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" + integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-member-expression-to-functions@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz#bfd34dc9bba9824a4658b0317ec2fd571a51e6ef" @@ -505,14 +587,28 @@ dependencies: "@babel/types" "^7.15.4" -"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.14.5", "@babel/helper-module-imports@^7.15.4": +"@babel/helper-member-expression-to-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz#42b9ca4b2b200123c3b7e726b0ae5153924905b0" + integrity sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz#e18007d230632dea19b47853b984476e7b4e103f" integrity sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA== dependencies: "@babel/types" "^7.15.4" -"@babel/helper-module-transforms@^7.14.5", "@babel/helper-module-transforms@^7.14.8", "@babel/helper-module-transforms@^7.15.4", "@babel/helper-module-transforms@^7.15.8": +"@babel/helper-module-imports@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" + integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-transforms@^7.15.8": version "7.15.8" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz#d8c0e75a87a52e374a8f25f855174786a09498b2" integrity sha512-DfAfA6PfpG8t4S6npwzLvTUpp0sS7JrcuaMiy1Y5645laRJIp/LiLGIBbQKaXSInK8tiGNI7FL7L8UvB8gdUZg== @@ -526,6 +622,20 @@ "@babel/traverse" "^7.15.4" "@babel/types" "^7.15.6" +"@babel/helper-module-transforms@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz#7665faeb721a01ca5327ddc6bba15a5cb34b6a41" + integrity sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng== + dependencies: + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-simple-access" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/helper-validator-identifier" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + "@babel/helper-optimise-call-expression@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz#f310a5121a3b9cc52d9ab19122bd729822dee171" @@ -533,21 +643,33 @@ dependencies: "@babel/types" "^7.15.4" +"@babel/helper-optimise-call-expression@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz#a34e3560605abbd31a18546bd2aad3e6d9a174f2" + integrity sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== -"@babel/helper-remap-async-to-generator@^7.14.5", "@babel/helper-remap-async-to-generator@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.15.4.tgz#2637c0731e4c90fbf58ac58b50b2b5a192fc970f" - integrity sha512-v53MxgvMK/HCwckJ1bZrq6dNKlmwlyRNYM6ypaRTdXWGOE2c1/SCa6dL/HimhPulGhZKw9W0QhREM583F/t0vQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.15.4" - "@babel/helper-wrap-function" "^7.15.4" - "@babel/types" "^7.15.4" +"@babel/helper-plugin-utils@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" + integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== -"@babel/helper-replace-supers@^7.14.5", "@babel/helper-replace-supers@^7.15.4": +"@babel/helper-remap-async-to-generator@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz#29ffaade68a367e2ed09c90901986918d25e57e3" + integrity sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-wrap-function" "^7.16.8" + "@babel/types" "^7.16.8" + +"@babel/helper-replace-supers@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz#52a8ab26ba918c7f6dee28628b07071ac7b7347a" integrity sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw== @@ -557,6 +679,17 @@ "@babel/traverse" "^7.15.4" "@babel/types" "^7.15.4" +"@babel/helper-replace-supers@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz#e9f5f5f32ac90429c1a4bdec0f231ef0c2838ab1" + integrity sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw== + dependencies: + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + "@babel/helper-simple-access@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz#ac368905abf1de8e9781434b635d8f8674bcc13b" @@ -564,12 +697,19 @@ dependencies: "@babel/types" "^7.15.4" -"@babel/helper-skip-transparent-expression-wrappers@^7.14.5", "@babel/helper-skip-transparent-expression-wrappers@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.15.4.tgz#707dbdba1f4ad0fa34f9114fc8197aec7d5da2eb" - integrity sha512-BMRLsdh+D1/aap19TycS4eD1qELGrCBJwzaY9IE8LrpJtJb+H7rQkPIdsfgnMtLBA6DJls7X9z93Z4U8h7xw0A== +"@babel/helper-simple-access@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7" + integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g== dependencies: - "@babel/types" "^7.15.4" + "@babel/types" "^7.16.7" + +"@babel/helper-skip-transparent-expression-wrappers@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz#0ee3388070147c3ae051e487eca3ebb0e2e8bb09" + integrity sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw== + dependencies: + "@babel/types" "^7.16.0" "@babel/helper-split-export-declaration@^7.15.4": version "7.15.4" @@ -578,27 +718,44 @@ dependencies: "@babel/types" "^7.15.4" +"@babel/helper-split-export-declaration@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" + integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.9", "@babel/helper-validator-identifier@^7.15.7": version "7.15.7" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== +"@babel/helper-validator-identifier@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" + integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== + "@babel/helper-validator-option@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow== -"@babel/helper-wrap-function@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.15.4.tgz#6f754b2446cfaf3d612523e6ab8d79c27c3a3de7" - integrity sha512-Y2o+H/hRV5W8QhIfTpRIBwl57y8PrZt6JM3V8FOo5qarjshHItyH5lXlpMfBfmBefOqSCpKZs/6Dxqp0E/U+uw== - dependencies: - "@babel/helper-function-name" "^7.15.4" - "@babel/template" "^7.15.4" - "@babel/traverse" "^7.15.4" - "@babel/types" "^7.15.4" +"@babel/helper-validator-option@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" + integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== -"@babel/helpers@^7.14.8", "@babel/helpers@^7.15.4", "@babel/helpers@^7.8.3": +"@babel/helper-wrap-function@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz#58afda087c4cd235de92f7ceedebca2c41274200" + integrity sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw== + dependencies: + "@babel/helper-function-name" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.8" + "@babel/types" "^7.16.8" + +"@babel/helpers@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.15.4.tgz#5f40f02050a3027121a3cf48d497c05c555eaf43" integrity sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ== @@ -607,6 +764,15 @@ "@babel/traverse" "^7.15.4" "@babel/types" "^7.15.4" +"@babel/helpers@^7.16.7", "@babel/helpers@^7.17.2", "@babel/helpers@^7.8.4": + version "7.17.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.2.tgz#23f0a0746c8e287773ccd27c14be428891f63417" + integrity sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ== + dependencies: + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.0" + "@babel/types" "^7.17.0" + "@babel/highlight@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" @@ -616,150 +782,170 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.14.5", "@babel/parser@^7.14.8", "@babel/parser@^7.15.4", "@babel/parser@^7.15.8", "@babel/parser@^7.8.3": +"@babel/highlight@^7.16.7": + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" + integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.14.7", "@babel/parser@^7.16.12", "@babel/parser@^7.16.7", "@babel/parser@^7.17.3", "@babel/parser@^7.8.6": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.3.tgz#b07702b982990bf6fdc1da5049a23fece4c5c3d0" + integrity sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA== + +"@babel/parser@^7.15.4", "@babel/parser@^7.15.8": version "7.15.8" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.8.tgz#7bacdcbe71bdc3ff936d510c15dcea7cf0b99016" integrity sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA== -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.14.5": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.15.4.tgz#dbdeabb1e80f622d9f0b583efb2999605e0a567e" - integrity sha512-eBnpsl9tlhPhpI10kU06JHnrYXwg3+V6CaP2idsCXNef0aeslpqyITXQ74Vfk5uHgY7IG7XP0yIH8b42KSzHog== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz#4eda6d6c2a0aa79c70fa7b6da67763dfe2141050" + integrity sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.15.4" - "@babel/plugin-proposal-optional-chaining" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-proposal-async-generator-functions@7.14.7": - version "7.14.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz#784a48c3d8ed073f65adcf30b57bcbf6c8119ace" - integrity sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz#cc001234dfc139ac45f6bcf801866198c8c72ff9" + integrity sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-remap-async-to-generator" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + "@babel/plugin-proposal-optional-chaining" "^7.16.7" + +"@babel/plugin-proposal-async-generator-functions@7.16.8", "@babel/plugin-proposal-async-generator-functions@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz#3bdd1ebbe620804ea9416706cd67d60787504bc8" + integrity sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-remap-async-to-generator" "^7.16.8" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-proposal-async-generator-functions@^7.14.7": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.15.8.tgz#a3100f785fab4357987c4223ab1b02b599048403" - integrity sha512-2Z5F2R2ibINTc63mY7FLqGfEbmofrHU9FitJW1Q7aPaKFhiPvSq6QEt/BoWN5oME3GVyjcRuNNSRbb9LC0CSWA== +"@babel/plugin-proposal-class-properties@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz#925cad7b3b1a2fcea7e59ecc8eb5954f961f91b0" + integrity sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-remap-async-to-generator" "^7.15.4" - "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-proposal-class-properties@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz#40d1ee140c5b1e31a350f4f5eed945096559b42e" - integrity sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg== +"@babel/plugin-proposal-class-static-block@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz#712357570b612106ef5426d13dc433ce0f200c2a" + integrity sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-proposal-class-static-block@^7.14.5": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.15.4.tgz#3e7ca6128453c089e8b477a99f970c63fc1cb8d7" - integrity sha512-M682XWrrLNk3chXCjoPUQWOyYsB93B9z3mRyjtqqYJWDf2mfCdIYgDrA11cgNVhAQieaq6F2fn2f3wI0U4aTjA== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.15.4" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-class-static-block" "^7.14.5" -"@babel/plugin-proposal-dynamic-import@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz#0c6617df461c0c1f8fff3b47cd59772360101d2c" - integrity sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g== +"@babel/plugin-proposal-dynamic-import@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz#c19c897eaa46b27634a00fee9fb7d829158704b2" + integrity sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-proposal-export-namespace-from@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz#dbad244310ce6ccd083072167d8cea83a52faf76" - integrity sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA== +"@babel/plugin-proposal-export-namespace-from@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz#09de09df18445a5786a305681423ae63507a6163" + integrity sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-proposal-json-strings@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz#38de60db362e83a3d8c944ac858ddf9f0c2239eb" - integrity sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ== +"@babel/plugin-proposal-json-strings@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz#9732cb1d17d9a2626a08c5be25186c195b6fa6e8" + integrity sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-proposal-logical-assignment-operators@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz#6e6229c2a99b02ab2915f82571e0cc646a40c738" - integrity sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw== +"@babel/plugin-proposal-logical-assignment-operators@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz#be23c0ba74deec1922e639832904be0bea73cdea" + integrity sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz#ee38589ce00e2cc59b299ec3ea406fcd3a0fdaf6" - integrity sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg== +"@babel/plugin-proposal-nullish-coalescing-operator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz#141fc20b6857e59459d430c850a0011e36561d99" + integrity sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" -"@babel/plugin-proposal-numeric-separator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz#83631bf33d9a51df184c2102a069ac0c58c05f18" - integrity sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg== +"@babel/plugin-proposal-numeric-separator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz#d6b69f4af63fb38b6ca2558442a7fb191236eba9" + integrity sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@^7.14.7": - version "7.15.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.15.6.tgz#ef68050c8703d07b25af402cb96cf7f34a68ed11" - integrity sha512-qtOHo7A1Vt+O23qEAX+GdBpqaIuD3i9VRrWgCJeq7WO6H2d14EK3q11urj5Te2MAeK97nMiIdRpwd/ST4JFbNg== +"@babel/plugin-proposal-object-rest-spread@^7.16.7": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz#d9eb649a54628a51701aef7e0ea3d17e2b9dd390" + integrity sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw== dependencies: - "@babel/compat-data" "^7.15.0" - "@babel/helper-compilation-targets" "^7.15.4" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/compat-data" "^7.17.0" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.15.4" + "@babel/plugin-transform-parameters" "^7.16.7" -"@babel/plugin-proposal-optional-catch-binding@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz#939dd6eddeff3a67fdf7b3f044b5347262598c3c" - integrity sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ== +"@babel/plugin-proposal-optional-catch-binding@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz#c623a430674ffc4ab732fd0a0ae7722b67cb74cf" + integrity sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-proposal-optional-chaining@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz#fa83651e60a360e3f13797eef00b8d519695b603" - integrity sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ== +"@babel/plugin-proposal-optional-chaining@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz#7cd629564724816c0e8a969535551f943c64c39a" + integrity sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-proposal-private-methods@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz#37446495996b2945f30f5be5b60d5e2aa4f5792d" - integrity sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g== +"@babel/plugin-proposal-private-methods@^7.16.11": + version "7.16.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz#e8df108288555ff259f4527dbe84813aac3a1c50" + integrity sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-create-class-features-plugin" "^7.16.10" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-proposal-private-property-in-object@^7.14.5": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.15.4.tgz#55c5e3b4d0261fd44fe637e3f624cfb0f484e3e5" - integrity sha512-X0UTixkLf0PCCffxgu5/1RQyGGbgZuKoI+vXP4iSbJSYwPb7hu06omsFGBvQ9lJEvwgrxHdS8B5nbfcd8GyUNA== +"@babel/plugin-proposal-private-property-in-object@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz#b0b8cef543c2c3d57e59e2c611994861d46a3fce" + integrity sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.15.4" - "@babel/helper-create-class-features-plugin" "^7.15.4" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" -"@babel/plugin-proposal-unicode-property-regex@^7.14.5", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": +"@babel/plugin-proposal-unicode-property-regex@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz#635d18eb10c6214210ffc5ff4932552de08188a2" + integrity sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz#0f95ee0e757a5d647f378daa0eca7e93faa8bbe8" integrity sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q== @@ -865,64 +1051,73 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-arrow-functions@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz#f7187d9588a768dd080bf4c9ffe117ea62f7862a" - integrity sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A== +"@babel/plugin-transform-arrow-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz#44125e653d94b98db76369de9c396dc14bef4154" + integrity sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-async-to-generator@7.14.5", "@babel/plugin-transform-async-to-generator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz#72c789084d8f2094acb945633943ef8443d39e67" - integrity sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA== +"@babel/plugin-transform-async-to-generator@7.16.8", "@babel/plugin-transform-async-to-generator@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz#b83dff4b970cf41f1b819f8b49cc0cfbaa53a808" + integrity sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg== dependencies: - "@babel/helper-module-imports" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-remap-async-to-generator" "^7.14.5" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-remap-async-to-generator" "^7.16.8" -"@babel/plugin-transform-block-scoped-functions@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz#e48641d999d4bc157a67ef336aeb54bc44fd3ad4" - integrity sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ== +"@babel/plugin-transform-block-scoped-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz#4d0d57d9632ef6062cdf354bb717102ee042a620" + integrity sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-block-scoping@^7.14.5": - version "7.15.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.15.3.tgz#94c81a6e2fc230bcce6ef537ac96a1e4d2b3afaf" - integrity sha512-nBAzfZwZb4DkaGtOes1Up1nOAp9TDRRFw4XBzBBSG9QK7KVFmYzgj9o9sbPv7TX5ofL4Auq4wZnxCoPnI/lz2Q== +"@babel/plugin-transform-block-scoping@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz#f50664ab99ddeaee5bc681b8f3a6ea9d72ab4f87" + integrity sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-classes@^7.14.5": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.15.4.tgz#50aee17aaf7f332ae44e3bce4c2e10534d5d3bf1" - integrity sha512-Yjvhex8GzBmmPQUvpXRPWQ9WnxXgAFuZSrqOK/eJlOGIXwvv8H3UEdUigl1gb/bnjTrln+e8bkZUYCBt/xYlBg== +"@babel/plugin-transform-classes@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz#8f4b9562850cd973de3b498f1218796eb181ce00" + integrity sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.15.4" - "@babel/helper-function-name" "^7.15.4" - "@babel/helper-optimise-call-expression" "^7.15.4" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-replace-supers" "^7.15.4" - "@babel/helper-split-export-declaration" "^7.15.4" + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz#1b9d78987420d11223d41195461cc43b974b204f" - integrity sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg== +"@babel/plugin-transform-computed-properties@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz#66dee12e46f61d2aae7a73710f591eb3df616470" + integrity sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-destructuring@^7.14.7": - version "7.14.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz#0ad58ed37e23e22084d109f185260835e5557576" - integrity sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw== +"@babel/plugin-transform-destructuring@^7.16.7": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz#c445f75819641788a27a0a3a759d9df911df6abc" + integrity sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-dotall-regex@^7.14.5", "@babel/plugin-transform-dotall-regex@^7.4.4": +"@babel/plugin-transform-dotall-regex@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz#6b2d67686fab15fb6a7fd4bd895d5982cfc81241" + integrity sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-dotall-regex@^7.4.4": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz#2f6bf76e46bdf8043b4e7e16cf24532629ba0c7a" integrity sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw== @@ -930,226 +1125,228 @@ "@babel/helper-create-regexp-features-plugin" "^7.14.5" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-duplicate-keys@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz#365a4844881bdf1501e3a9f0270e7f0f91177954" - integrity sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A== +"@babel/plugin-transform-duplicate-keys@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz#2207e9ca8f82a0d36a5a67b6536e7ef8b08823c9" + integrity sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-exponentiation-operator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz#5154b8dd6a3dfe6d90923d61724bd3deeb90b493" - integrity sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA== +"@babel/plugin-transform-exponentiation-operator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz#efa9862ef97e9e9e5f653f6ddc7b665e8536fe9b" + integrity sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-for-of@^7.14.5": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.15.4.tgz#25c62cce2718cfb29715f416e75d5263fb36a8c2" - integrity sha512-DRTY9fA751AFBDh2oxydvVm4SYevs5ILTWLs6xKXps4Re/KG5nfUkr+TdHCrRWB8C69TlzVgA9b3RmGWmgN9LA== +"@babel/plugin-transform-for-of@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz#649d639d4617dff502a9a158c479b3b556728d8c" + integrity sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-function-name@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz#e81c65ecb900746d7f31802f6bed1f52d915d6f2" - integrity sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ== +"@babel/plugin-transform-function-name@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz#5ab34375c64d61d083d7d2f05c38d90b97ec65cf" + integrity sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA== dependencies: - "@babel/helper-function-name" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz#41d06c7ff5d4d09e3cf4587bd3ecf3930c730f78" - integrity sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A== +"@babel/plugin-transform-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz#254c9618c5ff749e87cb0c0cef1a0a050c0bdab1" + integrity sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-member-expression-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz#b39cd5212a2bf235a617d320ec2b48bcc091b8a7" - integrity sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q== +"@babel/plugin-transform-member-expression-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz#6e5dcf906ef8a098e630149d14c867dd28f92384" + integrity sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-modules-amd@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz#4fd9ce7e3411cb8b83848480b7041d83004858f7" - integrity sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g== +"@babel/plugin-transform-modules-amd@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz#b28d323016a7daaae8609781d1f8c9da42b13186" + integrity sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g== dependencies: - "@babel/helper-module-transforms" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.14.5": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.4.tgz#8201101240eabb5a76c08ef61b2954f767b6b4c1" - integrity sha512-qg4DPhwG8hKp4BbVDvX1s8cohM8a6Bvptu4l6Iingq5rW+yRUAhe/YRup/YcW2zCOlrysEWVhftIcKzrEZv3sA== +"@babel/plugin-transform-modules-commonjs@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz#cdee19aae887b16b9d331009aa9a219af7c86afe" + integrity sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA== dependencies: - "@babel/helper-module-transforms" "^7.15.4" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-simple-access" "^7.15.4" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-simple-access" "^7.16.7" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.14.5": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.15.4.tgz#b42890c7349a78c827719f1d2d0cd38c7d268132" - integrity sha512-fJUnlQrl/mezMneR72CKCgtOoahqGJNVKpompKwzv3BrEXdlPspTcyxrZ1XmDTIr9PpULrgEQo3qNKp6dW7ssw== +"@babel/plugin-transform-modules-systemjs@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz#887cefaef88e684d29558c2b13ee0563e287c2d7" + integrity sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw== dependencies: - "@babel/helper-hoist-variables" "^7.15.4" - "@babel/helper-module-transforms" "^7.15.4" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-validator-identifier" "^7.14.9" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-validator-identifier" "^7.16.7" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-umd@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz#fb662dfee697cce274a7cda525190a79096aa6e0" - integrity sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA== +"@babel/plugin-transform-modules-umd@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz#23dad479fa585283dbd22215bff12719171e7618" + integrity sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ== dependencies: - "@babel/helper-module-transforms" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-named-capturing-groups-regex@^7.14.7": - version "7.14.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz#c68f5c5d12d2ebaba3762e57c2c4f6347a46e7b2" - integrity sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA== +"@babel/plugin-transform-named-capturing-groups-regex@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz#7f860e0e40d844a02c9dcf9d84965e7dfd666252" + integrity sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.14.5" + "@babel/helper-create-regexp-features-plugin" "^7.16.7" -"@babel/plugin-transform-new-target@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz#31bdae8b925dc84076ebfcd2a9940143aed7dbf8" - integrity sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ== +"@babel/plugin-transform-new-target@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz#9967d89a5c243818e0800fdad89db22c5f514244" + integrity sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-object-super@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz#d0b5faeac9e98597a161a9cf78c527ed934cdc45" - integrity sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg== +"@babel/plugin-transform-object-super@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz#ac359cf8d32cf4354d27a46867999490b6c32a94" + integrity sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-replace-supers" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" -"@babel/plugin-transform-parameters@^7.14.5", "@babel/plugin-transform-parameters@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.15.4.tgz#5f2285cc3160bf48c8502432716b48504d29ed62" - integrity sha512-9WB/GUTO6lvJU3XQsSr6J/WKvBC2hcs4Pew8YxZagi6GkTdniyqp8On5kqdK8MN0LMeu0mGbhPN+O049NV/9FQ== +"@babel/plugin-transform-parameters@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz#a1721f55b99b736511cb7e0152f61f17688f331f" + integrity sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-property-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz#0ddbaa1f83db3606f1cdf4846fa1dfb473458b34" - integrity sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw== +"@babel/plugin-transform-property-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz#2dadac85155436f22c696c4827730e0fe1057a55" + integrity sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-regenerator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz#9676fd5707ed28f522727c5b3c0aa8544440b04f" - integrity sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg== +"@babel/plugin-transform-regenerator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz#9e7576dc476cb89ccc5096fff7af659243b4adeb" + integrity sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q== dependencies: regenerator-transform "^0.14.2" -"@babel/plugin-transform-reserved-words@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz#c44589b661cfdbef8d4300dcc7469dffa92f8304" - integrity sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg== +"@babel/plugin-transform-reserved-words@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz#1d798e078f7c5958eec952059c460b220a63f586" + integrity sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-runtime@7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.14.5.tgz#30491dad49c6059f8f8fa5ee8896a0089e987523" - integrity sha512-fPMBhh1AV8ZyneiCIA+wYYUH1arzlXR1UMcApjvchDhfKxhy2r2lReJv8uHEyihi4IFIGlr1Pdx7S5fkESDQsg== +"@babel/plugin-transform-runtime@7.16.10": + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.10.tgz#53d9fd3496daedce1dd99639097fa5d14f4c7c2c" + integrity sha512-9nwTiqETv2G7xI4RvXHNfpGdr8pAA+Q/YtN3yLK7OoK7n9OibVm/xymJ838a9A6E/IciOLPj82lZk0fW6O4O7w== dependencies: - "@babel/helper-module-imports" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - babel-plugin-polyfill-corejs2 "^0.2.2" - babel-plugin-polyfill-corejs3 "^0.2.2" - babel-plugin-polyfill-regenerator "^0.2.2" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + babel-plugin-polyfill-corejs2 "^0.3.0" + babel-plugin-polyfill-corejs3 "^0.5.0" + babel-plugin-polyfill-regenerator "^0.3.0" semver "^6.3.0" -"@babel/plugin-transform-shorthand-properties@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz#97f13855f1409338d8cadcbaca670ad79e091a58" - integrity sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g== +"@babel/plugin-transform-shorthand-properties@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz#e8549ae4afcf8382f711794c0c7b6b934c5fbd2a" + integrity sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-spread@^7.14.6": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.15.8.tgz#79d5aa27f68d700449b2da07691dfa32d2f6d468" - integrity sha512-/daZ8s2tNaRekl9YJa9X4bzjpeRZLt122cpgFnQPLGUe61PH8zMEBmYqKkW5xF5JUEh5buEGXJoQpqBmIbpmEQ== +"@babel/plugin-transform-spread@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz#a303e2122f9f12e0105daeedd0f30fb197d8ff44" + integrity sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.15.4" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" -"@babel/plugin-transform-sticky-regex@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz#5b617542675e8b7761294381f3c28c633f40aeb9" - integrity sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A== +"@babel/plugin-transform-sticky-regex@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz#c84741d4f4a38072b9a1e2e3fd56d359552e8660" + integrity sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-template-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz#a5f2bc233937d8453885dc736bdd8d9ffabf3d93" - integrity sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg== +"@babel/plugin-transform-template-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz#f3d1c45d28967c8e80f53666fc9c3e50618217ab" + integrity sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-typeof-symbol@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz#39af2739e989a2bd291bf6b53f16981423d457d4" - integrity sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw== +"@babel/plugin-transform-typeof-symbol@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz#9cdbe622582c21368bd482b660ba87d5545d4f7e" + integrity sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-unicode-escapes@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz#9d4bd2a681e3c5d7acf4f57fa9e51175d91d0c6b" - integrity sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA== +"@babel/plugin-transform-unicode-escapes@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz#da8717de7b3287a2c6d659750c964f302b31ece3" + integrity sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-unicode-regex@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz#4cd09b6c8425dd81255c7ceb3fb1836e7414382e" - integrity sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw== +"@babel/plugin-transform-unicode-regex@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz#0f7aa4a501198976e25e82702574c34cfebe9ef2" + integrity sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/preset-env@7.14.8": - version "7.14.8" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.14.8.tgz#254942f5ca80ccabcfbb2a9f524c74bca574005b" - integrity sha512-a9aOppDU93oArQ51H+B8M1vH+tayZbuBqzjOhntGetZVa+4tTu5jp+XTwqHGG2lxslqomPYVSjIxQkFwXzgnxg== +"@babel/preset-env@7.16.11": + version "7.16.11" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.11.tgz#5dd88fd885fae36f88fd7c8342475c9f0abe2982" + integrity sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g== dependencies: - "@babel/compat-data" "^7.14.7" - "@babel/helper-compilation-targets" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-validator-option" "^7.14.5" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.14.5" - "@babel/plugin-proposal-async-generator-functions" "^7.14.7" - "@babel/plugin-proposal-class-properties" "^7.14.5" - "@babel/plugin-proposal-class-static-block" "^7.14.5" - "@babel/plugin-proposal-dynamic-import" "^7.14.5" - "@babel/plugin-proposal-export-namespace-from" "^7.14.5" - "@babel/plugin-proposal-json-strings" "^7.14.5" - "@babel/plugin-proposal-logical-assignment-operators" "^7.14.5" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.14.5" - "@babel/plugin-proposal-numeric-separator" "^7.14.5" - "@babel/plugin-proposal-object-rest-spread" "^7.14.7" - "@babel/plugin-proposal-optional-catch-binding" "^7.14.5" - "@babel/plugin-proposal-optional-chaining" "^7.14.5" - "@babel/plugin-proposal-private-methods" "^7.14.5" - "@babel/plugin-proposal-private-property-in-object" "^7.14.5" - "@babel/plugin-proposal-unicode-property-regex" "^7.14.5" + "@babel/compat-data" "^7.16.8" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-validator-option" "^7.16.7" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.16.7" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.16.7" + "@babel/plugin-proposal-async-generator-functions" "^7.16.8" + "@babel/plugin-proposal-class-properties" "^7.16.7" + "@babel/plugin-proposal-class-static-block" "^7.16.7" + "@babel/plugin-proposal-dynamic-import" "^7.16.7" + "@babel/plugin-proposal-export-namespace-from" "^7.16.7" + "@babel/plugin-proposal-json-strings" "^7.16.7" + "@babel/plugin-proposal-logical-assignment-operators" "^7.16.7" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.7" + "@babel/plugin-proposal-numeric-separator" "^7.16.7" + "@babel/plugin-proposal-object-rest-spread" "^7.16.7" + "@babel/plugin-proposal-optional-catch-binding" "^7.16.7" + "@babel/plugin-proposal-optional-chaining" "^7.16.7" + "@babel/plugin-proposal-private-methods" "^7.16.11" + "@babel/plugin-proposal-private-property-in-object" "^7.16.7" + "@babel/plugin-proposal-unicode-property-regex" "^7.16.7" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-class-properties" "^7.12.13" "@babel/plugin-syntax-class-static-block" "^7.14.5" @@ -1164,50 +1361,50 @@ "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-transform-arrow-functions" "^7.14.5" - "@babel/plugin-transform-async-to-generator" "^7.14.5" - "@babel/plugin-transform-block-scoped-functions" "^7.14.5" - "@babel/plugin-transform-block-scoping" "^7.14.5" - "@babel/plugin-transform-classes" "^7.14.5" - "@babel/plugin-transform-computed-properties" "^7.14.5" - "@babel/plugin-transform-destructuring" "^7.14.7" - "@babel/plugin-transform-dotall-regex" "^7.14.5" - "@babel/plugin-transform-duplicate-keys" "^7.14.5" - "@babel/plugin-transform-exponentiation-operator" "^7.14.5" - "@babel/plugin-transform-for-of" "^7.14.5" - "@babel/plugin-transform-function-name" "^7.14.5" - "@babel/plugin-transform-literals" "^7.14.5" - "@babel/plugin-transform-member-expression-literals" "^7.14.5" - "@babel/plugin-transform-modules-amd" "^7.14.5" - "@babel/plugin-transform-modules-commonjs" "^7.14.5" - "@babel/plugin-transform-modules-systemjs" "^7.14.5" - "@babel/plugin-transform-modules-umd" "^7.14.5" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.14.7" - "@babel/plugin-transform-new-target" "^7.14.5" - "@babel/plugin-transform-object-super" "^7.14.5" - "@babel/plugin-transform-parameters" "^7.14.5" - "@babel/plugin-transform-property-literals" "^7.14.5" - "@babel/plugin-transform-regenerator" "^7.14.5" - "@babel/plugin-transform-reserved-words" "^7.14.5" - "@babel/plugin-transform-shorthand-properties" "^7.14.5" - "@babel/plugin-transform-spread" "^7.14.6" - "@babel/plugin-transform-sticky-regex" "^7.14.5" - "@babel/plugin-transform-template-literals" "^7.14.5" - "@babel/plugin-transform-typeof-symbol" "^7.14.5" - "@babel/plugin-transform-unicode-escapes" "^7.14.5" - "@babel/plugin-transform-unicode-regex" "^7.14.5" - "@babel/preset-modules" "^0.1.4" - "@babel/types" "^7.14.8" - babel-plugin-polyfill-corejs2 "^0.2.2" - babel-plugin-polyfill-corejs3 "^0.2.2" - babel-plugin-polyfill-regenerator "^0.2.2" - core-js-compat "^3.15.0" + "@babel/plugin-transform-arrow-functions" "^7.16.7" + "@babel/plugin-transform-async-to-generator" "^7.16.8" + "@babel/plugin-transform-block-scoped-functions" "^7.16.7" + "@babel/plugin-transform-block-scoping" "^7.16.7" + "@babel/plugin-transform-classes" "^7.16.7" + "@babel/plugin-transform-computed-properties" "^7.16.7" + "@babel/plugin-transform-destructuring" "^7.16.7" + "@babel/plugin-transform-dotall-regex" "^7.16.7" + "@babel/plugin-transform-duplicate-keys" "^7.16.7" + "@babel/plugin-transform-exponentiation-operator" "^7.16.7" + "@babel/plugin-transform-for-of" "^7.16.7" + "@babel/plugin-transform-function-name" "^7.16.7" + "@babel/plugin-transform-literals" "^7.16.7" + "@babel/plugin-transform-member-expression-literals" "^7.16.7" + "@babel/plugin-transform-modules-amd" "^7.16.7" + "@babel/plugin-transform-modules-commonjs" "^7.16.8" + "@babel/plugin-transform-modules-systemjs" "^7.16.7" + "@babel/plugin-transform-modules-umd" "^7.16.7" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.16.8" + "@babel/plugin-transform-new-target" "^7.16.7" + "@babel/plugin-transform-object-super" "^7.16.7" + "@babel/plugin-transform-parameters" "^7.16.7" + "@babel/plugin-transform-property-literals" "^7.16.7" + "@babel/plugin-transform-regenerator" "^7.16.7" + "@babel/plugin-transform-reserved-words" "^7.16.7" + "@babel/plugin-transform-shorthand-properties" "^7.16.7" + "@babel/plugin-transform-spread" "^7.16.7" + "@babel/plugin-transform-sticky-regex" "^7.16.7" + "@babel/plugin-transform-template-literals" "^7.16.7" + "@babel/plugin-transform-typeof-symbol" "^7.16.7" + "@babel/plugin-transform-unicode-escapes" "^7.16.7" + "@babel/plugin-transform-unicode-regex" "^7.16.7" + "@babel/preset-modules" "^0.1.5" + "@babel/types" "^7.16.8" + babel-plugin-polyfill-corejs2 "^0.3.0" + babel-plugin-polyfill-corejs3 "^0.5.0" + babel-plugin-polyfill-regenerator "^0.3.0" + core-js-compat "^3.20.2" semver "^6.3.0" -"@babel/preset-modules@^0.1.4": - version "0.1.4" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" - integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== +"@babel/preset-modules@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" + integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" @@ -1215,10 +1412,10 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/runtime@7.14.8": - version "7.14.8" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.8.tgz#7119a56f421018852694290b9f9148097391b446" - integrity sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg== +"@babel/runtime@7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.7.tgz#03ff99f64106588c9c403c6ecb8c3bafbbdff1fa" + integrity sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ== dependencies: regenerator-runtime "^0.13.4" @@ -1229,16 +1426,16 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/template@7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4" - integrity sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g== +"@babel/template@7.16.7", "@babel/template@^7.16.7", "@babel/template@^7.8.6": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" + integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/parser" "^7.14.5" - "@babel/types" "^7.14.5" + "@babel/code-frame" "^7.16.7" + "@babel/parser" "^7.16.7" + "@babel/types" "^7.16.7" -"@babel/template@^7.14.5", "@babel/template@^7.15.4", "@babel/template@^7.8.3": +"@babel/template@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194" integrity sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg== @@ -1247,7 +1444,7 @@ "@babel/parser" "^7.15.4" "@babel/types" "^7.15.4" -"@babel/traverse@^7.13.0", "@babel/traverse@^7.14.8", "@babel/traverse@^7.15.4", "@babel/traverse@^7.8.3": +"@babel/traverse@^7.13.0", "@babel/traverse@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.4.tgz#ff8510367a144bfbff552d9e18e28f3e2889c22d" integrity sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA== @@ -1262,7 +1459,23 @@ debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.14.5", "@babel/types@^7.14.8", "@babel/types@^7.15.4", "@babel/types@^7.15.6", "@babel/types@^7.4.4", "@babel/types@^7.8.3", "@babel/types@^7.8.6": +"@babel/traverse@^7.16.10", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.17.0", "@babel/traverse@^7.17.3", "@babel/traverse@^7.8.6": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57" + integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.17.3" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/parser" "^7.17.3" + "@babel/types" "^7.17.0" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.15.4", "@babel/types@^7.15.6", "@babel/types@^7.4.4", "@babel/types@^7.8.6": version "7.15.6" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.6.tgz#99abdc48218b2881c058dd0a7ab05b99c9be758f" integrity sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig== @@ -1270,20 +1483,40 @@ "@babel/helper-validator-identifier" "^7.14.9" to-fast-properties "^2.0.0" -"@csstools/convert-colors@^1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7" - integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw== +"@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" + integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + to-fast-properties "^2.0.0" -"@discoveryjs/json-ext@0.5.3": - version "0.5.3" - resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz#90420f9f9c6d3987f176a19a7d8e764271a2f55d" - integrity sha512-Fxt+AfXgjMoin2maPIYzFZnQjAXjAL0PHscM5pRTtatFqB+vZxAM9tLp2Optnuw3QOQC40jTNeGYFOMvyf7v9g== +"@cordobo/qrcode@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@cordobo/qrcode/-/qrcode-1.5.0.tgz#fe430514bad73413cd9e4bf4bdd4698353d82217" + integrity sha512-aZ5n3MYw10t4v68EGvRGE1DL7iWfAiTUy4MSZRoqjHTRYdjX40sYgJf48NZa6zZeXVuJOEB/1Ni9KzS+C/EC0w== + dependencies: + dijkstrajs "^1.0.1" + encode-utf8 "^1.0.3" + pngjs "^5.0.0" + yargs "^17.3.1" -"@fortawesome/fontawesome-free@^5.15.4": - version "5.15.4" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz#ecda5712b61ac852c760d8b3c79c96adca5554e5" - integrity sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg== +"@csstools/postcss-progressive-custom-properties@^1.1.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.2.0.tgz#7d53b773de50874c3885918dcb10cac97bf66ed5" + integrity sha512-YLpFPK5OaLIRKZhUfnrZPT9s9cmtqltIOg7W6jPcxmiDpnZ4lk+odfufZttOAgcg6IHWvNLgcITSLpJxIQB/qQ== + dependencies: + postcss-value-parser "^4.2.0" + +"@discoveryjs/json-ext@0.5.6": + version "0.5.6" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz#d5e0706cf8c6acd8c6032f8d54070af261bbbb2f" + integrity sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA== + +"@fortawesome/fontawesome-free@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.0.0.tgz#6f3bd8e42997c7d536a1246877ed8bcd4f005a54" + integrity sha512-6LB4PYBST1Rx40klypw1SmSDArjFOcfBf2LeX9Zg5EKJT2eXiyiJq+CyBYKeXyK0sXS2FsCJWSPr/luyhuvh0Q== "@fullcalendar/core@^4.2.0": version "4.4.2" @@ -1305,64 +1538,77 @@ resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.2.tgz#30aa825f11d438671d585bd44e7fd564535fc210" integrity sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw== +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + "@istanbuljs/schema@^0.1.2": version "0.1.3" resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jridgewell/resolve-uri@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-1.0.0.tgz#3fdf5798f0b49e90155896f6291df186eac06c83" - integrity sha512-9oLAnygRMi8Q5QkYEU4XWK04B+nuoXoxjRvRxgjuChkLZFBja0YPSgdZ7dZtwhncLBcQe/I/E+fLuk5qxcYVJA== - -"@jsdevtools/coverage-istanbul-loader@3.0.5": +"@jridgewell/resolve-uri@^3.0.3": version "3.0.5" - resolved "https://registry.yarnpkg.com/@jsdevtools/coverage-istanbul-loader/-/coverage-istanbul-loader-3.0.5.tgz#2a4bc65d0271df8d4435982db4af35d81754ee26" - integrity sha512-EUCPEkaRPvmHjWAAZkWMT7JDzpw7FKB00WTISaiXsbNOd5hCHg77XLA8sLYLFDo1zepYLo2w7GstN8YBqRXZfA== + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz#68eb521368db76d040a6315cdb24bf2483037b9c" + integrity sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.11" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec" + integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg== + +"@jridgewell/trace-mapping@^0.3.0": + version "0.3.4" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz#f6a0832dffd5b8a6aaa633b7d9f8e8e94c83a0c3" + integrity sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ== dependencies: - convert-source-map "^1.7.0" - istanbul-lib-instrument "^4.0.3" - loader-utils "^2.0.0" - merge-source-map "^1.1.0" - schema-utils "^2.7.0" + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" -"@ngtools/webpack@12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-12.2.10.tgz#38d4a5ee9cc39012e9ba2f987f6c1c07b132b19e" - integrity sha512-8ptz2WqEeqFLOMbiYJ6x6XARjzWIrCHzRzpGwvKS28L5iMWeYuvX2EB48uKkMFy/8RJ0SkwyAJkFClPNJvDfrQ== +"@ngtools/webpack@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-13.2.3.tgz#a4434eb5e2ec3cc04d7f714f20d5203114563f33" + integrity sha512-wooUZiV92QyoeFxkhqIwH/cfiAAAn+l8fEEuaaEIfJtpjpbShvvlboEVsqb28soeGiFJfLcmsZM3mUFgsG4QBQ== -"@ngu/carousel@^3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@ngu/carousel/-/carousel-3.0.2.tgz#e0349e32344655a63fce82c580560365a06c09fd" - integrity sha512-EGvCs0LoStIKJoJfQWGeEs1RYHOgxZiSiqi6Thr7F9NVPvJkkwxlSh40uA6AQoWIv6WWhhNr1Imrbp27NZGs6Q== +"@ngu/carousel@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@ngu/carousel/-/carousel-4.0.0.tgz#928937168010b36946135d86a1a90a8417a0634c" + integrity sha512-/L54YCTMxEZ98BwEWu3cCmH5FkQ2uG6eyw3EANp7D2QOPwry20/5YRWYjp7OkMOVTQ/nOL/pI4na0wJ/qfWD2A== dependencies: - tslib "^2.0.0" + tslib "^2.3.0" -"@ngx-translate/core@^13.0.0": - version "13.0.0" - resolved "https://registry.yarnpkg.com/@ngx-translate/core/-/core-13.0.0.tgz#60547cb8a0845a2a0abfde6b0bf5ec6516a63fd6" - integrity sha512-+tzEp8wlqEnw0Gc7jtVRAJ6RteUjXw6JJR4O65KlnxOmJrCGPI0xjV/lKRnQeU0w4i96PQs/jtpL921Wrb7PWg== +"@ngx-translate/core@^14.0.0": + version "14.0.0" + resolved "https://registry.yarnpkg.com/@ngx-translate/core/-/core-14.0.0.tgz#af421d0e1a28376843f0fed375cd2fae7630a5ff" + integrity sha512-UevdwNCXMRCdJv//0kC8h2eSfmi02r29xeE8E9gJ1Al4D4jEJ7eiLPdjslTMc21oJNGguqqWeEVjf64SFtvw2w== dependencies: - tslib "^2.0.0" + tslib "^2.3.0" -"@ngx-translate/http-loader@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@ngx-translate/http-loader/-/http-loader-6.0.0.tgz#041393ab5753f50ecf64262d624703046b8c7570" - integrity sha512-LCekn6qCbeXWlhESCxU1rAbZz33WzDG0lI7Ig0pYC1o5YxJWrkU9y3Y4tNi+jakQ7R6YhTR2D3ox6APxDtA0wA== +"@ngx-translate/http-loader@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@ngx-translate/http-loader/-/http-loader-7.0.0.tgz#905f38d8d13342621516635bf480ff9a4f73e9fc" + integrity sha512-j+NpXXlcGVdyUNyY/qsJrqqeAdJdizCd+GKh3usXExSqy1aE9866jlAIL+xrfDU4w+LiMoma5pgE4emvFebZmA== dependencies: - tslib "^2.0.0" + tslib "^2.3.0" -"@ngxs/devtools-plugin@^3.7.2": - version "3.7.2" - resolved "https://registry.yarnpkg.com/@ngxs/devtools-plugin/-/devtools-plugin-3.7.2.tgz#995424e5faf48df55a1b54b9e1b36ce9c47c1d52" - integrity sha512-kRuOx1GPXHHZZAeQMm1J1msTZxjgiAUY4NR7bzaQPn+UwSY2OgGEsd8driMM5YSTF1hOjcFHinaLCM1vmu8FmQ== +"@ngxs/devtools-plugin@^3.7.3": + version "3.7.3" + resolved "https://registry.yarnpkg.com/@ngxs/devtools-plugin/-/devtools-plugin-3.7.3.tgz#0f8724ae15aabea4170b00edd632c594de16bd65" + integrity sha512-zkF2OyZKyXW8s/+WZZJgLbWpEguoDAA+EG9qWa/jlysRicYGDVCNZyoxZre4V9BkjwHvY+dQzcDHX4/Ng+Rf5w== dependencies: tslib "^1.9.0" -"@ngxs/store@^3.7.2": - version "3.7.2" - resolved "https://registry.yarnpkg.com/@ngxs/store/-/store-3.7.2.tgz#1088b0669adc382d36ca7ae8438c603e55879b42" - integrity sha512-1cnAjHOGCovfvhjtcAWBajrMXos97Un3c8ekKoS8FIHnq3aQOzY/ePspDRNi9kTcuBJ/r/xl097JC1ssEuNbyg== +"@ngxs/store@^3.7.3": + version "3.7.3" + resolved "https://registry.yarnpkg.com/@ngxs/store/-/store-3.7.3.tgz#74e2878d527fc12dace343ce43fd79fa1a2645af" + integrity sha512-JjATXC7FsxxQu2SaayP/iLe4O+5/RkRov3/J7WkaQmV6/JWFNkkdOwbEa6pDbh/po0JO7DHHMk3huIUNpDu67g== dependencies: tslib "^1.9.0" @@ -1437,14 +1683,14 @@ dependencies: infer-owner "^1.0.4" -"@npmcli/run-script@^1.8.2": - version "1.8.6" - resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-1.8.6.tgz#18314802a6660b0d4baa4c3afe7f1ad39d8c28b7" - integrity sha512-e42bVZnC6VluBZBAFEr3YrdqSspG3bgilyg4nSLBJ7TRGNCzxHa92XAHxQBLYg0BmgwO4b2mf3h/l5EkEWRn3g== +"@npmcli/run-script@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-2.0.0.tgz#9949c0cab415b17aaac279646db4f027d6f1e743" + integrity sha512-fSan/Pu11xS/TdaTpTB0MRn9guwGU8dye+x56mEVgBEd/QsybBbYcAL0phPXi8SGWFEChkQd6M9qL4y6VOpFig== dependencies: "@npmcli/node-gyp" "^1.0.2" "@npmcli/promise-spawn" "^1.3.2" - node-gyp "^7.1.0" + node-gyp "^8.2.0" read-package-json-fast "^2.0.1" "@scarf/scarf@^1.1.0": @@ -1452,13 +1698,13 @@ resolved "https://registry.yarnpkg.com/@scarf/scarf/-/scarf-1.1.1.tgz#d8b9f20037b3a37dbf8dcdc4b3b72f9285bfce35" integrity sha512-VGbKDbk1RFIaSmdVb0cNjjWJoRWRI/Weo23AjRCC2nryO0iAS8pzsToJfPVPtVs74WHw4L1UTADNdIYRLkirZQ== -"@schematics/angular@12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-12.2.10.tgz#c640be969ea7588da14ee5c4d58a6a2ce63b97e6" - integrity sha512-hjOWrC/RlZ97oYWO92f5VRu6LDzPHnowDcyGDGvI9wCrfipL4Y7Is6LgFAiVZxCHdRz71MCnES1IXSj5w6UuBA== +"@schematics/angular@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-13.2.3.tgz#600bbe21bff5b090aaee17ba726410ee1328b40b" + integrity sha512-jloooGC7eco9AKxlIMMqFRptJYzZ0jNRBStWOp2dCISg6rmOKqpxbsHLtYFQIT1PnlomSxtKDAgYGQMDi9zhXw== dependencies: - "@angular-devkit/core" "12.2.10" - "@angular-devkit/schematics" "12.2.10" + "@angular-devkit/core" "13.2.3" + "@angular-devkit/schematics" "13.2.3" jsonc-parser "3.0.0" "@tootallnate/once@1": @@ -1466,10 +1712,40 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== -"@trysound/sax@0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" - integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== +"@tootallnate/once@2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" + integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== + +"@types/body-parser@*": + version "1.19.2" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" + integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/bonjour@^3.5.9": + version "3.5.10" + resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" + integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== + dependencies: + "@types/node" "*" + +"@types/connect-history-api-fallback@^1.3.5": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" + integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== + dependencies: + "@types/express-serve-static-core" "*" + "@types/node" "*" + +"@types/connect@*": + version "3.4.35" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" + integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + dependencies: + "@types/node" "*" "@types/eslint-scope@^3.7.0": version "3.7.1" @@ -1492,12 +1768,30 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83" integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== -"@types/glob@^7.1.1": - version "7.1.4" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.4.tgz#ea59e21d2ee5c517914cb4bc8e4153b99e566672" - integrity sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA== +"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18": + version "4.17.28" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz#c47def9f34ec81dc6328d0b1b5303d1ec98d86b8" + integrity sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + +"@types/express@*": + version "4.17.13" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" + integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.18" + "@types/qs" "*" + "@types/serve-static" "*" + +"@types/http-proxy@^1.17.8": + version "1.17.8" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.8.tgz#968c66903e7e42b483608030ee85800f22d03f55" + integrity sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA== dependencies: - "@types/minimatch" "*" "@types/node" "*" "@types/jasmine@*": @@ -1517,22 +1811,22 @@ dependencies: "@types/jasmine" "*" -"@types/jquery@^3.3.29": - version "3.5.7" - resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.5.7.tgz#07614671f79c6ad70633bb2d8977f01cea242e27" - integrity sha512-Why+9t1KuqWtIqYKtbk6wgWbE1PjyXJOyGkpmTUh0RX5p4HL7nnRuBkjAO9P2r9tGQP6bLWxl77jRLew3V5xXg== +"@types/jquery@^3.5.13": + version "3.5.13" + resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.5.13.tgz#5482d3ee325d5862f77a91c09369ae0a5b082bf3" + integrity sha512-ZxJrup8nz/ZxcU0vantG+TPdboMhB24jad2uSap50zE7Q9rUeYlCF25kFMSmHR33qoeOgqcdHEp3roaookC0Sg== dependencies: "@types/sizzle" "*" -"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8": +"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== -"@types/minimatch@*": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" - integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== +"@types/mime@^1": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" + integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== "@types/node@*", "@types/node@^16.10.9": version "16.10.9" @@ -1549,29 +1843,59 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-0.0.32.tgz#bd284e57c84f1325da702babfc82a5328190c0c5" integrity sha1-vShOV8hPEyXacCur/IKlMoGQwMU= +"@types/qs@*": + version "6.9.7" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + +"@types/range-parser@*": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" + integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + +"@types/retry@^0.12.0": + version "0.12.1" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065" + integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g== + "@types/selenium-webdriver@^3.0.0": version "3.0.19" resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-3.0.19.tgz#28ecede76f15b13553b4e86074d4cf9a0bbe49c4" integrity sha512-OFUilxQg+rWL2FMxtmIgCkUDlJB6pskkpvmew7yeXfzzsOBb5rc+y2+DjHm+r3r1ZPPcJefK3DveNSYWGiy68g== +"@types/serve-index@^1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" + integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== + dependencies: + "@types/express" "*" + +"@types/serve-static@*": + version "1.13.10" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" + integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + "@types/sizzle@*": version "2.3.3" resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.3.tgz#ff5e2f1902969d305225a047c8a0fd5c915cebef" integrity sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ== -"@types/source-list-map@*": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" - integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA== - -"@types/webpack-sources@^0.1.5": - version "0.1.9" - resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-0.1.9.tgz#da69b06eb34f6432e6658acb5a6893c55d983920" - integrity sha512-bvzMnzqoK16PQIC8AYHNdW45eREJQMd6WG/msQWX5V2+vZmODCOPb4TJcbgRljTZZTwTM4wUMcsI8FftNA7new== +"@types/sockjs@^0.3.33": + version "0.3.33" + resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" + integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== + dependencies: + "@types/node" "*" + +"@types/ws@^8.2.2": + version "8.2.2" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.2.2.tgz#7c5be4decb19500ae6b3d563043cd407bf366c21" + integrity sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg== dependencies: "@types/node" "*" - "@types/source-list-map" "*" - source-map "^0.6.1" "@webassemblyjs/ast@1.11.1": version "1.11.1" @@ -1709,12 +2033,12 @@ resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== -"@yellowspot/ng-truncate@^1.4.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@yellowspot/ng-truncate/-/ng-truncate-1.7.0.tgz#36c0dd73f4f8cd2a35c881c97f31fe6c492d1598" - integrity sha512-UX1BqaGuY4H9hc+2u+OSR2jb4mzrtPW2tw+c1ca0er7PZJvWbNuXsKc1Hop2l8BMvddjEfRyCCe6I30zptC2Yg== +"@yellowspot/ng-truncate@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@yellowspot/ng-truncate/-/ng-truncate-2.0.0.tgz#e210fa537975ed454227b65befaa7866e7ef6f73" + integrity sha512-OzUPzcBLgC30gD1sqCgzOGDmZXlviJ51mr3C4HAEF70m9mSzFeCeiGpcJ8f7/SXSWkaMPs+Ar4xcFF4ZKtbFrA== dependencies: - tslib "^1.9.0" + tslib "^2.0.0" abab@^2.0.5: version "2.0.5" @@ -1780,6 +2104,15 @@ agentkeepalive@^4.1.3: depd "^1.1.2" humanize-ms "^1.2.1" +agentkeepalive@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.2.0.tgz#616ce94ccb41d1a39a45d203d8076fe98713062d" + integrity sha512-0PhAp58jZNw13UJv7NVdTGb0ZcghHUb3DrZ046JiiJY/BOaTTpbwdHq2VObPCBV8M2GPh7sgrJ3AQ8Ey468LJw== + dependencies: + debug "^4.1.0" + depd "^1.1.2" + humanize-ms "^1.2.1" + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -1788,34 +2121,36 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv-errors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" - integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== - -ajv-formats@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.0.tgz#96eaf83e38d32108b66d82a9cb0cfa24886cdfeb" - integrity sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q== +ajv-formats@2.1.1, ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== dependencies: ajv "^8.0.0" -ajv-keywords@^3.1.0, ajv-keywords@^3.5.2: +ajv-keywords@^3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@8.6.2: - version "8.6.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.6.2.tgz#2fb45e0e5fcbc0813326c1c3da535d1881bb0571" - integrity sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w== +ajv-keywords@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + +ajv@8.9.0: + version "8.9.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.9.0.tgz#738019146638824dea25edcf299dcba1b0e7eb18" + integrity sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" require-from-string "^2.0.2" uri-js "^4.2.2" -ajv@^6.1.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: +ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -1835,10 +2170,15 @@ ajv@^8.0.0: require-from-string "^2.0.2" uri-js "^4.2.2" -alphanum-sort@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" - integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= +ajv@^8.8.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.10.0.tgz#e573f719bd3af069017e3b66538ab968d040e54d" + integrity sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" angular-bootstrap-md@^7.5.4: version "7.5.4" @@ -1854,24 +2194,19 @@ angular-router-loader@^0.8.5: dependencies: loader-utils "^1.0.2" -angularx-qrcode@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/angularx-qrcode/-/angularx-qrcode-11.0.0.tgz#03f1ccdd34c99fa1fa9f5666febb0b903e3c6881" - integrity sha512-qg6g288LO9daqBP5GCHewy9W0IMW7jDMEaAiklA1za0UhjCj6VH1Agydr4JVp7RMkw1LsLapFhWsVSYqrWaERA== +angularx-qrcode@^13.0.3: + version "13.0.3" + resolved "https://registry.yarnpkg.com/angularx-qrcode/-/angularx-qrcode-13.0.3.tgz#6f632163027354391bcb0e5eaa7da473593a2fa5" + integrity sha512-KzalrRy2MczdApSq29k2TBOml6taQ7NqdgZDNgPSQBd5/27+l3xHkOkhhDOmGruSyCcT2KdB8qeOT/6K48c+xw== dependencies: - qrcode "1.4.2" - tslib "^2.0.0" + "@cordobo/qrcode" "1.5.0" + tslib "^2.3.0" ansi-colors@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== -ansi-colors@^3.0.0: - version "3.2.4" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" - integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== - ansi-escapes@^4.2.1: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -1879,10 +2214,10 @@ ansi-escapes@^4.2.1: dependencies: type-fest "^0.21.3" -ansi-html@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" - integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4= +ansi-html-community@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" + integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== ansi-regex@^2.0.0: version "2.1.1" @@ -1894,22 +2229,22 @@ ansi-regex@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= -ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== - ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= -ansi-styles@^3.2.0, ansi-styles@^3.2.1: +ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -1923,14 +2258,6 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - anymatch@~3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" @@ -1949,18 +2276,18 @@ app-root-path@^3.0.0: resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-3.0.0.tgz#210b6f43873227e18a4b810a032283311555d5ad" integrity sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw== -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== -are-we-there-yet@~1.1.2: - version "1.1.7" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146" - integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g== +are-we-there-yet@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz#ba20bd6b553e31d62fc8c31bd23d22b95734390d" + integrity sha512-0GWpv50YSOcLXaN6/FAKY3vfRbllXWV2xvfA/oKJF8pzFhWXPV+yjhJXDBbjscDYowv7Yw1A3uigpzn5iEGTyw== dependencies: delegates "^1.0.0" - readable-stream "^2.0.6" + readable-stream "^3.6.0" argparse@^1.0.7: version "1.0.10" @@ -1977,21 +2304,6 @@ aria-query@^3.0.0: ast-types-flow "0.0.7" commander "^2.11.0" -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -2014,16 +2326,16 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +array-union@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-3.0.1.tgz#da52630d327f8b88cfbfb57728e2af5cd9b6b975" + integrity sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw== + array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= - arrify@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -2041,21 +2353,11 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - ast-types-flow@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= -async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== - async-limiter@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" @@ -2078,18 +2380,17 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -autoprefixer@^9.6.1: - version "9.8.8" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.8.tgz#fd4bd4595385fa6f06599de749a4d5f7a474957a" - integrity sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA== +autoprefixer@^10.4.2: + version "10.4.2" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.2.tgz#25e1df09a31a9fba5c40b578936b90d35c9d4d3b" + integrity sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ== dependencies: - browserslist "^4.12.0" - caniuse-lite "^1.0.30001109" + browserslist "^4.19.1" + caniuse-lite "^1.0.30001297" + fraction.js "^4.1.2" normalize-range "^0.1.2" - num2fraction "^1.2.2" - picocolors "^0.2.1" - postcss "^7.0.32" - postcss-value-parser "^4.1.0" + picocolors "^1.0.0" + postcss-value-parser "^4.2.0" aws-sign2@~0.7.0: version "0.7.0" @@ -2108,10 +2409,10 @@ axobject-query@2.0.2: dependencies: ast-types-flow "0.0.7" -babel-loader@8.2.2: - version "8.2.2" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.2.tgz#9363ce84c10c9a40e6c753748e1441b60c8a0b81" - integrity sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g== +babel-loader@8.2.3: + version "8.2.3" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.3.tgz#8986b40f1a64cacfcb4b8429320085ef68b1342d" + integrity sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw== dependencies: find-cache-dir "^3.3.1" loader-utils "^1.4.0" @@ -2125,29 +2426,40 @@ babel-plugin-dynamic-import-node@^2.3.3: dependencies: object.assign "^4.1.0" -babel-plugin-polyfill-corejs2@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz#e9124785e6fd94f94b618a7954e5693053bf5327" - integrity sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ== +babel-plugin-istanbul@6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-polyfill-corejs2@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz#440f1b70ccfaabc6b676d196239b138f8a2cfba5" + integrity sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w== dependencies: "@babel/compat-data" "^7.13.11" - "@babel/helper-define-polyfill-provider" "^0.2.2" + "@babel/helper-define-polyfill-provider" "^0.3.1" semver "^6.1.1" -babel-plugin-polyfill-corejs3@^0.2.2: - version "0.2.5" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.5.tgz#2779846a16a1652244ae268b1e906ada107faf92" - integrity sha512-ninF5MQNwAX9Z7c9ED+H2pGt1mXdP4TqzlHKyPIYmJIYz0N+++uwdM7RnJukklhzJ54Q84vA4ZJkgs7lu5vqcw== +babel-plugin-polyfill-corejs3@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz#aabe4b2fa04a6e038b688c5e55d44e78cd3a5f72" + integrity sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ== dependencies: - "@babel/helper-define-polyfill-provider" "^0.2.2" - core-js-compat "^3.16.2" + "@babel/helper-define-polyfill-provider" "^0.3.1" + core-js-compat "^3.21.0" -babel-plugin-polyfill-regenerator@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz#b310c8d642acada348c1fa3b3e6ce0e851bee077" - integrity sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg== +babel-plugin-polyfill-regenerator@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz#2c0678ea47c75c8cc2fbb1852278d8fb68233990" + integrity sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A== dependencies: - "@babel/helper-define-polyfill-provider" "^0.2.2" + "@babel/helper-define-polyfill-provider" "^0.3.1" balanced-match@^1.0.0: version "1.0.2" @@ -2159,19 +2471,6 @@ base64-js@^1.2.0, base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - batch@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" @@ -2189,23 +2488,11 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== - binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -bindings@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - bl@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" @@ -2268,22 +2555,6 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^2.3.1, braces@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - braces@^3.0.1, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -2291,7 +2562,7 @@ braces@^3.0.1, braces@~3.0.2: dependencies: fill-range "^7.0.1" -browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.16.0, browserslist@^4.16.6, browserslist@^4.17.3, browserslist@^4.6.4, browserslist@^4.9.1: +browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.9.1: version "4.17.4" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.4.tgz#72e2508af2a403aec0a49847ef31bd823c57ead4" integrity sha512-Zg7RpbZpIJRW3am9Lyckue7PLytvVxxhJj1CaJVlCWENsGEAOlnlt8X0ZxGRPp7Bt9o8tIRM5SEXy4BCPMJjLQ== @@ -2302,6 +2573,17 @@ browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4 node-releases "^2.0.0" picocolors "^1.0.0" +browserslist@^4.17.5, browserslist@^4.19.1: + version "4.19.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3" + integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A== + dependencies: + caniuse-lite "^1.0.30001286" + electron-to-chromium "^1.4.17" + escalade "^3.1.1" + node-releases "^2.0.1" + picocolors "^1.0.0" + browserstack@^1.5.1: version "1.6.1" resolved "https://registry.yarnpkg.com/browserstack/-/browserstack-1.6.1.tgz#e051f9733ec3b507659f395c7a4765a1b1e358b3" @@ -2347,30 +2629,7 @@ bytes@3.1.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== -cacache@15.2.0: - version "15.2.0" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.2.0.tgz#73af75f77c58e72d8c630a7a2858cb18ef523389" - integrity sha512-uKoJSHmnrqXgthDFx/IU6ED/5xd+NNGe+Bb+kLZy7Ku4P+BaiWEUflAKPZ7eAzsYGcsAGASJZsybXp+quEcHTw== - dependencies: - "@npmcli/move-file" "^1.0.1" - chownr "^2.0.0" - fs-minipass "^2.0.0" - glob "^7.1.4" - infer-owner "^1.0.4" - lru-cache "^6.0.0" - minipass "^3.1.1" - minipass-collect "^1.0.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.2" - mkdirp "^1.0.3" - p-map "^4.0.0" - promise-inflight "^1.0.1" - rimraf "^3.0.2" - ssri "^8.0.1" - tar "^6.0.2" - unique-filename "^1.1.1" - -cacache@^15.0.5, cacache@^15.2.0: +cacache@15.3.0, cacache@^15.0.5, cacache@^15.2.0, cacache@^15.3.0: version "15.3.0" resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb" integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== @@ -2394,21 +2653,6 @@ cacache@^15.0.5, cacache@^15.2.0: tar "^6.0.2" unique-filename "^1.1.1" -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -2422,30 +2666,20 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camelcase@^5.0.0: +camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -caniuse-api@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" - integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== - dependencies: - browserslist "^4.0.0" - caniuse-lite "^1.0.0" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001032, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001265: +caniuse-lite@^1.0.30001265: version "1.0.30001267" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001267.tgz#b1cf2937175afc0570e4615fc2d2f9069fa0ed30" integrity sha512-r1mjTzAuJ9W8cPBGbbus8E0SKcUP7gn03R14Wk8FlAlqhH9hroy9nLqmpuXlfKEw/oILW+FGz47ipXV2O7x8lg== -canonical-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/canonical-path/-/canonical-path-1.0.0.tgz#fcb470c23958def85081856be7a86e904f180d1d" - integrity sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg== +caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001297, caniuse-lite@^1.0.30001299: + version "1.0.30001312" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz#e11eba4b87e24d22697dae05455d5aea28550d5f" + integrity sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ== caseless@~0.12.0: version "0.12.0" @@ -2523,24 +2757,20 @@ chartjs-color@^2.1.0: optionalDependencies: fsevents "~2.3.2" -chokidar@^2.1.8: - version "2.1.8" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" - integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== +chokidar@^3.5.2: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" optionalDependencies: - fsevents "^1.2.7" + fsevents "~2.3.2" chownr@^2.0.0: version "2.0.0" @@ -2557,16 +2787,6 @@ circular-dependency-plugin@5.2.2: resolved "https://registry.yarnpkg.com/circular-dependency-plugin/-/circular-dependency-plugin-5.2.2.tgz#39e836079db1d3cf2f988dc48c5188a44058b600" integrity sha512-g38K9Cm5WRwlaH6g03B9OEz/0qRizI+2I7n+Gz+L5DxXJAPAiWQvwlYNm1V1jkdpUv95bOe/ASm2vfi/G560jQ== -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" @@ -2598,15 +2818,6 @@ cliui@^4.0.0: strip-ansi "^4.0.0" wrap-ansi "^2.0.0" -cliui@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== - dependencies: - string-width "^3.1.0" - strip-ansi "^5.2.0" - wrap-ansi "^5.1.0" - cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -2667,14 +2878,6 @@ codelyzer@^6.0.1: tslib "^1.10.0" zone.js "~0.10.3" -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - color-convert@^1.9.0, color-convert@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -2699,15 +2902,15 @@ color-name@^1.0.0, color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colord@^2.0.1, colord@^2.6: - version "2.8.0" - resolved "https://registry.yarnpkg.com/colord/-/colord-2.8.0.tgz#64fb7aa03de7652b5a39eee50271a104c2783b12" - integrity sha512-kNkVV4KFta3TYQv0bzs4xNwLaeag261pxgzGQSh4cQ1rEhYjcTJfFRP0SDlbhLONg0eSoLzrDd79PosjbltufA== +color-support@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== -colorette@^1.2.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" - integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== +colorette@^2.0.10: + version "2.0.16" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" + integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" @@ -2721,17 +2924,12 @@ commander@^2.11.0, commander@^2.12.1, commander@^2.20.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== - commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= -component-emitter@^1.2.0, component-emitter@^1.2.1: +component-emitter@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== @@ -2766,7 +2964,7 @@ connect-history-api-fallback@^1.6.0: resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== -console-control-strings@^1.0.0, console-control-strings@~1.1.0: +console-control-strings@^1.0.0, console-control-strings@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= @@ -2812,36 +3010,30 @@ copy-anything@^2.0.1: dependencies: is-what "^3.12.0" -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= - -copy-webpack-plugin@9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-9.0.1.tgz#b71d21991599f61a4ee00ba79087b8ba279bbb59" - integrity sha512-14gHKKdYIxF84jCEgPgYXCPpldbwpxxLbCmA7LReY7gvbaT555DgeBWBgBZM116tv/fO6RRJrsivBqRyRlukhw== +copy-webpack-plugin@10.2.1: + version "10.2.1" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-10.2.1.tgz#115a41f913070ac236a1b576066204cbf35341a1" + integrity sha512-nr81NhCAIpAWXGCK5thrKmfCQ6GDY0L5RN0U+BnIn/7Us55+UCex5ANNsNKmIVtDRnk0Ecf+/kzp9SUVrrBMLg== dependencies: - fast-glob "^3.2.5" - glob-parent "^6.0.0" - globby "^11.0.3" + fast-glob "^3.2.7" + glob-parent "^6.0.1" + globby "^12.0.2" normalize-path "^3.0.0" - p-limit "^3.1.0" - schema-utils "^3.0.0" + schema-utils "^4.0.0" serialize-javascript "^6.0.0" -core-js-compat@^3.15.0, core-js-compat@^3.16.2: - version "3.18.3" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.18.3.tgz#e0e7e87abc55efb547e7fa19169e45fa9df27a67" - integrity sha512-4zP6/y0a2RTHN5bRGT7PTq9lVt3WzvffTNjqnTKsXhkAYNDTkdCLOIfAdOLcQ/7TDdyRj3c+NeHe1NmF1eDScw== +core-js-compat@^3.20.2, core-js-compat@^3.21.0: + version "3.21.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.21.1.tgz#cac369f67c8d134ff8f9bd1623e3bc2c42068c82" + integrity sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g== dependencies: - browserslist "^4.17.3" + browserslist "^4.19.1" semver "7.0.0" -core-js@3.16.0: - version "3.16.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.16.0.tgz#1d46fb33720bc1fa7f90d20431f36a5540858986" - integrity sha512-5+5VxRFmSf97nM8Jr2wzOwLqRo6zphH2aX+7KsAUONObyzakDNq2G/bgbhinxB4PoV9L3aXQYhiDKyIKWd2c8g== +core-js@3.20.3: + version "3.20.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.20.3.tgz#c710d0a676e684522f3db4ee84e5e18a9d11d69a" + integrity sha512-vVl8j8ph6tRS3B8qir40H7yw7voy17xL0piAjlbBUsH7WIfzoedL/ZOr1OV9FyZQLWXsayOJyV4tnRyXR85/ag== core-js@^2.5.4: version "2.6.12" @@ -2869,15 +3061,16 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" -critters@0.0.10: - version "0.0.10" - resolved "https://registry.yarnpkg.com/critters/-/critters-0.0.10.tgz#edd0e962fc5af6c4adb6dbf1a71bae2d3f917000" - integrity sha512-p5VKhP1803+f+0Jq5P03w1SbiHtpAKm+1EpJHkiPxQPq0Vu9QLZHviJ02GRrWi0dlcJqrmzMWInbwp4d22RsGw== +critters@0.0.16: + version "0.0.16" + resolved "https://registry.yarnpkg.com/critters/-/critters-0.0.16.tgz#ffa2c5561a65b43c53b940036237ce72dcebfe93" + integrity sha512-JwjgmO6i3y6RWtLYmXwO5jMd+maZt8Tnfu7VVISmEWyQqfLpB8soBswf8/2bu6SBXxtKA68Al3c+qIG1ApT68A== dependencies: chalk "^4.1.0" - css "^3.0.0" + css-select "^4.2.0" parse5 "^6.0.1" parse5-htmlparser2-tree-adapter "^6.0.1" + postcss "^8.3.7" pretty-bytes "^5.3.0" cross-spawn@^6.0.0: @@ -2891,37 +3084,33 @@ cross-spawn@^6.0.0: shebang-command "^1.2.0" which "^1.2.9" -css-blank-pseudo@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5" - integrity sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w== +cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== dependencies: - postcss "^7.0.5" + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" -css-color-names@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-1.0.1.tgz#6ff7ee81a823ad46e020fa2fd6ab40a887e2ba67" - integrity sha512-/loXYOch1qU1biStIFsHH8SxTmOseh1IJqFvy8IujXOm1h+QjUdDhkzOrR5HG8K8mlxREj0yfi8ewCHx0eMxzA== - -css-declaration-sorter@^6.0.3: - version "6.1.3" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.1.3.tgz#e9852e4cf940ba79f509d9425b137d1f94438dc2" - integrity sha512-SvjQjNRZgh4ULK1LDJ2AduPKUKxIqmtU7ZAyi47BTV+M90Qvxr9AB6lKlLbDUfXqI9IQeYA8LbAsCZPpJEV3aA== +css-blank-pseudo@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz#36523b01c12a25d812df343a32c322d2a2324561" + integrity sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ== dependencies: - timsort "^0.3.0" + postcss-selector-parser "^6.0.9" -css-has-pseudo@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz#3c642ab34ca242c59c41a125df9105841f6966ee" - integrity sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ== +css-has-pseudo@^3.0.3: + version "3.0.4" + resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz#57f6be91ca242d5c9020ee3e51bbb5b89fc7af73" + integrity sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw== dependencies: - postcss "^7.0.6" - postcss-selector-parser "^5.0.0-rc.4" + postcss-selector-parser "^6.0.9" -css-loader@6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.2.0.tgz#9663d9443841de957a3cb9bcea2eda65b3377071" - integrity sha512-/rvHfYRjIpymZblf49w8jYcRo2y9gj6rV8UroHGmBxKrIyGLokpycyKzp9OkitvqT29ZSpzJ0Ic7SpnJX3sC8g== +css-loader@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.5.1.tgz#0c43d4fbe0d97f699c91e9818cb585759091d1b1" + integrity sha512-gEy2w9AnJNnD9Kuo4XAP9VflW/ujKoS9c/syO+uWMlm5igc7LysKzPXaDoR2vroROkSwsTS2tGr1yGGEbZOYZQ== dependencies: icss-utils "^5.1.0" postcss "^8.2.15" @@ -2932,43 +3121,21 @@ css-loader@6.2.0: postcss-value-parser "^4.1.0" semver "^7.3.5" -css-minimizer-webpack-plugin@3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.0.2.tgz#8fadbdf10128cb40227bff275a4bb47412534245" - integrity sha512-B3I5e17RwvKPJwsxjjWcdgpU/zqylzK1bPVghcmpFHRL48DXiBgrtqz1BJsn68+t/zzaLp9kYAaEDvQ7GyanFQ== - dependencies: - cssnano "^5.0.6" - jest-worker "^27.0.2" - p-limit "^3.0.2" - postcss "^8.3.5" - schema-utils "^3.0.0" - serialize-javascript "^6.0.0" - source-map "^0.6.1" +css-prefers-color-scheme@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz#ca8a22e5992c10a5b9d315155e7caee625903349" + integrity sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA== -css-parse@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/css-parse/-/css-parse-2.0.0.tgz#a468ee667c16d81ccf05c58c38d2a97c780dbfd4" - integrity sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q= - dependencies: - css "^2.0.0" - -css-prefers-color-scheme@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz#6f830a2714199d4f0d0d0bb8a27916ed65cff1f4" - integrity sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg== - dependencies: - postcss "^7.0.5" - -css-select@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.1.3.tgz#a70440f70317f2669118ad74ff105e65849c7067" - integrity sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA== +css-select@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.2.1.tgz#9e665d6ae4c7f9d65dbe69d0316e3221fb274cdd" + integrity sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ== dependencies: boolbase "^1.0.0" - css-what "^5.0.0" - domhandler "^4.2.0" - domutils "^2.6.0" - nth-check "^2.0.0" + css-what "^5.1.0" + domhandler "^4.3.0" + domutils "^2.8.0" + nth-check "^2.0.1" css-selector-tokenizer@^0.7.0, css-selector-tokenizer@^0.7.1: version "0.7.3" @@ -2978,29 +3145,11 @@ css-selector-tokenizer@^0.7.0, css-selector-tokenizer@^0.7.1: cssesc "^3.0.0" fastparse "^1.1.2" -css-tree@^1.1.2, css-tree@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" - integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== - dependencies: - mdn-data "2.0.14" - source-map "^0.6.1" - -css-what@^5.0.0: +css-what@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== -css@^2.0.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" - integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw== - dependencies: - inherits "^2.0.3" - source-map "^0.6.1" - source-map-resolve "^0.5.2" - urix "^0.1.0" - css@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/css/-/css-3.0.0.tgz#4447a4d58fdd03367c516ca9f64ae365cee4aa5d" @@ -3017,78 +3166,16 @@ cssauron@^1.4.0: dependencies: through X.X.X -cssdb@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0" - integrity sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ== - -cssesc@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" - integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== +cssdb@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-5.1.0.tgz#ec728d5f5c0811debd0820cbebda505d43003400" + integrity sha512-/vqjXhv1x9eGkE/zO6o8ZOI7dgdZbLVLUGyVRbPgk6YipXbW87YzUCcO+Jrmi5bwJlAH6oD+MNeZyRgXea1GZw== cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== -cssnano-preset-default@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.1.4.tgz#359943bf00c5c8e05489f12dd25f3006f2c1cbd2" - integrity sha512-sPpQNDQBI3R/QsYxQvfB4mXeEcWuw0wGtKtmS5eg8wudyStYMgKOQT39G07EbW1LB56AOYrinRS9f0ig4Y3MhQ== - dependencies: - css-declaration-sorter "^6.0.3" - cssnano-utils "^2.0.1" - postcss-calc "^8.0.0" - postcss-colormin "^5.2.0" - postcss-convert-values "^5.0.1" - postcss-discard-comments "^5.0.1" - postcss-discard-duplicates "^5.0.1" - postcss-discard-empty "^5.0.1" - postcss-discard-overridden "^5.0.1" - postcss-merge-longhand "^5.0.2" - postcss-merge-rules "^5.0.2" - postcss-minify-font-values "^5.0.1" - postcss-minify-gradients "^5.0.2" - postcss-minify-params "^5.0.1" - postcss-minify-selectors "^5.1.0" - postcss-normalize-charset "^5.0.1" - postcss-normalize-display-values "^5.0.1" - postcss-normalize-positions "^5.0.1" - postcss-normalize-repeat-style "^5.0.1" - postcss-normalize-string "^5.0.1" - postcss-normalize-timing-functions "^5.0.1" - postcss-normalize-unicode "^5.0.1" - postcss-normalize-url "^5.0.2" - postcss-normalize-whitespace "^5.0.1" - postcss-ordered-values "^5.0.2" - postcss-reduce-initial "^5.0.1" - postcss-reduce-transforms "^5.0.1" - postcss-svgo "^5.0.2" - postcss-unique-selectors "^5.0.1" - -cssnano-utils@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-2.0.1.tgz#8660aa2b37ed869d2e2f22918196a9a8b6498ce2" - integrity sha512-i8vLRZTnEH9ubIyfdZCAdIdgnHAUeQeByEeQ2I7oTilvP9oHO6RScpeq3GsFUVqeB8uZgOQ9pw8utofNn32hhQ== - -cssnano@^5.0.6: - version "5.0.8" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.0.8.tgz#39ad166256980fcc64faa08c9bb18bb5789ecfa9" - integrity sha512-Lda7geZU0Yu+RZi2SGpjYuQz4HI4/1Y+BhdD0jL7NXAQ5larCzVn+PUGuZbDMYz904AXXCOgO5L1teSvgu7aFg== - dependencies: - cssnano-preset-default "^5.1.4" - is-resolvable "^1.1.0" - lilconfig "^2.0.3" - yaml "^1.10.2" - -csso@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" - integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== - dependencies: - css-tree "^1.1.2" - damerau-levenshtein@^1.0.4: version "1.0.7" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz#64368003512a1a6992593741a09a9d31a836f55d" @@ -3101,20 +3188,27 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -debug@2.6.9, debug@^2.2.0, debug@^2.3.3: +debug@2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@4, debug@4.3.2, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: version "4.3.2" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== dependencies: ms "2.1.2" +debug@4.3.3, debug@^4.3.2: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + debug@^3.1.0, debug@^3.1.1, debug@^3.2.6: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -3122,13 +3216,6 @@ debug@^3.1.0, debug@^3.1.1, debug@^3.2.6: dependencies: ms "^2.1.1" -debug@~3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -3151,13 +3238,12 @@ deep-equal@^1.0.1: object-keys "^1.1.1" regexp.prototype.flags "^1.2.0" -default-gateway@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" - integrity sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA== +default-gateway@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" + integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== dependencies: - execa "^1.0.0" - ip-regex "^2.1.0" + execa "^5.0.0" defaults@^1.0.3: version "1.0.3" @@ -3178,28 +3264,6 @@ define-properties@^1.1.3: dependencies: object-keys "^1.0.12" -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - del@^2.2.0: version "2.2.2" resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" @@ -3213,18 +3277,19 @@ del@^2.2.0: pinkie-promise "^2.0.0" rimraf "^2.2.8" -del@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" - integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== +del@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/del/-/del-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952" + integrity sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ== dependencies: - "@types/glob" "^7.1.1" - globby "^6.1.0" - is-path-cwd "^2.0.0" - is-path-in-cwd "^2.0.0" - p-map "^2.0.0" - pify "^4.0.1" - rimraf "^2.6.3" + globby "^11.0.1" + graceful-fs "^4.2.4" + is-glob "^4.0.1" + is-path-cwd "^2.2.0" + is-path-inside "^3.0.2" + p-map "^4.0.0" + rimraf "^3.0.2" + slash "^3.0.0" delayed-stream@~1.0.0: version "1.0.0" @@ -3319,12 +3384,19 @@ domhandler@^4.2.0: dependencies: domelementtype "^2.2.0" +domhandler@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.0.tgz#16c658c626cf966967e306f966b431f77d4a5626" + integrity sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g== + dependencies: + domelementtype "^2.2.0" + domino@^2.1.2: version "2.1.6" resolved "https://registry.yarnpkg.com/domino/-/domino-2.1.6.tgz#fe4ace4310526e5e7b9d12c7de01b7f485a57ffe" integrity sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ== -domutils@^2.6.0: +domutils@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== @@ -3351,10 +3423,10 @@ electron-to-chromium@^1.3.867: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.868.tgz#ed835023b57ecf0ba63dfe7d50e16b53758ab1da" integrity sha512-kZYCHqwJ1ctGrYDlOcWQH+/AftAm/KD4lEnLDNwS0kKwx1x6dU4zv+GuDjsPPOGn/2TjnKBaZjDyjXaoix0q/A== -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== +electron-to-chromium@^1.4.17: + version "1.4.71" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.71.tgz#17056914465da0890ce00351a3b946fd4cd51ff6" + integrity sha512-Hk61vXXKRb2cd3znPE9F+2pLWdIOmP7GjiTj45y6L3W/lO+hSnUSUhq+6lEaERWBdZOHbk2s3YV5c9xVl3boVw== emoji-regex@^8.0.0: version "8.0.0" @@ -3366,6 +3438,11 @@ emojis-list@^3.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== +encode-utf8@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" + integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -3385,10 +3462,10 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enhanced-resolve@^5.8.0: - version "5.8.3" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz#6d552d465cce0423f5b3d718511ea53826a7b2f0" - integrity sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA== +enhanced-resolve@^5.8.3: + version "5.9.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.0.tgz#49ac24953ac8452ed8fed2ef1340fc8e043667ee" + integrity sha512-weDYmzbBygL7HzGGS26M3hGQx68vehdEg6VUmqSOaFzXExFqlnKuSvsEJCVGQHScS8CQMbrAqftT+AzzHNt/YA== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -3408,7 +3485,7 @@ err-code@^2.0.2: resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== -errno@^0.1.1, errno@^0.1.3: +errno@^0.1.1: version "0.1.8" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== @@ -3422,10 +3499,10 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-module-lexer@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.7.1.tgz#c2c8e0f46f2df06274cdaf0dd3f3b33e0a0b267d" - integrity sha512-MgtWFl5No+4S3TmhDmCz2ObFGm6lEpTnzbQi+Dd+pw4mlTIZTmM2iAs5gRlmx5zS9luzobCSBSI90JM/1/JgOw== +es-module-lexer@^0.9.0: + version "0.9.3" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" + integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== es6-promise@^4.0.3: version "4.2.8" @@ -3439,112 +3516,124 @@ es6-promisify@^5.0.0: dependencies: es6-promise "^4.0.3" -esbuild-android-arm64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.13.4.tgz#5178a20d2b7aba741a31c19609f9e67b346996b9" - integrity sha512-elDJt+jNyoHFId0/dKsuVYUPke3EcquIyUwzJCH17a3ERglN3A9aMBI5zbz+xNZ+FbaDNdpn0RaJHCFLbZX+fA== +esbuild-android-arm64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.14.tgz#3705f32f209deeb11c275af47c298c8783dd5f0c" + integrity sha512-be/Uw6DdpQiPfula1J4bdmA+wtZ6T3BRCZsDMFB5X+k0Gp8TIh9UvmAcqvKNnbRAafSaXG3jPCeXxDKqnc8hFQ== -esbuild-darwin-64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.13.4.tgz#7a3e66c8e1271b650541b25eed65c84f3564a69d" - integrity sha512-zJQGyHRAdZUXlRzbN7W+7ykmEiGC+bq3Gc4GxKYjjWTgDRSEly98ym+vRNkDjXwXYD3gGzSwvH35+MiHAtWvLA== +esbuild-darwin-64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.14.tgz#c07e4eae6d938300a2d330ea82494c55bcea84e5" + integrity sha512-BEexYmjWafcISK8cT6O98E3TfcLuZL8DKuubry6G54n2+bD4GkoRD6HYUOnCkfl2p7jodA+s4369IjSFSWjtHg== -esbuild-darwin-arm64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.4.tgz#793feca6032b2a57ef291eb9b2d33768d60a49d6" - integrity sha512-r8oYvAtqSGq8HNTZCAx4TdLE7jZiGhX9ooGi5AQAey37MA6XNaP8ZNlw9OCpcgpx3ryU2WctXwIqPzkHO7a8dg== +esbuild-darwin-arm64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.14.tgz#a8631e13a51a6f784fb0906e2a64c6ab53988755" + integrity sha512-tnBKm41pDOB1GtZ8q/w26gZlLLRzVmP8fdsduYjvM+yFD7E2DLG4KbPAqFMWm4Md9B+DitBglP57FY7AznxbTg== -esbuild-freebsd-64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.4.tgz#294aec3c2cf4b41fb6900212fc9c33dd8fbbb4a2" - integrity sha512-u9DRGkn09EN8+lCh6z7FKle7awi17PJRBuAKdRNgSo5ZrH/3m+mYaJK2PR2URHMpAfXiwJX341z231tSdVe3Yw== +esbuild-freebsd-64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.14.tgz#c280c2b944746b27ee6c6487c2691865c90bed2e" + integrity sha512-Q9Rx6sgArOHalQtNwAaIzJ6dnQ8A+I7f/RsQsdkS3JrdzmnlFo8JEVofTmwVQLoIop7OKUqIVOGP4PoQcwfVMA== -esbuild-freebsd-arm64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.4.tgz#09fe66c751c12f9b976976b1d83f3de594cb2787" - integrity sha512-q3B2k68Uf6gfjATjcK16DqxvjqRQkHL8aPoOfj4op+lSqegdXvBacB1d8jw8PxbWJ8JHpdTLdAVUYU80kotQXA== +esbuild-freebsd-arm64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.14.tgz#aa4e21276efcf20e5ab2487e91ca1d789573189b" + integrity sha512-TJvq0OpLM7BkTczlyPIphcvnwrQwQDG1HqxzoYePWn26SMUAlt6wrLnEvxdbXAvNvDLVzG83kA+JimjK7aRNBA== -esbuild-linux-32@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.13.4.tgz#a9f0793d7bcc9cef4f4ffa4398c525877fba5839" - integrity sha512-UUYJPHSiKAO8KoN3Ls/iZtgDLZvK5HarES96aolDPWZnq9FLx4dIHM/x2z4Rxv9IYqQ/DxlPoE2Co1UPBIYYeA== +esbuild-linux-32@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.14.tgz#3db4d929239203ce38a9060d5419ac6a6d28846c" + integrity sha512-h/CrK9Baimt5VRbu8gqibWV7e1P9l+mkanQgyOgv0Ng3jHT1NVFC9e6rb1zbDdaJVmuhWX5xVliUA5bDDCcJeg== -esbuild-linux-64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.13.4.tgz#c0d0b4c9d62e3bbf8bdf2cece37403aa6d60fc2e" - integrity sha512-+RnohAKiiUW4UHLGRkNR1AnENW1gCuDWuygEtd4jxTNPIoeC7lbXGor7rtgjj9AdUzFgOEvAXyNNX01kJ8NueQ== +esbuild-linux-64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.14.tgz#f880026254c1f565a7a10fdebb7cff9b083a127d" + integrity sha512-IC+wAiIg/egp5OhQp4W44D9PcBOH1b621iRn1OXmlLzij9a/6BGr9NMIL4CRwz4j2kp3WNZu5sT473tYdynOuQ== -esbuild-linux-arm64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.4.tgz#1292d97bfa64a08d12728f8a7837bf92776c779b" - integrity sha512-+A188cAdd6QuSRxMIwRrWLjgphQA0LDAQ/ECVlrPVJwnx+1i64NjDZivoqPYLOTkSPIKntiWwMhhf0U5/RrPHQ== +esbuild-linux-arm64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.14.tgz#a34bc3076e50b109c3b8c8bad9c146e35942322b" + integrity sha512-6QVul3RI4M5/VxVIRF/I5F+7BaxzR3DfNGoqEVSCZqUbgzHExPn+LXr5ly1C7af2Kw4AHpo+wDqx8A4ziP9avw== -esbuild-linux-arm@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.13.4.tgz#186cd9b8885ac132b9953a4a0afe668168debd10" - integrity sha512-BH5gKve4jglS7UPSsfwHSX79I5agC/lm4eKoRUEyo8lwQs89frQSRp2Xup+6SFQnxt3md5EsKcd2Dbkqeb3gPA== +esbuild-linux-arm@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.14.tgz#231ffd12fef69ee06365d4c94b69850e4830e927" + integrity sha512-gxpOaHOPwp7zSmcKYsHrtxabScMqaTzfSQioAMUaB047YiMuDBzqVcKBG8OuESrYkGrL9DDljXr/mQNg7pbdaQ== -esbuild-linux-mips64le@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.4.tgz#42049bf72bc586817b4a51cc9e32148d13e5e807" - integrity sha512-0xkwtPaUkG5xMTFGaQPe1AadSe5QAiQuD4Gix1O9k5Xo/U8xGIkw9UFUTvfEUeu71vFb6ZgsIacfP1NLoFjWNw== +esbuild-linux-mips64le@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.14.tgz#bd00570e3a30422224b732c7a5f262146c357403" + integrity sha512-4Jl5/+xoINKbA4cesH3f4R+q0vltAztZ6Jm8YycS8lNhN1pgZJBDxWfI6HUMIAdkKlIpR1PIkA9aXQgZ8sxFAg== -esbuild-linux-ppc64le@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.4.tgz#adf1ce2ef2302757c4383887da6ac4dd25be9d4f" - integrity sha512-E1+oJPP7A+j23GPo3CEpBhGwG1bni4B8IbTA3/3rvzjURwUMZdcN3Fhrz24rnjzdLSHmULtOE4VsbT42h1Om4Q== +esbuild-linux-ppc64le@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.14.tgz#430609413fd9e04d9def4e3f06726b031b23d825" + integrity sha512-BitW37GxeebKxqYNl4SVuSdnIJAzH830Lr6Mkq3pBHXtzQay0vK+IeOR/Ele1GtNVJ+/f8wYM53tcThkv5SC5w== -esbuild-openbsd-64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.4.tgz#1c8122101898c52a20c8786935cf3eb7a19b83b4" - integrity sha512-xEkI1o5HYxDzbv9jSox0EsDxpwraG09SRiKKv0W8pH6O3bt+zPSlnoK7+I7Q69tkvONkpIq5n2o+c55uq0X7cw== +esbuild-linux-s390x@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.14.tgz#2f0d8cbfe53cf3cb97f6372549a41a8051dbd689" + integrity sha512-vLj6p76HOZG3wfuTr5MyO3qW5iu8YdhUNxuY+tx846rPo7GcKtYSPMusQjeVEfZlJpSYoR+yrNBBxq+qVF9zrw== -esbuild-sunos-64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.13.4.tgz#4ec95faa14a60f295fe485bebffefff408739337" - integrity sha512-bjXUMcODMnB6hQicLBBmmnBl7OMDyVpFahKvHGXJfDChIi5udiIRKCmFUFIRn+AUAKVlfrofRKdyPC7kBsbvGQ== +esbuild-netbsd-64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.14.tgz#3e44de35e1add7e9582f3c0d2558d86aafbc813b" + integrity sha512-fn8looXPQhpVqUyCBWUuPjesH+yGIyfbIQrLKG05rr1Kgm3rZD/gaYrd3Wpmf5syVZx70pKZPvdHp8OTA+y7cQ== -esbuild-wasm@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-wasm/-/esbuild-wasm-0.13.4.tgz#9ae8ec5234cc651b2d74b23d4adac984055cff1c" - integrity sha512-2dN7njr9/2QzKLqbTEgXr73vDbSqffdJMv4EfaMQoy04cej0owbGHH5apPgED0wN9I5e7sBT0/Q81tVy3wQBlA== +esbuild-openbsd-64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.14.tgz#04710ef1d01cd9f15d54f50d20b5a3778f8306a2" + integrity sha512-HdAnJ399pPff3SKbd8g+P4o5znseni5u5n5rJ6Z7ouqOdgbOwHe2ofZbMow17WMdNtz1IyOZk2Wo9Ve6/lZ4Rg== -esbuild-windows-32@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.13.4.tgz#3182c380487b797b04d0ec2c80c2945666869080" - integrity sha512-z4CH07pfyVY0XF98TCsGmLxKCl0kyvshKDbdpTekW9f2d+dJqn5mmoUyWhpSVJ0SfYWJg86FoD9nMbbaMVyGdg== +esbuild-sunos-64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.14.tgz#8e583dd92c5c7ac4303ddc37f588e44211e04e19" + integrity sha512-bmDHa99ulsGnYlh/xjBEfxoGuC8CEG5OWvlgD+pF7bKKiVTbtxqVCvOGEZeoDXB+ja6AvHIbPxrEE32J+m5nqQ== -esbuild-windows-64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.13.4.tgz#b9e995f92d81f433a04f33611e603e82f9232e69" - integrity sha512-uVL11vORRPjocGLYam67rwFLd0LvkrHEs+JG+1oJN4UD9MQmNGZPa4gBHo6hDpF+kqRJ9kXgQSeDqUyRy0tj/Q== +esbuild-wasm@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-wasm/-/esbuild-wasm-0.14.14.tgz#d4c8d5fc405939a2234a31abf00967dfd1da1caa" + integrity sha512-qTjK4MWnYtQHCMGg2qDUqeFYXfVvYq5qJkQTIsOV4VZCknoYePVaDTG9ygEB9Ct0kc0DWs7IrS6Ja+GjY62Kzw== -esbuild-windows-arm64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.4.tgz#fb239532f07b764d158f4cc787178ef4c6fadb5c" - integrity sha512-vA6GLvptgftRcDcWngD5cMlL4f4LbL8JjU2UMT9yJ0MT5ra6hdZNFWnOeOoEtY4GtJ6OjZ0i+81sTqhAB0fMkg== +esbuild-windows-32@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.14.tgz#6d293ddfb71229f21cc13d85d5d2f43e8131693b" + integrity sha512-6tVooQcxJCNenPp5GHZBs/RLu31q4B+BuF4MEoRxswT+Eq2JGF0ZWDRQwNKB8QVIo3t6Svc5wNGez+CwKNQjBg== -esbuild@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.13.4.tgz#ce2deb56c4fb360938311cbfc67f8e467bb6841b" - integrity sha512-wMA5eUwpavTBiNl+It6j8OQuKVh69l6z4DKDLzoTIqC+gChnPpcmqdA8WNHptUHRnfyML+mKEQPlW7Mybj8gHg== +esbuild-windows-64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.14.tgz#08a36844b69542f8ec1cb33a5ddcea02b9d0b2e8" + integrity sha512-kl3BdPXh0/RD/dad41dtzj2itMUR4C6nQbXQCyYHHo4zoUoeIXhpCrSl7BAW1nv5EFL8stT1V+TQVXGZca5A2A== + +esbuild-windows-arm64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.14.tgz#ca747ce4066d5b8a79dbe48fe6ecd92d202e5366" + integrity sha512-dCm1wTOm6HIisLanmybvRKvaXZZo4yEVrHh1dY0v582GThXJOzuXGja1HIQgV09RpSHYRL3m4KoUBL00l6SWEg== + +esbuild@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.14.tgz#3b99f20d628013c3e2ae90e67687e03f1d6eb071" + integrity sha512-aiK4ddv+uui0k52OqSHu4xxu+SzOim7Rlz4i25pMEiC8rlnGU0HJ9r+ZMfdWL5bzifg+nhnn7x4NSWTeehYblg== optionalDependencies: - esbuild-android-arm64 "0.13.4" - esbuild-darwin-64 "0.13.4" - esbuild-darwin-arm64 "0.13.4" - esbuild-freebsd-64 "0.13.4" - esbuild-freebsd-arm64 "0.13.4" - esbuild-linux-32 "0.13.4" - esbuild-linux-64 "0.13.4" - esbuild-linux-arm "0.13.4" - esbuild-linux-arm64 "0.13.4" - esbuild-linux-mips64le "0.13.4" - esbuild-linux-ppc64le "0.13.4" - esbuild-openbsd-64 "0.13.4" - esbuild-sunos-64 "0.13.4" - esbuild-windows-32 "0.13.4" - esbuild-windows-64 "0.13.4" - esbuild-windows-arm64 "0.13.4" + esbuild-android-arm64 "0.14.14" + esbuild-darwin-64 "0.14.14" + esbuild-darwin-arm64 "0.14.14" + esbuild-freebsd-64 "0.14.14" + esbuild-freebsd-arm64 "0.14.14" + esbuild-linux-32 "0.14.14" + esbuild-linux-64 "0.14.14" + esbuild-linux-arm "0.14.14" + esbuild-linux-arm64 "0.14.14" + esbuild-linux-mips64le "0.14.14" + esbuild-linux-ppc64le "0.14.14" + esbuild-linux-s390x "0.14.14" + esbuild-netbsd-64 "0.14.14" + esbuild-openbsd-64 "0.14.14" + esbuild-sunos-64 "0.14.14" + esbuild-windows-32 "0.14.14" + esbuild-windows-64 "0.14.14" + esbuild-windows-arm64 "0.14.14" escalade@^3.1.1: version "3.1.1" @@ -3641,24 +3730,26 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - express@^4.17.1: version "4.17.1" resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" @@ -3695,21 +3786,6 @@ express@^4.17.1: utils-merge "1.0.1" vary "~1.1.2" -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - extend@^3.0.0, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" @@ -3724,20 +3800,6 @@ external-editor@^3.0.3: iconv-lite "^0.4.24" tmp "^0.0.33" -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -3748,15 +3810,15 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= -fast-deep-equal@^3.1.1: +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.1.1, fast-glob@^3.2.5: - version "3.2.7" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" - integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== +fast-glob@^3.2.7, fast-glob@^3.2.9: + version "3.2.11" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" + integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -3795,21 +3857,6 @@ figures@^3.0.0: dependencies: escape-string-regexp "^1.0.5" -file-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -3830,15 +3877,6 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-cache-dir@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" - integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== - dependencies: - commondir "^1.0.1" - make-dir "^3.0.2" - pkg-dir "^4.1.0" - find-cache-dir@^3.3.1: version "3.3.2" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" @@ -3855,7 +3893,7 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" -find-up@^4.0.0: +find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== @@ -3863,21 +3901,11 @@ find-up@^4.0.0: locate-path "^5.0.0" path-exists "^4.0.0" -flatten@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" - integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== - follow-redirects@^1.0.0: version "1.14.4" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379" integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g== -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -3911,12 +3939,10 @@ forwarded@0.2.0: resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= - dependencies: - map-cache "^0.2.2" +fraction.js@^4.1.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.3.tgz#be65b0f20762ef27e1e793860bc2dfb716e99e65" + integrity sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg== fresh@0.5.2: version "0.5.2" @@ -3940,14 +3966,6 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@^1.2.7: - version "1.2.13" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" - integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== - dependencies: - bindings "^1.5.0" - nan "^2.12.1" - fsevents@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" @@ -3969,19 +3987,20 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= +gauge@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.1.tgz#82984bc08c90357d60b0a46c03a296beb1affec4" + integrity sha512-zJ4jePUHR8cceduZ53b6temRalyGpkC2Kc2r3ecNphmL+uWNoJ3YcOcUjpbG6WwoE/Ef6/+aEZz63neI2WIa1Q== dependencies: - aproba "^1.0.3" + ansi-regex "^5.0.1" + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.2" console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" + has-unicode "^2.0.1" signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.2" gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: version "1.0.0-beta.2" @@ -3993,7 +4012,7 @@ get-caller-file@^1.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== -get-caller-file@^2.0.1, get-caller-file@^2.0.5: +get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== @@ -4007,6 +4026,11 @@ get-intrinsic@^1.0.2: has "^1.0.3" has-symbols "^1.0.1" +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + get-stream@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -4014,10 +4038,10 @@ get-stream@^4.0.0: dependencies: pump "^3.0.0" -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== getpass@^0.1.1: version "0.1.7" @@ -4026,14 +4050,6 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -4041,7 +4057,7 @@ glob-parent@^5.1.2, glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" -glob-parent@^6.0.0: +glob-parent@^6.0.1: version "6.0.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== @@ -4053,19 +4069,7 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@7.1.7: - version "7.1.7" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" - integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.3, glob@^7.0.6, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: +glob@7.2.0, glob@^7.0.3, glob@^7.0.6, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -4082,18 +4086,30 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globby@^11.0.3: - version "11.0.4" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" - integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== +globby@^11.0.1: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: array-union "^2.1.0" dir-glob "^3.0.1" - fast-glob "^3.1.1" - ignore "^5.1.4" - merge2 "^1.3.0" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" slash "^3.0.0" +globby@^12.0.2: + version "12.2.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-12.2.0.tgz#2ab8046b4fba4ff6eede835b29f678f90e3d3c22" + integrity sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA== + dependencies: + array-union "^3.0.1" + dir-glob "^3.0.1" + fast-glob "^3.2.7" + ignore "^5.1.9" + merge2 "^1.4.1" + slash "^4.0.0" + globby@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" @@ -4106,22 +4122,16 @@ globby@^5.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" -globby@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" - integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw= - dependencies: - array-union "^1.0.1" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.2.3, graceful-fs@^4.2.4: +graceful-fs@^4.1.2, graceful-fs@^4.2.4: version "4.2.8" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== +graceful-fs@^4.2.6, graceful-fs@^4.2.9: + version "4.2.9" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" + integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== + handle-thing@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" @@ -4169,42 +4179,11 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" -has-unicode@^2.0.0: +has-unicode@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -4243,10 +4222,10 @@ hpack.js@^2.1.6: readable-stream "^2.0.1" wbuf "^1.1.0" -html-entities@^1.3.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.4.0.tgz#cfbd1b01d2afaf9adca1b10ae7dffab98c71d2dc" - integrity sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA== +html-entities@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.2.tgz#760b404685cb1d794e4f4b744332e3b00dcfe488" + integrity sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ== http-cache-semantics@^4.1.0: version "4.1.0" @@ -4304,17 +4283,27 @@ http-proxy-agent@^4.0.1: agent-base "6" debug "4" -http-proxy-middleware@0.19.1: - version "0.19.1" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" - integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q== +http-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" + integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== dependencies: - http-proxy "^1.17.0" - is-glob "^4.0.0" - lodash "^4.17.11" - micromatch "^3.1.10" + "@tootallnate/once" "2" + agent-base "6" + debug "4" -http-proxy@^1.17.0: +http-proxy-middleware@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.3.tgz#5df04f69a89f530c2284cd71eeaa51ba52243289" + integrity sha512-1bloEwnrHMnCoO/Gcwbz7eSVvW50KPES01PecpagI+YLNLci4AcuKJrujW4Mc3sBLpFxMSlsLNHS5Nl/lvrTPA== + dependencies: + "@types/http-proxy" "^1.17.8" + http-proxy "^1.18.1" + is-glob "^4.0.1" + is-plain-obj "^3.0.0" + micromatch "^4.0.2" + +http-proxy@^1.18.1: version "1.18.1" resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== @@ -4348,6 +4337,11 @@ https-proxy-agent@^2.2.1: agent-base "^4.3.0" debug "^3.1.0" +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + humanize-ms@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" @@ -4362,7 +4356,7 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4: dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@^0.6.2: +iconv-lite@^0.6.2, iconv-lite@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== @@ -4379,17 +4373,17 @@ ieee754@^1.1.13: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ignore-walk@^3.0.3: - version "3.0.4" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.4.tgz#c9a09f69b7c7b479a5d74ac1a3c0d4236d2a6335" - integrity sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ== +ignore-walk@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-4.0.1.tgz#fc840e8346cf88a3a9380c5b17933cd8f4d39fa3" + integrity sha512-rzDQLaW4jQbh2YrOFlJdCtX8qgJTehFRYiUB2r1osqTeDzV/3+Jh8fz1oAPzUThf3iku8Ds4IDqawI5d8mUiQw== dependencies: minimatch "^3.0.4" -ignore@^5.1.4: - version "5.1.8" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" - integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== +ignore@^5.1.9, ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== image-size@~0.5.0: version "0.5.5" @@ -4406,6 +4400,11 @@ immer@^9.0.6: resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.6.tgz#7a96bf2674d06c8143e327cbf73539388ddf1a73" integrity sha512-G95ivKpy+EvVAnAab4fVa4YGYn24J1SpEktnJX7JJ45Bd7xqME/SCplFzYFmTbrkwZbQ4xJK1xMTUYBkN6pWsQ== +immutable@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0.tgz#b86f78de6adef3608395efb269a91462797e2c23" + integrity sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw== + import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -4414,14 +4413,6 @@ import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" -import-local@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" - integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== - dependencies: - pkg-dir "^3.0.0" - resolve-cwd "^2.0.0" - imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -4432,11 +4423,6 @@ indent-string@^4.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== -indexes-of@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" - integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= - infer-owner@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" @@ -4470,10 +4456,10 @@ ini@^1.3.4: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -inquirer@8.1.2: - version "8.1.2" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.1.2.tgz#65b204d2cd7fb63400edd925dfe428bafd422e3d" - integrity sha512-DHLKJwLPNgkfwNmsuEUKSejJFbkv0FMO9SMiQbjI3n5NQuCrSIBqP66ggqyz2a6t2qEolKrMjhQ3+W/xXgUQ+Q== +inquirer@8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.0.tgz#f44f008dd344bbfc4b30031f45d984e034a3ac3a" + integrity sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ== dependencies: ansi-escapes "^4.2.1" chalk "^4.1.1" @@ -4483,59 +4469,32 @@ inquirer@8.1.2: figures "^3.0.0" lodash "^4.17.21" mute-stream "0.0.8" - ora "^5.3.0" + ora "^5.4.1" run-async "^2.4.0" rxjs "^7.2.0" string-width "^4.1.0" strip-ansi "^6.0.0" through "^2.3.6" -internal-ip@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" - integrity sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg== - dependencies: - default-gateway "^4.2.0" - ipaddr.js "^1.9.0" - invert-kv@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== -ip-regex@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" - integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= - ip@^1.1.0, ip@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= -ipaddr.js@1.9.1, ipaddr.js@^1.9.0: +ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== -is-absolute-url@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" - integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== - -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" +ipaddr.js@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" + integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== is-arguments@^1.0.4: version "1.1.1" @@ -4550,13 +4509,6 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -4564,11 +4516,6 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - is-core-module@^2.2.0: version "2.7.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.7.0.tgz#3c0ef7d31b4acfc574f80c58409d568a836848e3" @@ -4576,19 +4523,12 @@ is-core-module@^2.2.0: dependencies: has "^1.0.3" -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= +is-core-module@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" + integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" + has "^1.0.3" is-date-object@^1.0.1: version "1.0.5" @@ -4597,42 +4537,12 @@ is-date-object@^1.0.1: dependencies: has-tostringtag "^1.0.0" -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - is-docker@^2.0.0, is-docker@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^2.1.0, is-extglob@^2.1.1: +is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= @@ -4654,14 +4564,7 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: +is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -4678,13 +4581,6 @@ is-lambda@^1.0.1: resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" integrity sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU= -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -4695,7 +4591,7 @@ is-path-cwd@^1.0.0: resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0= -is-path-cwd@^2.0.0: +is-path-cwd@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== @@ -4707,13 +4603,6 @@ is-path-in-cwd@^1.0.0: dependencies: is-path-inside "^1.0.0" -is-path-in-cwd@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" - integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== - dependencies: - is-path-inside "^2.1.0" - is-path-inside@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" @@ -4721,14 +4610,17 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" -is-path-inside@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" - integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== - dependencies: - path-is-inside "^1.0.2" +is-path-inside@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== -is-plain-object@^2.0.3, is-plain-object@^2.0.4: +is-plain-obj@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" + integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== + +is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== @@ -4743,16 +4635,16 @@ is-regex@^1.0.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-resolvable@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== - is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -4768,16 +4660,6 @@ is-what@^3.12.0: resolved "https://registry.yarnpkg.com/is-what/-/is-what-3.14.1.tgz#e1222f46ddda85dead0fd1c9df131760e77755c1" integrity sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA== -is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= - is-wsl@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" @@ -4785,29 +4667,17 @@ is-wsl@^2.2.0: dependencies: is-docker "^2.0.0" -isarray@1.0.0, isarray@~1.0.0: +isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= -isarray@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: +isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= @@ -4817,19 +4687,20 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= -istanbul-lib-coverage@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.2.tgz#36786d4d82aad2ea5911007e255e2da6b5f80d86" - integrity sha512-o5+eTUYzCJ11/+JhW5/FUCdfsdoYVdQ/8I/OveE2XsjehYn5DdeSnNQAbjYaO8gQ6hvGTN6GM6ddQqpTVG5j8g== +istanbul-lib-coverage@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== -istanbul-lib-instrument@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" - integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== +istanbul-lib-instrument@^5.0.4: + version "5.1.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz#7b49198b657b27a730b8e9cb601f1e1bff24c59a" + integrity sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q== dependencies: - "@babel/core" "^7.7.5" + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.0.0" + istanbul-lib-coverage "^3.2.0" semver "^6.3.0" jasmine-core@~2.8.0: @@ -4851,7 +4722,7 @@ jasminewd2@^2.1.0: resolved "https://registry.yarnpkg.com/jasminewd2/-/jasminewd2-2.2.0.tgz#e37cf0b17f199cce23bea71b2039395246b4ec4e" integrity sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4= -jest-worker@^27.0.2, jest-worker@^27.0.6: +jest-worker@^27.0.6: version "27.2.5" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.2.5.tgz#ed42865661959488aa020e8a325df010597c36d4" integrity sha512-HTjEPZtcNKZ4LnhSp02NEH4vE+5OpJ0EsOWYvGQpHgUMLngydESAAMH5Wd/asPf29+XUDQZszxpLg1BkIIA2aw== @@ -4923,11 +4794,6 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json3@^3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" - integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== - json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -4979,31 +4845,7 @@ karma-source-map-support@1.4.0: dependencies: source-map-support "^0.5.5" -killable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" - integrity sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg== - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2: +kind-of@^6.0.2: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== @@ -5013,6 +4855,11 @@ klona@^2.0.4: resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0" integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA== +klona@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" + integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== + lcid@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" @@ -5020,21 +4867,21 @@ lcid@^2.0.0: dependencies: invert-kv "^2.0.0" -less-loader@10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-10.0.1.tgz#c05aaba68d00400820275f21c2ad87cb9fa9923f" - integrity sha512-Crln//HpW9M5CbtdfWm3IO66Cvx1WhZQvNybXgfB2dD/6Sav9ppw+IWqs/FQKPBFO4B6X0X28Z0WNznshgwUzA== +less-loader@10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-10.2.0.tgz#97286d8797dc3dc05b1d16b0ecec5f968bdd4e32" + integrity sha512-AV5KHWvCezW27GT90WATaDnfXBv99llDbtaj4bshq6DvAihMdNjaPDcUMa6EXKLRF+P2opFenJp89BXg91XLYg== dependencies: klona "^2.0.4" -less@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/less/-/less-4.1.1.tgz#15bf253a9939791dc690888c3ff424f3e6c7edba" - integrity sha512-w09o8tZFPThBscl5d0Ggp3RcrKIouBoQscnOMgFH3n5V3kN/CXGHNfCkRPtxJk6nKryDXaV9aHLK55RXuH4sAw== +less@4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/less/-/less-4.1.2.tgz#6099ee584999750c2624b65f80145f8674e4b4b0" + integrity sha512-EoQp/Et7OSOVu0aJknJOtlXZsnr8XE8KwuzTHOLeVSEx8pVWUICc8Q0VYRHgzyjX78nMEyC/oztWFbgyhtNfDA== dependencies: copy-anything "^2.0.1" parse-node-version "^1.0.1" - tslib "^1.10.0" + tslib "^2.3.0" optionalDependencies: errno "^0.1.1" graceful-fs "^4.1.2" @@ -5044,13 +4891,12 @@ less@4.1.1: needle "^2.5.2" source-map "~0.6.0" -license-webpack-plugin@2.3.20: - version "2.3.20" - resolved "https://registry.yarnpkg.com/license-webpack-plugin/-/license-webpack-plugin-2.3.20.tgz#f51fb674ca31519dbedbe1c7aabc036e5a7f2858" - integrity sha512-AHVueg9clOKACSHkhmEI+PCC9x8+qsQVuKECZD3ETxETK5h/PCv5/MUzyG1gm8OMcip/s1tcNxqo9Qb7WhjGsg== +license-webpack-plugin@4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/license-webpack-plugin/-/license-webpack-plugin-4.0.1.tgz#957930fa595f5b65aa0b21bfd2c19644486f3d9f" + integrity sha512-SQum9mg3BgnY5BK+2KYl4W7pk9b26Q8tW2lTsO6tidD0/Ds9ksdXvp3ip2s9LqDjj5gtBMyWRfOPZptWj4PfCg== dependencies: - "@types/webpack-sources" "^0.1.5" - webpack-sources "^1.2.0" + webpack-sources "^3.0.0" lie@~3.3.0: version "3.3.0" @@ -5059,11 +4905,6 @@ lie@~3.3.0: dependencies: immediate "~3.0.5" -lilconfig@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.3.tgz#68f3005e921dafbd2a2afb48379986aa6d2579fd" - integrity sha512-EHKqr/+ZvdKCifpNrJCKxBTgk5XupZA3y/aCPY9mxfgBzmgh93Mt/WqjjQ38oMxXuvDokaKiM3lAgvSH2sjtHg== - lines-and-columns@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" @@ -5074,14 +4915,10 @@ loader-runner@^4.2.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== -loader-utils@2.0.0, loader-utils@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" - integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^2.1.2" +loader-utils@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.0.tgz#bcecc51a7898bee7473d4bc6b845b23af8304d4f" + integrity sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ== loader-utils@^1.0.2, loader-utils@^1.4.0: version "1.4.0" @@ -5092,6 +4929,15 @@ loader-utils@^1.0.2, loader-utils@^1.4.0: emojis-list "^3.0.0" json5 "^1.0.1" +loader-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" + integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -5112,17 +4958,7 @@ lodash.debounce@^4.0.8: resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= -lodash.memoize@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - -lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= - -lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.21: +lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -5135,11 +4971,6 @@ log-symbols@^4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" -loglevel@^1.6.8: - version "1.7.1" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197" - integrity sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw== - lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -5147,6 +4978,11 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +lru-cache@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.3.1.tgz#7702e80694ec2bf19865567a469f2b081fcf53f5" + integrity sha512-nX1x4qUrKqwbIAhv4s9et4FIUVzNOpeY07bsjGUy8gwJrXH/wScImSQqXErmo/b2jZY2r0mohbLA9zVj7u1cNw== + luxon@^1.10.0, luxon@^1.21.3: version "1.28.0" resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.28.0.tgz#e7f96daad3938c06a62de0fb027115d251251fbf" @@ -5179,7 +5015,29 @@ make-error@^1.1.1: resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== -make-fetch-happen@^9.0.1: +make-fetch-happen@^10.0.1: + version "10.0.3" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-10.0.3.tgz#94bbe675cf62a811dbab59668052388a078beaf2" + integrity sha512-CzarPHynPpHjhF5in/YapnO44rSZeYX5VCMfdXa99+gLwpbfFLh20CWa6dP/taV9Net9PWJwXNKtp/4ZTCQnag== + dependencies: + agentkeepalive "^4.2.0" + cacache "^15.3.0" + http-cache-semantics "^4.1.0" + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.0" + is-lambda "^1.0.1" + lru-cache "^7.3.1" + minipass "^3.1.6" + minipass-collect "^1.0.2" + minipass-fetch "^1.4.1" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + negotiator "^0.6.3" + promise-retry "^2.0.1" + socks-proxy-agent "^6.1.1" + ssri "^8.0.1" + +make-fetch-happen@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz#53085a09e7971433e6765f7971bf63f4e05cb968" integrity sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg== @@ -5201,30 +5059,13 @@ make-fetch-happen@^9.0.1: socks-proxy-agent "^6.0.0" ssri "^8.0.0" -map-age-cleaner@^0.1.1, map-age-cleaner@^0.1.3: +map-age-cleaner@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== dependencies: p-defer "^1.0.0" -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= - dependencies: - object-visit "^1.0.0" - -mdn-data@2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" - integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== - media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -5239,14 +5080,6 @@ mem@^4.0.0: mimic-fn "^2.0.0" p-is-promise "^2.0.0" -mem@^8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/mem/-/mem-8.1.1.tgz#cf118b357c65ab7b7e0817bdf00c8062297c0122" - integrity sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA== - dependencies: - map-age-cleaner "^0.1.3" - mimic-fn "^3.1.0" - memfs@^3.2.2: version "3.3.0" resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.3.0.tgz#4da2d1fc40a04b170a56622c7164c6be2c4cbef2" @@ -5254,32 +5087,24 @@ memfs@^3.2.2: dependencies: fs-monkey "1.0.3" -memory-fs@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= +memfs@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.1.tgz#b78092f466a0dce054d63d39275b24c71d3f1305" + integrity sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw== dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" + fs-monkey "1.0.3" merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= -merge-source-map@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" - integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw== - dependencies: - source-map "^0.6.1" - merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.3.0: +merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -5289,26 +5114,7 @@ methods@^1.1.1, methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= -micromatch@^3.1.10, micromatch@^3.1.4: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - -micromatch@^4.0.4: +micromatch@^4.0.2, micromatch@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== @@ -5333,27 +5139,17 @@ mime@1.6.0, mime@^1.4.1: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.4.4: - version "2.5.2" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe" - integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg== - mimic-fn@^2.0.0, mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-fn@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74" - integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ== - -mini-css-extract-plugin@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.2.1.tgz#a44bbfc8ede9211f31474b91c4e8863bf52dd294" - integrity sha512-A0GBXpz8WIPgh2HfASJ0EeY8grd2dGxmC4R8uTujFJXZY7zFy0nvYSYW6SKCLKlz7y45BdHONfaxZQMIZpeF/w== +mini-css-extract-plugin@2.5.3: + version "2.5.3" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.3.tgz#c5c79f9b22ce9b4f164e9492267358dbe35376d9" + integrity sha512-YseMB8cs8U/KCaAGQoqYmfUuhhGW0a9p9XvWXrxVOkE3/IiISTLw4ALNt7JR5B2eYauFM+PQGSbXMDmVbR7Tfw== dependencies: - schema-utils "^3.1.0" + schema-utils "^4.0.0" minimalistic-assert@^1.0.0: version "1.0.1" @@ -5379,7 +5175,7 @@ minipass-collect@^1.0.2: dependencies: minipass "^3.0.0" -minipass-fetch@^1.3.0, minipass-fetch@^1.3.2: +minipass-fetch@^1.3.2, minipass-fetch@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-1.4.1.tgz#d75e0091daac1b0ffd7e9d41629faff7d0c1f1b6" integrity sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw== @@ -5426,7 +5222,14 @@ minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3: dependencies: yallist "^4.0.0" -minizlib@^2.0.0, minizlib@^2.1.1: +minipass@^3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee" + integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ== + dependencies: + yallist "^4.0.0" + +minizlib@^2.0.0, minizlib@^2.1.1, minizlib@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== @@ -5434,14 +5237,6 @@ minizlib@^2.0.0, minizlib@^2.1.1: minipass "^3.0.0" yallist "^4.0.0" -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - mkdirp@^0.5.1, mkdirp@^0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" @@ -5449,7 +5244,7 @@ mkdirp@^0.5.1, mkdirp@^0.5.5: dependencies: minimist "^1.2.5" -mkdirp@^1.0.3, mkdirp@^1.0.4, mkdirp@~1.0.4: +mkdirp@^1.0.3, mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -5504,37 +5299,15 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nan@^2.12.1: - version "2.15.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" - integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== - -nanocolors@^0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/nanocolors/-/nanocolors-0.1.12.tgz#8577482c58cbd7b5bb1681db4cf48f11a87fd5f6" - integrity sha512-2nMHqg1x5PU+unxX7PGY7AuYxl2qDx7PSrTRjizr8sxdd3l/3hBuWWaki62qmtYm2U5i4Z5E7GbjlyDFhs9/EQ== - -nanoid@^3.1.23, nanoid@^3.1.28: +nanoid@^3.1.28: version "3.1.30" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.30.tgz#63f93cc548d2a113dc5dfbc63bfa09e2b9b64362" integrity sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ== -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" +nanoid@^3.1.30, nanoid@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.0.tgz#5906f776fd886c66c24f3653e0c46fcb1d4ad6b0" + integrity sha512-JzxqqT5u/x+/KOFSd7JP15DOo9nOoHpx6DYatqIHUW2+flybkm+mdcraotSQR5WcnZr+qhGVh8Ted0KdfSMxlg== needle@^2.5.2: version "2.9.1" @@ -5550,6 +5323,11 @@ negotiator@0.6.2, negotiator@^0.6.2: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== +negotiator@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" @@ -5583,10 +5361,10 @@ ngx-moment@^3.0.1: dependencies: tslib "^1.9.0" -ngx-order-pipe@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ngx-order-pipe/-/ngx-order-pipe-2.1.1.tgz#981b7ff2fac20bc88a1e9922527e2e61da0ff4f1" - integrity sha512-yBaG0uYWsXBlmAuCYvBedKxl3kRUSXNXsMrD0m2E4tBA8I9TJSomucp5SHFlyfMQK8V6pjRGdz17Sjb9YwLhSg== +ngx-order-pipe@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ngx-order-pipe/-/ngx-order-pipe-2.2.0.tgz#14ab50dfe0a679e5216138ff9a0820a83173a4fe" + integrity sha512-fym4A3j0XMqETskCm0tHUHQWCgB1p1MrIstFA3jCClJqNU9KjtQh/AE4C7srUkz9U3HIBIAN9D3ty2L9l/jvmA== dependencies: tslib "^2.0.0" @@ -5615,30 +5393,30 @@ node-addon-api@^3.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== -node-forge@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" - integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== +node-forge@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.2.1.tgz#82794919071ef2eb5c509293325cec8afd0fd53c" + integrity sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w== node-gyp-build@^4.2.2: version "4.3.0" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q== -node-gyp@^7.1.0: - version "7.1.2" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-7.1.2.tgz#21a810aebb187120251c3bcec979af1587b188ae" - integrity sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ== +node-gyp@^8.2.0: + version "8.4.1" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-8.4.1.tgz#3d49308fc31f768180957d6b5746845fbd429937" + integrity sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w== dependencies: env-paths "^2.2.0" glob "^7.1.4" - graceful-fs "^4.2.3" + graceful-fs "^4.2.6" + make-fetch-happen "^9.1.0" nopt "^5.0.0" - npmlog "^4.1.2" - request "^2.88.2" + npmlog "^6.0.0" rimraf "^3.0.2" - semver "^7.3.2" - tar "^6.0.2" + semver "^7.3.5" + tar "^6.1.2" which "^2.0.2" node-releases@^2.0.0: @@ -5646,6 +5424,11 @@ node-releases@^2.0.0: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.0.tgz#67dc74903100a7deb044037b8a2e5f453bb05400" integrity sha512-aA87l0flFYMzCHpTM3DERFSYxc6lv/BltdbRTOMZuxZ0cwZCD3mejE5n9vLhSJCN++/eOqr77G1IO5uXxlQYWA== +node-releases@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01" + integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg== + nopt@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" @@ -5653,13 +5436,6 @@ nopt@^5.0.0: dependencies: abbrev "1" -normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -5670,11 +5446,6 @@ normalize-range@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= -normalize-url@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" - integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== - npm-bundled@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.2.tgz#944c78789bd739035b70baa2ca5cc32b8d860bc1" @@ -5694,7 +5465,7 @@ npm-normalize-package-bin@^1.0.1: resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== -npm-package-arg@8.1.5, npm-package-arg@^8.0.0, npm-package-arg@^8.0.1, npm-package-arg@^8.1.2: +npm-package-arg@8.1.5, npm-package-arg@^8.0.1, npm-package-arg@^8.1.2, npm-package-arg@^8.1.5: version "8.1.5" resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-8.1.5.tgz#3369b2d5fe8fdc674baa7f1786514ddc15466e44" integrity sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q== @@ -5703,13 +5474,13 @@ npm-package-arg@8.1.5, npm-package-arg@^8.0.0, npm-package-arg@^8.0.1, npm-packa semver "^7.3.4" validate-npm-package-name "^3.0.0" -npm-packlist@^2.1.4: - version "2.2.2" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-2.2.2.tgz#076b97293fa620f632833186a7a8f65aaa6148c8" - integrity sha512-Jt01acDvJRhJGthnUJVF/w6gumWOZxO7IkpY/lsX9//zqQgnF7OJaxgQXcerd4uQOLu7W5bkb4mChL9mdfm+Zg== +npm-packlist@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-3.0.0.tgz#0370df5cfc2fcc8f79b8f42b37798dd9ee32c2a9" + integrity sha512-L/cbzmutAwII5glUcf2DBRNY/d0TFd4e/FnaZigJV6JD85RHZXJFGwCndjMWiiViiWSsWt3tiOLpI3ByTnIdFQ== dependencies: glob "^7.1.6" - ignore-walk "^3.0.3" + ignore-walk "^4.0.1" npm-bundled "^1.1.1" npm-normalize-package-bin "^1.0.1" @@ -5723,17 +5494,17 @@ npm-pick-manifest@6.1.1, npm-pick-manifest@^6.0.0, npm-pick-manifest@^6.1.1: npm-package-arg "^8.1.2" semver "^7.3.4" -npm-registry-fetch@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-11.0.0.tgz#68c1bb810c46542760d62a6a965f85a702d43a76" - integrity sha512-jmlgSxoDNuhAtxUIG6pVwwtz840i994dL14FoNVZisrmZW5kWd63IUTNv1m/hyRSGSqWjCUp/YZlS1BJyNp9XA== +npm-registry-fetch@^12.0.0: + version "12.0.2" + resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-12.0.2.tgz#ae583bb3c902a60dae43675b5e33b5b1f6159f1e" + integrity sha512-Df5QT3RaJnXYuOwtXBXS9BWs+tHH2olvkCLh6jcR/b/u3DvPMlp3J0TvvYwplPKxHMOwfg287PYih9QqaVFoKA== dependencies: - make-fetch-happen "^9.0.1" - minipass "^3.1.3" - minipass-fetch "^1.3.0" + make-fetch-happen "^10.0.1" + minipass "^3.1.6" + minipass-fetch "^1.4.1" minipass-json-stream "^1.0.1" - minizlib "^2.0.0" - npm-package-arg "^8.0.0" + minizlib "^2.1.2" + npm-package-arg "^8.1.5" npm-run-path@^2.0.0: version "2.0.2" @@ -5742,28 +5513,30 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -npmlog@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" + path-key "^3.0.0" -nth-check@^2.0.0: +npmlog@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.1.tgz#06f1344a174c06e8de9c6c70834cfba2964bba17" + integrity sha512-BTHDvY6nrRHuRfyjt1MAufLxYdVXZfd099H4+i1f0lPywNQyI4foeNXJRObB/uy+TYqUW0vAD9gbdSOXPst7Eg== + dependencies: + are-we-there-yet "^3.0.0" + console-control-strings "^1.1.0" + gauge "^4.0.0" + set-blocking "^2.0.0" + +nth-check@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2" integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w== dependencies: boolbase "^1.0.0" -num2fraction@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" - integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= - number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" @@ -5774,20 +5547,11 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.0.1, object-assign@^4.1.0: +object-assign@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - object-inspect@^1.9.0: version "1.11.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" @@ -5806,13 +5570,6 @@ object-keys@^1.0.12, object-keys@^1.1.1: resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= - dependencies: - isobject "^3.0.0" - object.assign@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" @@ -5823,13 +5580,6 @@ object.assign@^4.1.0: has-symbols "^1.0.1" object-keys "^1.1.1" -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= - dependencies: - isobject "^3.0.1" - obuf@^1.0.0, obuf@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" @@ -5854,17 +5604,17 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^5.1.0: +onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== dependencies: mimic-fn "^2.1.0" -open@8.2.1: - version "8.2.1" - resolved "https://registry.yarnpkg.com/open/-/open-8.2.1.tgz#82de42da0ccbf429bc12d099dad2e0975e14e8af" - integrity sha512-rXILpcQlkF/QuFez2BJDf3GsqpjGKbkUUToAIGo9A0Q6ZkoSGogZJulrUdwRkrAsoQvoZsrjCYt8+zblOk7JQQ== +open@8.4.0, open@^8.0.9: + version "8.4.0" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" + integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q== dependencies: define-lazy-prop "^2.0.0" is-docker "^2.1.1" @@ -5875,14 +5625,7 @@ opencollective-postinstall@^2.0.2: resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259" integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q== -opn@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" - integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== - dependencies: - is-wsl "^1.1.0" - -ora@5.4.1, ora@^5.3.0: +ora@5.4.1, ora@^5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== @@ -5940,7 +5683,7 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.2, p-limit@^3.1.0: +p-limit@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -5961,11 +5704,6 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" -p-map@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" - integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== - p-map@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" @@ -5973,27 +5711,28 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" -p-retry@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328" - integrity sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w== +p-retry@^4.5.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.1.tgz#8fcddd5cdf7a67a0911a9cf2ef0e5df7f602316c" + integrity sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA== dependencies: - retry "^0.12.0" + "@types/retry" "^0.12.0" + retry "^0.13.1" p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -pacote@11.3.5: - version "11.3.5" - resolved "https://registry.yarnpkg.com/pacote/-/pacote-11.3.5.tgz#73cf1fc3772b533f575e39efa96c50be8c3dc9d2" - integrity sha512-fT375Yczn4zi+6Hkk2TBe1x1sP8FgFsEIZ2/iWaXY2r/NkhDJfxbcn5paz1+RTFCyNf+dPnaoBDJoAxXSU8Bkg== +pacote@12.0.3: + version "12.0.3" + resolved "https://registry.yarnpkg.com/pacote/-/pacote-12.0.3.tgz#b6f25868deb810e7e0ddf001be88da2bcaca57c7" + integrity sha512-CdYEl03JDrRO3x18uHjBYA9TyoW8gy+ThVcypcDkxPtKlw76e4ejhYB6i9lJ+/cebbjpqPW/CijjqxwDTts8Ow== dependencies: "@npmcli/git" "^2.1.0" "@npmcli/installed-package-contents" "^1.0.6" "@npmcli/promise-spawn" "^1.2.0" - "@npmcli/run-script" "^1.8.2" + "@npmcli/run-script" "^2.0.0" cacache "^15.0.5" chownr "^2.0.0" fs-minipass "^2.1.0" @@ -6001,9 +5740,9 @@ pacote@11.3.5: minipass "^3.1.3" mkdirp "^1.0.3" npm-package-arg "^8.0.1" - npm-packlist "^2.1.4" + npm-packlist "^3.0.0" npm-pick-manifest "^6.0.0" - npm-registry-fetch "^11.0.0" + npm-registry-fetch "^12.0.0" promise-retry "^2.0.1" read-package-json-fast "^2.0.1" rimraf "^3.0.2" @@ -6074,16 +5813,6 @@ parseurl@~1.3.2, parseurl@~1.3.3: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -6099,7 +5828,7 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-is-inside@^1.0.1, path-is-inside@^1.0.2: +path-is-inside@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= @@ -6109,7 +5838,12 @@ path-key@^2.0.0, path-key@^2.0.1: resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= -path-parse@^1.0.6: +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.6, path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== @@ -6166,10 +5900,10 @@ pinkie@^2.0.0: resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= -piscina@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/piscina/-/piscina-3.1.0.tgz#2333636865b6cb69c5a370bbc499a98cabcf3e04" - integrity sha512-KTW4sjsCD34MHrUbx9eAAbuUSpVj407hQSgk/6Epkg0pbRBmv4a3UX7Sr8wxm9xYqQLnsN4mFOjqGDzHAdgKQg== +piscina@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/piscina/-/piscina-3.2.0.tgz#f5a1dde0c05567775690cccefe59d9223924d154" + integrity sha512-yn/jMdHRw+q2ZJhFhyqsmANcbF6V2QwmD84c6xRau+QpQOmtrBCoRGdvTfeuFDYXB5W2m6MfLkjkvQa9lUSmIA== dependencies: eventemitter-asyncresource "^1.0.0" hdr-histogram-js "^2.0.1" @@ -6177,13 +5911,6 @@ piscina@3.1.0: optionalDependencies: nice-napi "^1.0.2" -pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== - dependencies: - find-up "^3.0.0" - pkg-dir@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" @@ -6191,17 +5918,17 @@ pkg-dir@^4.1.0: dependencies: find-up "^4.0.0" -pngjs@^3.3.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" - integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== +pngjs@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb" + integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw== popper.js@^1.14.3: version "1.16.1" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== -portfinder@^1.0.26: +portfinder@^1.0.28: version "1.0.28" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== @@ -6210,188 +5937,105 @@ portfinder@^1.0.26: debug "^3.1.1" mkdirp "^0.5.5" -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - -postcss-attribute-case-insensitive@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz#d93e46b504589e94ac7277b0463226c68041a880" - integrity sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA== +postcss-attribute-case-insensitive@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.0.tgz#39cbf6babf3ded1e4abf37d09d6eda21c644105c" + integrity sha512-b4g9eagFGq9T5SWX4+USfVyjIb3liPnjhHHRMP7FMB2kFVpYyfEscV0wP3eaXhKlcHKUut8lt5BGoeylWA/dBQ== dependencies: - postcss "^7.0.2" postcss-selector-parser "^6.0.2" -postcss-calc@^8.0.0: +postcss-color-functional-notation@^4.2.1: + version "4.2.2" + resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.2.tgz#f59ccaeb4ee78f1b32987d43df146109cc743073" + integrity sha512-DXVtwUhIk4f49KK5EGuEdgx4Gnyj6+t2jBSEmxvpIK9QI40tWrpS2Pua8Q7iIZWBrki2QOaeUdEaLPPa91K0RQ== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-color-hex-alpha@^8.0.2: + version "8.0.3" + resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.3.tgz#61a0fd151d28b128aa6a8a21a2dad24eebb34d52" + integrity sha512-fESawWJCrBV035DcbKRPAVmy21LpoyiXdPTuHUfWJ14ZRjY7Y7PA6P4g8z6LQGYhU1WAxkTxjIjurXzoe68Glw== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-color-rebeccapurple@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.0.2.tgz#5d397039424a58a9ca628762eb0b88a61a66e079" + integrity sha512-SFc3MaocHaQ6k3oZaFwH8io6MdypkUtEy/eXzXEB1vEQlO3S3oDc/FSZA8AsS04Z25RirQhlDlHLh3dn7XewWw== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-custom-media@^8.0.0: version "8.0.0" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.0.0.tgz#a05b87aacd132740a5db09462a3612453e5df90a" - integrity sha512-5NglwDrcbiy8XXfPM11F3HeC6hoT9W7GUH/Zi5U/p7u3Irv4rHhdDcIZwG0llHXV4ftsBjpfWMXAnXNl4lnt8g== - dependencies: - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.0.2" + resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-8.0.0.tgz#1be6aff8be7dc9bf1fe014bde3b71b92bb4552f1" + integrity sha512-FvO2GzMUaTN0t1fBULDeIvxr5IvbDXcIatt6pnJghc736nqNgsGao5NT+5+WVLAQiTt6Cb3YUms0jiPaXhL//g== -postcss-color-functional-notation@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz#5efd37a88fbabeb00a2966d1e53d98ced93f74e0" - integrity sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g== +postcss-custom-properties@^12.1.2: + version "12.1.4" + resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-12.1.4.tgz#e3d8a8000f28094453b836dff5132385f2862285" + integrity sha512-i6AytuTCoDLJkWN/MtAIGriJz3j7UX6bV7Z5t+KgFz+dwZS15/mlTJY1S0kRizlk6ba0V8u8hN50Fz5Nm7tdZw== dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" + postcss-value-parser "^4.2.0" -postcss-color-gray@^5.0.0: +postcss-custom-selectors@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-6.0.0.tgz#022839e41fbf71c47ae6e316cb0e6213012df5ef" + integrity sha512-/1iyBhz/W8jUepjGyu7V1OPcGbc636snN1yXEQCinb6Bwt7KxsiU7/bLQlp8GwAXzCh7cobBU5odNn/2zQWR8Q== + dependencies: + postcss-selector-parser "^6.0.4" + +postcss-dir-pseudo-class@^6.0.3: + version "6.0.4" + resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.4.tgz#9afe49ea631f0cb36fa0076e7c2feb4e7e3f049c" + integrity sha512-I8epwGy5ftdzNWEYok9VjW9whC4xnelAtbajGv4adql4FIF09rnrxnA9Y8xSHN47y7gqFIv10C5+ImsLeJpKBw== + dependencies: + postcss-selector-parser "^6.0.9" + +postcss-double-position-gradients@^3.0.4: + version "3.1.0" + resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.0.tgz#a8614fb3a2a4b8877bffb8961b770e00322bbad1" + integrity sha512-oz73I08yMN3oxjj0s8mED1rG+uOYoK3H8N9RjQofyg52KBRNmePJKg3fVwTpL2U5ZFbCzXoZBsUD/CvZdlqE4Q== + dependencies: + "@csstools/postcss-progressive-custom-properties" "^1.1.0" + postcss-value-parser "^4.2.0" + +postcss-env-function@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-4.0.5.tgz#b9614d50abd91e4c88a114644a9766880dabe393" + integrity sha512-gPUJc71ji9XKyl0WSzAalBeEA/89kU+XpffpPxSaaaZ1c48OL36r1Ep5R6+9XAPkIiDlSvVAwP4io12q/vTcvA== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-focus-visible@^6.0.3: + version "6.0.4" + resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz#50c9ea9afa0ee657fb75635fabad25e18d76bf9e" + integrity sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw== + dependencies: + postcss-selector-parser "^6.0.9" + +postcss-focus-within@^5.0.3: + version "5.0.4" + resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz#5b1d2ec603195f3344b716c0b75f61e44e8d2e20" + integrity sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ== + dependencies: + postcss-selector-parser "^6.0.9" + +postcss-font-variant@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz#532a31eb909f8da898ceffe296fdc1f864be8547" - integrity sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw== - dependencies: - "@csstools/convert-colors" "^1.4.0" - postcss "^7.0.5" - postcss-values-parser "^2.0.0" + resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz#efd59b4b7ea8bb06127f2d031bfbb7f24d32fa66" + integrity sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA== -postcss-color-hex-alpha@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz#a8d9ca4c39d497c9661e374b9c51899ef0f87388" - integrity sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw== - dependencies: - postcss "^7.0.14" - postcss-values-parser "^2.0.1" - -postcss-color-mod-function@^3.0.3: +postcss-gap-properties@^3.0.2: version "3.0.3" - resolved "https://registry.yarnpkg.com/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz#816ba145ac11cc3cb6baa905a75a49f903e4d31d" - integrity sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ== + resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-3.0.3.tgz#6401bb2f67d9cf255d677042928a70a915e6ba60" + integrity sha512-rPPZRLPmEKgLk/KlXMqRaNkYTUpE7YC+bOIQFN5xcu1Vp11Y4faIXv6/Jpft6FMnl6YRxZqDZG0qQOW80stzxQ== + +postcss-image-set-function@^4.0.4: + version "4.0.6" + resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-4.0.6.tgz#bcff2794efae778c09441498f40e0c77374870a9" + integrity sha512-KfdC6vg53GC+vPd2+HYzsZ6obmPqOk6HY09kttU19+Gj1nC3S3XBVEXDHxkhxTohgZqzbUb94bKXvKDnYWBm/A== dependencies: - "@csstools/convert-colors" "^1.4.0" - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-color-rebeccapurple@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz#c7a89be872bb74e45b1e3022bfe5748823e6de77" - integrity sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-colormin@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.2.0.tgz#2b620b88c0ff19683f3349f4cf9e24ebdafb2c88" - integrity sha512-+HC6GfWU3upe5/mqmxuqYZ9B2Wl4lcoUUNkoaX59nEWV4EtADCMiBqui111Bu8R8IvaZTmqmxrqOAqjbHIwXPw== - dependencies: - browserslist "^4.16.6" - caniuse-api "^3.0.0" - colord "^2.0.1" - postcss-value-parser "^4.1.0" - -postcss-convert-values@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.0.1.tgz#4ec19d6016534e30e3102fdf414e753398645232" - integrity sha512-C3zR1Do2BkKkCgC0g3sF8TS0koF2G+mN8xxayZx3f10cIRmTaAnpgpRQZjNekTZxM2ciSPoh2IWJm0VZx8NoQg== - dependencies: - postcss-value-parser "^4.1.0" - -postcss-custom-media@^7.0.8: - version "7.0.8" - resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz#fffd13ffeffad73621be5f387076a28b00294e0c" - integrity sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg== - dependencies: - postcss "^7.0.14" - -postcss-custom-properties@^8.0.11: - version "8.0.11" - resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz#2d61772d6e92f22f5e0d52602df8fae46fa30d97" - integrity sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA== - dependencies: - postcss "^7.0.17" - postcss-values-parser "^2.0.1" - -postcss-custom-selectors@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz#64858c6eb2ecff2fb41d0b28c9dd7b3db4de7fba" - integrity sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w== - dependencies: - postcss "^7.0.2" - postcss-selector-parser "^5.0.0-rc.3" - -postcss-dir-pseudo-class@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz#6e3a4177d0edb3abcc85fdb6fbb1c26dabaeaba2" - integrity sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw== - dependencies: - postcss "^7.0.2" - postcss-selector-parser "^5.0.0-rc.3" - -postcss-discard-comments@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.0.1.tgz#9eae4b747cf760d31f2447c27f0619d5718901fe" - integrity sha512-lgZBPTDvWrbAYY1v5GYEv8fEO/WhKOu/hmZqmCYfrpD6eyDWWzAOsl2rF29lpvziKO02Gc5GJQtlpkTmakwOWg== - -postcss-discard-duplicates@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.1.tgz#68f7cc6458fe6bab2e46c9f55ae52869f680e66d" - integrity sha512-svx747PWHKOGpAXXQkCc4k/DsWo+6bc5LsVrAsw+OU+Ibi7klFZCyX54gjYzX4TH+f2uzXjRviLARxkMurA2bA== - -postcss-discard-empty@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.0.1.tgz#ee136c39e27d5d2ed4da0ee5ed02bc8a9f8bf6d8" - integrity sha512-vfU8CxAQ6YpMxV2SvMcMIyF2LX1ZzWpy0lqHDsOdaKKLQVQGVP1pzhrI9JlsO65s66uQTfkQBKBD/A5gp9STFw== - -postcss-discard-overridden@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.0.1.tgz#454b41f707300b98109a75005ca4ab0ff2743ac6" - integrity sha512-Y28H7y93L2BpJhrdUR2SR2fnSsT+3TVx1NmVQLbcnZWwIUpJ7mfcTC6Za9M2PG6w8j7UQRfzxqn8jU2VwFxo3Q== - -postcss-double-position-gradients@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz#fc927d52fddc896cb3a2812ebc5df147e110522e" - integrity sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA== - dependencies: - postcss "^7.0.5" - postcss-values-parser "^2.0.0" - -postcss-env-function@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-2.0.2.tgz#0f3e3d3c57f094a92c2baf4b6241f0b0da5365d7" - integrity sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-focus-visible@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz#477d107113ade6024b14128317ade2bd1e17046e" - integrity sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g== - dependencies: - postcss "^7.0.2" - -postcss-focus-within@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz#763b8788596cee9b874c999201cdde80659ef680" - integrity sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w== - dependencies: - postcss "^7.0.2" - -postcss-font-variant@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-4.0.1.tgz#42d4c0ab30894f60f98b17561eb5c0321f502641" - integrity sha512-I3ADQSTNtLTTd8uxZhtSOrTCQ9G4qUVKPjHiDk0bV75QSxXjVWiJVJ2VLdspGUi9fbW9BcjKJoRvxAH1pckqmA== - dependencies: - postcss "^7.0.2" - -postcss-gap-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz#431c192ab3ed96a3c3d09f2ff615960f902c1715" - integrity sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg== - dependencies: - postcss "^7.0.2" - -postcss-image-set-function@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz#28920a2f29945bed4c3198d7df6496d410d3f288" - integrity sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" + postcss-value-parser "^4.2.0" postcss-import@14.0.2: version "14.0.2" @@ -6402,99 +6046,37 @@ postcss-import@14.0.2: read-cache "^1.0.0" resolve "^1.1.7" -postcss-initial@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.4.tgz#9d32069a10531fe2ecafa0b6ac750ee0bc7efc53" - integrity sha512-3RLn6DIpMsK1l5UUy9jxQvoDeUN4gP939tDcKUHD/kM8SGSKbFAnvkpFpj3Bhtz3HGk1jWY5ZNWX6mPta5M9fg== - dependencies: - postcss "^7.0.2" +postcss-initial@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-4.0.1.tgz#529f735f72c5724a0fb30527df6fb7ac54d7de42" + integrity sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ== -postcss-lab-function@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz#bb51a6856cd12289ab4ae20db1e3821ef13d7d2e" - integrity sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg== +postcss-lab-function@^4.0.3: + version "4.1.1" + resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-4.1.1.tgz#8b37dfcb9ca4ff82bbe7192c7ba3cc2bccbc0ef1" + integrity sha512-j3Z0WQCimY2tMle++YcmygnnVbt6XdnrCV1FO2IpzaCSmtTF2oO8h4ZYUA1Q+QHYroIiaWPvNHt9uBR4riCksQ== dependencies: - "@csstools/convert-colors" "^1.4.0" - postcss "^7.0.2" - postcss-values-parser "^2.0.0" + "@csstools/postcss-progressive-custom-properties" "^1.1.0" + postcss-value-parser "^4.2.0" -postcss-loader@6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-6.1.1.tgz#58dd0a3accd9bc87cc52eff75244db578d11301a" - integrity sha512-lBmJMvRh1D40dqpWKr9Rpygwxn8M74U9uaCSeYGNKLGInbk9mXBt1ultHf2dH9Ghk6Ue4UXlXWwGMH9QdUJ5ug== +postcss-loader@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-6.2.1.tgz#0895f7346b1702103d30fdc66e4d494a93c008ef" + integrity sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q== dependencies: cosmiconfig "^7.0.0" - klona "^2.0.4" + klona "^2.0.5" semver "^7.3.5" -postcss-logical@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-3.0.0.tgz#2495d0f8b82e9f262725f75f9401b34e7b45d5b5" - integrity sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA== - dependencies: - postcss "^7.0.2" +postcss-logical@^5.0.3: + version "5.0.4" + resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-5.0.4.tgz#ec75b1ee54421acc04d5921576b7d8db6b0e6f73" + integrity sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g== -postcss-media-minmax@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz#b75bb6cbc217c8ac49433e12f22048814a4f5ed5" - integrity sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw== - dependencies: - postcss "^7.0.2" - -postcss-merge-longhand@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.0.2.tgz#277ada51d9a7958e8ef8cf263103c9384b322a41" - integrity sha512-BMlg9AXSI5G9TBT0Lo/H3PfUy63P84rVz3BjCFE9e9Y9RXQZD3+h3YO1kgTNsNJy7bBc1YQp8DmSnwLIW5VPcw== - dependencies: - css-color-names "^1.0.1" - postcss-value-parser "^4.1.0" - stylehacks "^5.0.1" - -postcss-merge-rules@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.0.2.tgz#d6e4d65018badbdb7dcc789c4f39b941305d410a" - integrity sha512-5K+Md7S3GwBewfB4rjDeol6V/RZ8S+v4B66Zk2gChRqLTCC8yjnHQ601omj9TKftS19OPGqZ/XzoqpzNQQLwbg== - dependencies: - browserslist "^4.16.6" - caniuse-api "^3.0.0" - cssnano-utils "^2.0.1" - postcss-selector-parser "^6.0.5" - vendors "^1.0.3" - -postcss-minify-font-values@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.0.1.tgz#a90cefbfdaa075bd3dbaa1b33588bb4dc268addf" - integrity sha512-7JS4qIsnqaxk+FXY1E8dHBDmraYFWmuL6cgt0T1SWGRO5bzJf8sUoelwa4P88LEWJZweHevAiDKxHlofuvtIoA== - dependencies: - postcss-value-parser "^4.1.0" - -postcss-minify-gradients@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.0.2.tgz#7c175c108f06a5629925d698b3c4cf7bd3864ee5" - integrity sha512-7Do9JP+wqSD6Prittitt2zDLrfzP9pqKs2EcLX7HJYxsxCOwrrcLt4x/ctQTsiOw+/8HYotAoqNkrzItL19SdQ== - dependencies: - colord "^2.6" - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" - -postcss-minify-params@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.0.1.tgz#371153ba164b9d8562842fdcd929c98abd9e5b6c" - integrity sha512-4RUC4k2A/Q9mGco1Z8ODc7h+A0z7L7X2ypO1B6V8057eVK6mZ6xwz6QN64nHuHLbqbclkX1wyzRnIrdZehTEHw== - dependencies: - alphanum-sort "^1.0.2" - browserslist "^4.16.0" - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" - uniqs "^2.0.0" - -postcss-minify-selectors@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.1.0.tgz#4385c845d3979ff160291774523ffa54eafd5a54" - integrity sha512-NzGBXDa7aPsAcijXZeagnJBKBPMYLaJJzB8CQh6ncvyl2sIndLVWfbcDi0SBjRWk5VqEjXvf8tYwzoKf4Z07og== - dependencies: - alphanum-sort "^1.0.2" - postcss-selector-parser "^6.0.5" +postcss-media-minmax@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz#7140bddec173e2d6d657edbd8554a55794e2a5b5" + integrity sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ== postcss-modules-extract-imports@^3.0.0: version "3.0.0" @@ -6524,210 +6106,89 @@ postcss-modules-values@^4.0.0: dependencies: icss-utils "^5.0.0" -postcss-nesting@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-7.0.1.tgz#b50ad7b7f0173e5b5e3880c3501344703e04c052" - integrity sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg== +postcss-nesting@^10.1.2: + version "10.1.2" + resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-10.1.2.tgz#2e5f811b3d75602ea18a95dd445bde5297145141" + integrity sha512-dJGmgmsvpzKoVMtDMQQG/T6FSqs6kDtUDirIfl4KnjMCiY9/ETX8jdKyCd20swSRAbUYkaBKV20pxkzxoOXLqQ== dependencies: - postcss "^7.0.2" + postcss-selector-parser "^6.0.8" -postcss-normalize-charset@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.0.1.tgz#121559d1bebc55ac8d24af37f67bd4da9efd91d0" - integrity sha512-6J40l6LNYnBdPSk+BHZ8SF+HAkS4q2twe5jnocgd+xWpz/mx/5Sa32m3W1AA8uE8XaXN+eg8trIlfu8V9x61eg== +postcss-overflow-shorthand@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.3.tgz#ebcfc0483a15bbf1b27fdd9b3c10125372f4cbc2" + integrity sha512-CxZwoWup9KXzQeeIxtgOciQ00tDtnylYIlJBBODqkgS/PU2jISuWOL/mYLHmZb9ZhZiCaNKsCRiLp22dZUtNsg== -postcss-normalize-display-values@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.1.tgz#62650b965981a955dffee83363453db82f6ad1fd" - integrity sha512-uupdvWk88kLDXi5HEyI9IaAJTE3/Djbcrqq8YgjvAVuzgVuqIk3SuJWUisT2gaJbZm1H9g5k2w1xXilM3x8DjQ== +postcss-page-break@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-3.0.4.tgz#7fbf741c233621622b68d435babfb70dd8c1ee5f" + integrity sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ== + +postcss-place@^7.0.3: + version "7.0.4" + resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-7.0.4.tgz#eb026650b7f769ae57ca4f938c1addd6be2f62c9" + integrity sha512-MrgKeiiu5OC/TETQO45kV3npRjOFxEHthsqGtkh3I1rPbZSbXGD/lZVi9j13cYh+NA8PIAPyk6sGjT9QbRyvSg== dependencies: - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" + postcss-value-parser "^4.2.0" -postcss-normalize-positions@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.0.1.tgz#868f6af1795fdfa86fbbe960dceb47e5f9492fe5" - integrity sha512-rvzWAJai5xej9yWqlCb1OWLd9JjW2Ex2BCPzUJrbaXmtKtgfL8dBMOOMTX6TnvQMtjk3ei1Lswcs78qKO1Skrg== +postcss-preset-env@7.2.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-7.2.3.tgz#01b9b6eea0ff16c27a3d514f10105d56363428a6" + integrity sha512-Ok0DhLfwrcNGrBn8sNdy1uZqWRk/9FId0GiQ39W4ILop5GHtjJs8bu1MY9isPwHInpVEPWjb4CEcEaSbBLpfwA== dependencies: - postcss-value-parser "^4.1.0" + autoprefixer "^10.4.2" + browserslist "^4.19.1" + caniuse-lite "^1.0.30001299" + css-blank-pseudo "^3.0.2" + css-has-pseudo "^3.0.3" + css-prefers-color-scheme "^6.0.2" + cssdb "^5.0.0" + postcss-attribute-case-insensitive "^5.0.0" + postcss-color-functional-notation "^4.2.1" + postcss-color-hex-alpha "^8.0.2" + postcss-color-rebeccapurple "^7.0.2" + postcss-custom-media "^8.0.0" + postcss-custom-properties "^12.1.2" + postcss-custom-selectors "^6.0.0" + postcss-dir-pseudo-class "^6.0.3" + postcss-double-position-gradients "^3.0.4" + postcss-env-function "^4.0.4" + postcss-focus-visible "^6.0.3" + postcss-focus-within "^5.0.3" + postcss-font-variant "^5.0.0" + postcss-gap-properties "^3.0.2" + postcss-image-set-function "^4.0.4" + postcss-initial "^4.0.1" + postcss-lab-function "^4.0.3" + postcss-logical "^5.0.3" + postcss-media-minmax "^5.0.0" + postcss-nesting "^10.1.2" + postcss-overflow-shorthand "^3.0.2" + postcss-page-break "^3.0.4" + postcss-place "^7.0.3" + postcss-pseudo-class-any-link "^7.0.2" + postcss-replace-overflow-wrap "^4.0.0" + postcss-selector-not "^5.0.0" -postcss-normalize-repeat-style@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.1.tgz#cbc0de1383b57f5bb61ddd6a84653b5e8665b2b5" - integrity sha512-syZ2itq0HTQjj4QtXZOeefomckiV5TaUO6ReIEabCh3wgDs4Mr01pkif0MeVwKyU/LHEkPJnpwFKRxqWA/7O3w== +postcss-pseudo-class-any-link@^7.0.2: + version "7.1.1" + resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.1.tgz#534eb1dadd9945eb07830dbcc06fb4d5d865b8e0" + integrity sha512-JRoLFvPEX/1YTPxRxp1JO4WxBVXJYrSY7NHeak5LImwJ+VobFMwYDQHvfTXEpcn+7fYIeGkC29zYFhFWIZD8fg== dependencies: - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" + postcss-selector-parser "^6.0.9" -postcss-normalize-string@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.0.1.tgz#d9eafaa4df78c7a3b973ae346ef0e47c554985b0" - integrity sha512-Ic8GaQ3jPMVl1OEn2U//2pm93AXUcF3wz+OriskdZ1AOuYV25OdgS7w9Xu2LO5cGyhHCgn8dMXh9bO7vi3i9pA== - dependencies: - postcss-value-parser "^4.1.0" - -postcss-normalize-timing-functions@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.1.tgz#8ee41103b9130429c6cbba736932b75c5e2cb08c" - integrity sha512-cPcBdVN5OsWCNEo5hiXfLUnXfTGtSFiBU9SK8k7ii8UD7OLuznzgNRYkLZow11BkQiiqMcgPyh4ZqXEEUrtQ1Q== - dependencies: - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" - -postcss-normalize-unicode@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.1.tgz#82d672d648a411814aa5bf3ae565379ccd9f5e37" - integrity sha512-kAtYD6V3pK0beqrU90gpCQB7g6AOfP/2KIPCVBKJM2EheVsBQmx/Iof+9zR9NFKLAx4Pr9mDhogB27pmn354nA== - dependencies: - browserslist "^4.16.0" - postcss-value-parser "^4.1.0" - -postcss-normalize-url@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.0.2.tgz#ddcdfb7cede1270740cf3e4dfc6008bd96abc763" - integrity sha512-k4jLTPUxREQ5bpajFQZpx8bCF2UrlqOTzP9kEqcEnOfwsRshWs2+oAFIHfDQB8GO2PaUaSE0NlTAYtbluZTlHQ== - dependencies: - is-absolute-url "^3.0.3" - normalize-url "^6.0.1" - postcss-value-parser "^4.1.0" - -postcss-normalize-whitespace@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.1.tgz#b0b40b5bcac83585ff07ead2daf2dcfbeeef8e9a" - integrity sha512-iPklmI5SBnRvwceb/XH568yyzK0qRVuAG+a1HFUsFRf11lEJTiQQa03a4RSCQvLKdcpX7XsI1Gen9LuLoqwiqA== - dependencies: - postcss-value-parser "^4.1.0" - -postcss-ordered-values@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.0.2.tgz#1f351426977be00e0f765b3164ad753dac8ed044" - integrity sha512-8AFYDSOYWebJYLyJi3fyjl6CqMEG/UVworjiyK1r573I56kb3e879sCJLGvR3merj+fAdPpVplXKQZv+ey6CgQ== - dependencies: - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" - -postcss-overflow-shorthand@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz#31ecf350e9c6f6ddc250a78f0c3e111f32dd4c30" - integrity sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g== - dependencies: - postcss "^7.0.2" - -postcss-page-break@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-2.0.0.tgz#add52d0e0a528cabe6afee8b46e2abb277df46bf" - integrity sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ== - dependencies: - postcss "^7.0.2" - -postcss-place@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-4.0.1.tgz#e9f39d33d2dc584e46ee1db45adb77ca9d1dcc62" - integrity sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-preset-env@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz#c34ddacf8f902383b35ad1e030f178f4cdf118a5" - integrity sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg== - dependencies: - autoprefixer "^9.6.1" - browserslist "^4.6.4" - caniuse-lite "^1.0.30000981" - css-blank-pseudo "^0.1.4" - css-has-pseudo "^0.10.0" - css-prefers-color-scheme "^3.1.1" - cssdb "^4.4.0" - postcss "^7.0.17" - postcss-attribute-case-insensitive "^4.0.1" - postcss-color-functional-notation "^2.0.1" - postcss-color-gray "^5.0.0" - postcss-color-hex-alpha "^5.0.3" - postcss-color-mod-function "^3.0.3" - postcss-color-rebeccapurple "^4.0.1" - postcss-custom-media "^7.0.8" - postcss-custom-properties "^8.0.11" - postcss-custom-selectors "^5.1.2" - postcss-dir-pseudo-class "^5.0.0" - postcss-double-position-gradients "^1.0.0" - postcss-env-function "^2.0.2" - postcss-focus-visible "^4.0.0" - postcss-focus-within "^3.0.0" - postcss-font-variant "^4.0.0" - postcss-gap-properties "^2.0.0" - postcss-image-set-function "^3.0.1" - postcss-initial "^3.0.0" - postcss-lab-function "^2.0.1" - postcss-logical "^3.0.0" - postcss-media-minmax "^4.0.0" - postcss-nesting "^7.0.0" - postcss-overflow-shorthand "^2.0.0" - postcss-page-break "^2.0.0" - postcss-place "^4.0.1" - postcss-pseudo-class-any-link "^6.0.0" - postcss-replace-overflow-wrap "^3.0.0" - postcss-selector-matches "^4.0.0" - postcss-selector-not "^4.0.0" - -postcss-pseudo-class-any-link@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz#2ed3eed393b3702879dec4a87032b210daeb04d1" - integrity sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew== - dependencies: - postcss "^7.0.2" - postcss-selector-parser "^5.0.0-rc.3" - -postcss-reduce-initial@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.0.1.tgz#9d6369865b0f6f6f6b165a0ef5dc1a4856c7e946" - integrity sha512-zlCZPKLLTMAqA3ZWH57HlbCjkD55LX9dsRyxlls+wfuRfqCi5mSlZVan0heX5cHr154Dq9AfbH70LyhrSAezJw== - dependencies: - browserslist "^4.16.0" - caniuse-api "^3.0.0" - -postcss-reduce-transforms@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.1.tgz#93c12f6a159474aa711d5269923e2383cedcf640" - integrity sha512-a//FjoPeFkRuAguPscTVmRQUODP+f3ke2HqFNgGPwdYnpeC29RZdCBvGRGTsKpMURb/I3p6jdKoBQ2zI+9Q7kA== - dependencies: - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" - -postcss-replace-overflow-wrap@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz#61b360ffdaedca84c7c918d2b0f0d0ea559ab01c" - integrity sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw== - dependencies: - postcss "^7.0.2" - -postcss-selector-matches@^4.0.0: +postcss-replace-overflow-wrap@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz#71c8248f917ba2cc93037c9637ee09c64436fcff" - integrity sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww== - dependencies: - balanced-match "^1.0.0" - postcss "^7.0.2" + resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz#d2df6bed10b477bf9c52fab28c568b4b29ca4319" + integrity sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw== -postcss-selector-not@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-4.0.1.tgz#263016eef1cf219e0ade9a913780fc1f48204cbf" - integrity sha512-YolvBgInEK5/79C+bdFMyzqTg6pkYqDbzZIST/PDMqa/o3qtXenD05apBG2jLgT0/BQ77d4U2UK12jWpilqMAQ== - dependencies: - balanced-match "^1.0.0" - postcss "^7.0.2" - -postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4: +postcss-selector-not@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" - integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== + resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-5.0.0.tgz#ac5fc506f7565dd872f82f5314c0f81a05630dc7" + integrity sha512-/2K3A4TCP9orP4TNS7u3tGdRFVKqz/E6pX3aGnriPG0jU78of8wsUcqE4QAhWEU0d+WnMSF93Ah3F//vUtK+iQ== dependencies: - cssesc "^2.0.0" - indexes-of "^1.0.1" - uniq "^1.0.1" + balanced-match "^1.0.0" -postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5: +postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: version "6.0.6" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz#2c5bba8174ac2f6981ab631a42ab0ee54af332ea" integrity sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg== @@ -6735,55 +6196,43 @@ postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector cssesc "^3.0.0" util-deprecate "^1.0.2" -postcss-svgo@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.0.2.tgz#bc73c4ea4c5a80fbd4b45e29042c34ceffb9257f" - integrity sha512-YzQuFLZu3U3aheizD+B1joQ94vzPfE6BNUcSYuceNxlVnKKsOtdo6hL9/zyC168Q8EwfLSgaDSalsUGa9f2C0A== +postcss-selector-parser@^6.0.8, postcss-selector-parser@^6.0.9: + version "6.0.9" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f" + integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ== dependencies: - postcss-value-parser "^4.1.0" - svgo "^2.3.0" + cssesc "^3.0.0" + util-deprecate "^1.0.2" -postcss-unique-selectors@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.0.1.tgz#3be5c1d7363352eff838bd62b0b07a0abad43bfc" - integrity sha512-gwi1NhHV4FMmPn+qwBNuot1sG1t2OmacLQ/AX29lzyggnjd+MnVD5uqQmpXO3J17KGL2WAxQruj1qTd3H0gG/w== - dependencies: - alphanum-sort "^1.0.2" - postcss-selector-parser "^6.0.5" - uniqs "^2.0.0" - -postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0: +postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== -postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz#da8b472d901da1e205b47bdc98637b9e9e550e5f" - integrity sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg== - dependencies: - flatten "^1.0.2" - indexes-of "^1.0.1" - uniq "^1.0.1" +postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@8.3.6: - version "8.3.6" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.6.tgz#2730dd76a97969f37f53b9a6096197be311cc4ea" - integrity sha512-wG1cc/JhRgdqB6WHEuyLTedf3KIRuD0hG6ldkFEZNCjRxiC+3i6kkWUUbiJQayP28iwG35cEmAbe98585BYV0A== +postcss@8.4.5: + version "8.4.5" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95" + integrity sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg== dependencies: - colorette "^1.2.2" - nanoid "^3.1.23" - source-map-js "^0.6.2" + nanoid "^3.1.30" + picocolors "^1.0.0" + source-map-js "^1.0.1" -postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.32, postcss@^7.0.35, postcss@^7.0.5, postcss@^7.0.6: - version "7.0.39" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309" - integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA== +postcss@^8.2.14, postcss@^8.3.7: + version "8.4.6" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.6.tgz#c5ff3c3c457a23864f32cb45ac9b741498a09ae1" + integrity sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA== dependencies: - picocolors "^0.2.1" - source-map "^0.6.1" + nanoid "^3.2.0" + picocolors "^1.0.0" + source-map-js "^1.0.2" -postcss@^8.2.15, postcss@^8.3.5: +postcss@^8.2.15: version "8.3.9" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.9.tgz#98754caa06c4ee9eb59cc48bd073bb6bd3437c31" integrity sha512-f/ZFyAKh9Dnqytx5X62jgjhhzttjZS7hMsohcI7HEI5tjELX/HxCy3EFhsRxyzGvrzFF+82XPvCS8T9TFleVJw== @@ -6797,17 +6246,17 @@ pretty-bytes@^5.3.0: resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== -primeicons@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/primeicons/-/primeicons-4.1.0.tgz#19eaef8ef5594b0006358ae64e738d03e167c9bb" - integrity sha512-uEv2pSPk1zQCfaB2VgnUfnUxxlGryYi+5rbdxmZBBt5v9S/pscIQYS5YDLxsQZ7D9jn5c76+Tx5wX/2J1nK6sA== +primeicons@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/primeicons/-/primeicons-5.0.0.tgz#73a0b6028a77c58a9eeb331ad13aaf085e8451ee" + integrity sha512-heygWF0X5HFI1otlZE62pp6ye7sZ8om78J9au2BRkg8O7Y8AHTZ9qKMRzchZUHLe8zUAvdi6hZzzm9XxgwIExw== -primeng@^12.2.0: - version "12.2.0" - resolved "https://registry.yarnpkg.com/primeng/-/primeng-12.2.0.tgz#f42fd389722959319dc225ff7a08386bf828eef4" - integrity sha512-EKU6VRDPbE9VzPzP/XbSTT2oEBV/RVbREzgXENUIIYdEmaPpRao/j6MDnX6niKKBe7VWA50hf18djhSQgAsCOg== +primeng@^13.2.0: + version "13.2.0" + resolved "https://registry.yarnpkg.com/primeng/-/primeng-13.2.0.tgz#cbcc7fbc55b1479435e978c5156228e6e853c278" + integrity sha512-6rnjfXu91B1bVAFoJdbGTD7e3EXeTabPLvAJlVOg7/YFPbvzvOKjdFKa+8zomSun7TJgDLJTEa1ijgjc9b+uiA== dependencies: - tslib "^2.1.0" + tslib "^2.3.0" process-nextick-args@~2.0.0: version "2.0.1" @@ -6874,11 +6323,6 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -6894,16 +6338,6 @@ q@^1.4.1: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= -qrcode@1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.4.2.tgz#e7c82a60140916d666541043bd2b0b72ee4e38a6" - integrity sha512-eR6RgxFYPDFH+zFLTJKtoNP/RlsHANQb52AUmQ2bGDPMuUw7jJb0F+DNEgx7qQGIElrbFxWYMc0/B91zLZPF9Q== - dependencies: - dijkstrajs "^1.0.1" - isarray "^2.0.1" - pngjs "^3.3.0" - yargs "^13.2.4" - qs@6.7.0: version "6.7.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" @@ -6921,11 +6355,6 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= - querystringify@^2.1.1: version "2.2.0" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" @@ -6973,7 +6402,7 @@ read-package-json-fast@^2.0.1: json-parse-even-better-errors "^2.3.0" npm-normalize-package-bin "^1.0.1" -readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.3.5, readable-stream@~2.3.6: +readable-stream@^2.0.1, readable-stream@^2.3.5, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -6986,7 +6415,7 @@ readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6, readable-stream@^3.4.0: +readable-stream@^3.0.6, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -6995,15 +6424,6 @@ readable-stream@^3.0.6, readable-stream@^3.4.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -7016,6 +6436,13 @@ reflect-metadata@^0.1.2: resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08" integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg== +regenerate-unicode-properties@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56" + integrity sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw== + dependencies: + regenerate "^1.4.2" + regenerate-unicode-properties@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz#54d09c7115e1f53dc2314a974b32c1c344efe326" @@ -7040,14 +6467,6 @@ regenerator-transform@^0.14.2: dependencies: "@babel/runtime" "^7.8.4" -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - regex-parser@^2.2.11: version "2.2.11" resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.11.tgz#3b37ec9049e19479806e878cabe7c1ca83ccfe58" @@ -7073,11 +6492,28 @@ regexpu-core@^4.7.1: unicode-match-property-ecmascript "^2.0.0" unicode-match-property-value-ecmascript "^2.0.0" +regexpu-core@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.0.1.tgz#c531122a7840de743dcf9c83e923b5560323ced3" + integrity sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw== + dependencies: + regenerate "^1.4.2" + regenerate-unicode-properties "^10.0.1" + regjsgen "^0.6.0" + regjsparser "^0.8.2" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.0.0" + regjsgen@^0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== +regjsgen@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.6.0.tgz#83414c5354afd7d6627b16af5f10f41c4e71808d" + integrity sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA== + regjsparser@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.7.0.tgz#a6b667b54c885e18b52554cb4960ef71187e9968" @@ -7085,22 +6521,14 @@ regjsparser@^0.7.0: dependencies: jsesc "~0.5.0" -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= +regjsparser@^0.8.2: + version "0.8.4" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.8.4.tgz#8a14285ffcc5de78c5b95d62bbf413b6bc132d5f" + integrity sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA== + dependencies: + jsesc "~0.5.0" -repeat-element@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" - integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -request@^2.87.0, request@^2.88.0, request@^2.88.2: +request@^2.87.0, request@^2.88.0: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -7141,50 +6569,42 @@ require-main-filename@^1.0.1: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= -resolve-cwd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" - integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= - dependencies: - resolve-from "^3.0.0" - -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha1-six699nWiBvItuZTM17rywoYh0g= - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve-url-loader@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz#d50d4ddc746bb10468443167acf800dcd6c3ad57" - integrity sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA== +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve-url-loader@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz#ee3142fb1f1e0d9db9524d539cfa166e9314f795" + integrity sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg== dependencies: adjust-sourcemap-loader "^4.0.0" convert-source-map "^1.7.0" loader-utils "^2.0.0" - postcss "^7.0.35" + postcss "^8.2.14" source-map "0.6.1" -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= +resolve@1.22.0: + version "1.22.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" + integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== + dependencies: + is-core-module "^2.8.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" -resolve@1.20.0, resolve@^1.1.7, resolve@^1.14.2, resolve@^1.3.2: +resolve@^1.1.7, resolve@^1.14.2, resolve@^1.3.2: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== @@ -7200,22 +6620,22 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - retry@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= +retry@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.3: +rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.5.4: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -7257,13 +6677,20 @@ rxjs@6.6.7, rxjs@^6.5.3: dependencies: tslib "^1.9.0" -rxjs@^7.2.0, rxjs@^7.4.0: +rxjs@^7.2.0: version "7.4.0" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.4.0.tgz#a12a44d7eebf016f5ff2441b87f28c9a51cebc68" integrity sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w== dependencies: tslib "~2.1.0" +rxjs@^7.5.4: + version "7.5.4" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.4.tgz#3d6bd407e6b7ce9a123e76b1e770dc5761aa368d" + integrity sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ== + dependencies: + tslib "^2.1.0" + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -7274,22 +6701,15 @@ safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= - dependencies: - ret "~0.1.10" - "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@^2.1.2, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sass-loader@12.1.0: - version "12.1.0" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.1.0.tgz#b73324622231009da6fba61ab76013256380d201" - integrity sha512-FVJZ9kxVRYNZTIe2xhw93n3xJNYZADr+q69/s98l9nTCrWASo+DR2Ot0s5xTKQDDEosUkatsGeHxcH4QBp5bSg== +sass-loader@12.4.0: + version "12.4.0" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.4.0.tgz#260b0d51a8a373bb8e88efc11f6ba5583fea0bcf" + integrity sha512-7xN+8khDIzym1oL9XyS6zP6Ges+Bo2B2xbPrjdMHEYyV3AQYhd/wXeru++3ODHF0zMjYmVadblSKrPrjEkL8mg== dependencies: klona "^2.0.4" neo-async "^2.6.2" @@ -7299,12 +6719,14 @@ sass-recursive-map-merge@^1.0.1: resolved "https://registry.yarnpkg.com/sass-recursive-map-merge/-/sass-recursive-map-merge-1.0.1.tgz#d5460b9fe10df62d246ca27c48d823f25c2290cb" integrity sha512-OuDTGVGx2o2sPeaSgGob5s2Qf6LxoMU4LG7n6vCzNgfXyBz/y8tKzcEYdmvgyhjvGQVcGA1g2UJnP7WMmahuVg== -sass@1.36.0: - version "1.36.0" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.36.0.tgz#5912ef9d5d16714171ba11cb17edb274c4bbc07e" - integrity sha512-fQzEjipfOv5kh930nu3Imzq3ie/sGDc/4KtQMJlt7RRdrkQSfe37Bwi/Rf/gfuYHsIuE1fIlDMvpyMcEwjnPvg== +sass@1.49.0: + version "1.49.0" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.49.0.tgz#65ec1b1d9a6bc1bae8d2c9d4b392c13f5d32c078" + integrity sha512-TVwVdNDj6p6b4QymJtNtRS2YtLJ/CqZriGg0eIAbAKMlN8Xy6kbv33FsEZSF7FufFFM705SQviHjjThfaQ4VNw== dependencies: chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" saucelabs@^1.5.0: version "1.5.0" @@ -7318,16 +6740,7 @@ sax@>=0.6.0, sax@^1.2.4, sax@~1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -schema-utils@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" - integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== - dependencies: - ajv "^6.1.0" - ajv-errors "^1.0.0" - ajv-keywords "^3.1.0" - -schema-utils@^2.6.5, schema-utils@^2.7.0: +schema-utils@^2.6.5: version "2.7.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== @@ -7336,7 +6749,7 @@ schema-utils@^2.6.5, schema-utils@^2.7.0: ajv "^6.12.4" ajv-keywords "^3.5.2" -schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: +schema-utils@^3.1.0, schema-utils@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== @@ -7345,6 +6758,16 @@ schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: ajv "^6.12.5" ajv-keywords "^3.5.2" +schema-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" + integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.8.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.0.0" + select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" @@ -7360,12 +6783,12 @@ selenium-webdriver@3.6.0, selenium-webdriver@^3.0.1: tmp "0.0.30" xml2js "^0.4.17" -selfsigned@^1.10.8: - version "1.10.11" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.11.tgz#24929cd906fe0f44b6d01fb23999a739537acbe9" - integrity sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA== +selfsigned@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.0.0.tgz#e927cd5377cbb0a1075302cff8df1042cc2bce5b" + integrity sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ== dependencies: - node-forge "^0.10.0" + node-forge "^1.2.0" semver-dsl@^1.0.1: version "1.0.1" @@ -7379,7 +6802,7 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@7.3.5, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: +semver@7.3.5, semver@^7.0.0, semver@^7.1.1, semver@^7.3.4, semver@^7.3.5: version "7.3.5" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== @@ -7445,7 +6868,7 @@ serve-static@1.14.1: parseurl "~1.3.3" send "0.17.1" -set-blocking@^2.0.0, set-blocking@~2.0.0: +set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -7455,16 +6878,6 @@ set-immediate-shim@~1.0.1: resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" @@ -7489,11 +6902,23 @@ shebang-command@^1.2.0: dependencies: shebang-regex "^1.0.0" +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -7508,58 +6933,26 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.5.tgz#9e3e8cc0c75a99472b44321033a7702e7738252f" integrity sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ== +signal-exit@^3.0.3: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +slash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" + integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== + smart-buffer@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -sockjs-client@^1.5.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.2.tgz#4bc48c2da9ce4769f19dc723396b50f5c12330a3" - integrity sha512-ZzRxPBISQE7RpzlH4tKJMQbHM9pabHluk0WBaxAQ+wm/UieeBVBou0p4wVnSQGN9QmpAZygQ0cDIypWuqOFmFQ== - dependencies: - debug "^3.2.6" - eventsource "^1.0.7" - faye-websocket "^0.11.3" - inherits "^2.0.4" - json3 "^3.3.3" - url-parse "^1.5.3" - sockjs@^0.3.21: version "0.3.21" resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.21.tgz#b34ffb98e796930b60a0cfa11904d6a339a7d417" @@ -7578,6 +6971,15 @@ socks-proxy-agent@^6.0.0: debug "^4.3.1" socks "^2.6.1" +socks-proxy-agent@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz#e664e8f1aaf4e1fb3df945f09e3d94f911137f87" + integrity sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew== + dependencies: + agent-base "^6.0.2" + debug "^4.3.1" + socks "^2.6.1" + socks@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.1.tgz#989e6534a07cf337deb1b1c94aaa44296520d30e" @@ -7586,35 +6988,24 @@ socks@^2.6.1: ip "^1.1.5" smart-buffer "^4.1.0" -source-list-map@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== source-map-js@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e" integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug== -source-map-loader@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-3.0.0.tgz#f2a04ee2808ad01c774dea6b7d2639839f3b3049" - integrity sha512-GKGWqWvYr04M7tn8dryIWvb0s8YM41z82iQv01yBtIylgxax0CwvSy6gc2Y02iuXwEfGWRlMicH0nvms9UZphw== +source-map-loader@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-3.0.1.tgz#9ae5edc7c2d42570934be4c95d1ccc6352eba52d" + integrity sha512-Vp1UsfyPvgujKQzi4pyDiTOnE3E4H+yHvkVRN3c/9PJmQS4CQJExvcDvaX/D+RV+xQben9HJ56jMJS3CgUeWyA== dependencies: abab "^2.0.5" - iconv-lite "^0.6.2" - source-map-js "^0.6.2" - -source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: - version "0.5.3" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" - integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== - dependencies: - atob "^2.1.2" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" + iconv-lite "^0.6.3" + source-map-js "^1.0.1" source-map-resolve@^0.6.0: version "0.6.0" @@ -7624,15 +7015,15 @@ source-map-resolve@^0.6.0: atob "^2.1.2" decode-uri-component "^0.2.0" -source-map-support@0.5.19: - version "0.5.19" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" - integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== +source-map-support@0.5.21: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-support@^0.5.3, source-map-support@^0.5.5, source-map-support@~0.5.19, source-map-support@~0.5.20: +source-map-support@^0.5.3, source-map-support@^0.5.5, source-map-support@~0.5.20: version "0.5.20" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9" integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw== @@ -7647,12 +7038,7 @@ source-map-support@~0.4.0: dependencies: source-map "^0.5.6" -source-map-url@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" - integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== - -source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: +source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -7695,13 +7081,6 @@ spdy@^4.0.2: select-hose "^2.0.0" spdy-transport "^3.0.0" -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - sprintf-js@^1.1.1, sprintf-js@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673" @@ -7734,19 +7113,6 @@ ssri@^8.0.0, ssri@^8.0.1: dependencies: minipass "^3.1.1" -stable@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== - -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - "statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" @@ -7766,24 +7132,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string-width@^3.0.0, string-width@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - -string-width@^4.1.0, string-width@^4.2.0: +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -7792,6 +7141,14 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string-width@^2.0.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -7820,13 +7177,6 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -7834,45 +7184,42 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-ansi@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" + integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== + dependencies: + ansi-regex "^6.0.1" + strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= -style-loader@3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.2.1.tgz#63cb920ec145c8669e9a50e92961452a1ef5dcde" - integrity sha512-1k9ZosJCRFaRbY6hH49JFlRB0fVSbmnyq1iTPjNxUmGVjBNEmwrrHPenhlp+Lgo51BojHSf6pl2FcqYaN3PfVg== +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== -stylehacks@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.0.1.tgz#323ec554198520986806388c7fdaebc38d2c06fb" - integrity sha512-Es0rVnHIqbWzveU1b24kbw92HsebBepxfcqe5iix7t9j0PQqhs0IxXVXv0pY2Bxa08CgMkzD6OWql7kbGOuEdA== +stylus-loader@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/stylus-loader/-/stylus-loader-6.2.0.tgz#0ba499e744e7fb9d9b3977784c8639728a7ced8c" + integrity sha512-5dsDc7qVQGRoc6pvCL20eYgRUxepZ9FpeK28XhdXaIPP6kXr6nI1zAAKFQgP5OBkOfKaURp4WUpJzspg1f01Gg== dependencies: - browserslist "^4.16.0" - postcss-selector-parser "^6.0.4" - -stylus-loader@6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/stylus-loader/-/stylus-loader-6.1.0.tgz#7a3a719a27cb2b9617896d6da28fda94c3ed9762" - integrity sha512-qKO34QCsOtSJrXxQQmXsPeaVHh6hMumBAFIoJTcsSr2VzrA6o/CW9HCGR8spCjzJhN8oKQHdj/Ytx0wwXyElkw== - dependencies: - fast-glob "^3.2.5" + fast-glob "^3.2.7" klona "^2.0.4" normalize-path "^3.0.0" -stylus@0.54.8: - version "0.54.8" - resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.54.8.tgz#3da3e65966bc567a7b044bfe0eece653e099d147" - integrity sha512-vr54Or4BZ7pJafo2mpf0ZcwA74rpuYCZbxrHBsH8kbcXOwSfvBFwsRfpGO5OD5fhG5HDCFW737PKaawI7OqEAg== +stylus@0.56.0: + version "0.56.0" + resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.56.0.tgz#13fc85c48082db483c90d2530942fe8b0be988eb" + integrity sha512-Ev3fOb4bUElwWu4F9P9WjnnaSpc8XB9OFHSFZSKMFL1CE1oM+oFXWEgAqPmmZIyhBihuqIQlFsVTypiiS9RxeA== dependencies: - css-parse "~2.0.0" - debug "~3.1.0" + css "^3.0.0" + debug "^4.3.2" glob "^7.1.6" - mkdirp "~1.0.4" safer-buffer "^2.1.2" sax "~1.2.4" - semver "^6.3.0" source-map "^0.7.3" superagent@^3.8.3: @@ -7903,13 +7250,6 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -supports-color@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" - integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== - dependencies: - has-flag "^3.0.0" - supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -7924,18 +7264,10 @@ supports-color@^8.0.0: dependencies: has-flag "^4.0.0" -svgo@^2.3.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.7.0.tgz#e164cded22f4408fe4978f082be80159caea1e2d" - integrity sha512-aDLsGkre4fTDCWvolyW+fs8ZJFABpzLXbtdK1y71CKnHzAnpDxKXPj2mNKj+pyOXUCzFHzuxRJ94XOFygOWV3w== - dependencies: - "@trysound/sax" "0.2.0" - commander "^7.2.0" - css-select "^4.1.3" - css-tree "^1.1.3" - csso "^4.2.0" - nanocolors "^0.1.12" - stable "^0.1.8" +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== symbol-observable@4.0.0: version "4.0.0" @@ -7947,7 +7279,7 @@ tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -tar@^6.0.2, tar@^6.1.0: +tar@^6.0.2, tar@^6.1.0, tar@^6.1.2: version "6.1.11" resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== @@ -7959,18 +7291,6 @@ tar@^6.0.2, tar@^6.1.0: mkdirp "^1.0.3" yallist "^4.0.0" -terser-webpack-plugin@5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.1.4.tgz#c369cf8a47aa9922bd0d8a94fe3d3da11a7678a1" - integrity sha512-C2WkFwstHDhVEmsmlCxrXUtVklS+Ir1A7twrYzrDrQQOIMOaVAYykaoo/Aq1K0QRkMoY2hhvDQY1cm4jnIMFwA== - dependencies: - jest-worker "^27.0.2" - p-limit "^3.1.0" - schema-utils "^3.0.0" - serialize-javascript "^6.0.0" - source-map "^0.6.1" - terser "^5.7.0" - terser-webpack-plugin@^5.1.3: version "5.2.4" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.2.4.tgz#ad1be7639b1cbe3ea49fab995cbe7224b31747a1" @@ -7983,16 +7303,16 @@ terser-webpack-plugin@^5.1.3: source-map "^0.6.1" terser "^5.7.2" -terser@5.7.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.7.1.tgz#2dc7a61009b66bb638305cb2a824763b116bf784" - integrity sha512-b3e+d5JbHAe/JSjwsC3Zn55wsBIM7AsHLjKxT31kGCldgbpFePaFo+PiddtO6uwRZWRw7sPXmAN8dTW61xmnSg== +terser@5.10.0: + version "5.10.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.10.0.tgz#b86390809c0389105eb0a0b62397563096ddafcc" + integrity sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA== dependencies: commander "^2.20.0" source-map "~0.7.2" - source-map-support "~0.5.19" + source-map-support "~0.5.20" -terser@^5.7.0, terser@^5.7.2: +terser@^5.7.2: version "5.9.0" resolved "https://registry.yarnpkg.com/terser/-/terser-5.9.0.tgz#47d6e629a522963240f2b55fcaa3c99083d2c351" integrity sha512-h5hxa23sCdpzcye/7b8YqbE5OwKca/ni0RQz1uRX3tGh8haaGHqcuSqbGRybuAKNdntZ0mDgFNXPJ48xQ2RXKQ== @@ -8001,6 +7321,15 @@ terser@^5.7.0, terser@^5.7.2: source-map "~0.7.2" source-map-support "~0.5.20" +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + text-table@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -8016,11 +7345,6 @@ thunky@^1.0.2: resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== -timsort@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" - integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= - tmp@0.0.30: version "0.0.30" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.30.tgz#72419d4a8be7d6ce75148fd8b324e593a711c2ed" @@ -8040,21 +7364,6 @@ to-fast-properties@^2.0.0: resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -8062,16 +7371,6 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - toidentifier@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" @@ -8109,21 +7408,16 @@ ts-node@~5.0.1: source-map-support "^0.5.3" yn "^2.0.0" -tslib@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" - integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== +tslib@2.3.1, tslib@^2.0.0, tslib@^2.1.0, tslib@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" + integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== tslib@^1.10.0, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.1.0, tslib@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== - tslib@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" @@ -8188,10 +7482,15 @@ type-is@~1.6.17, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -typescript@4.3.5, typescript@~4.3.4: - version "4.3.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4" - integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA== +typed-assert@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/typed-assert/-/typed-assert-1.0.8.tgz#4bf9f1ce7f3f974d09c3afd7c68d12e1391a233c" + integrity sha512-5NkbXZUlmCE73Fs7gvkp1XXJWHYetPkg60QnQ2NXQmBYNFxbBr2zA8GCtaH4K2s2WhOmSlgiSTmrjrcm5tnM5g== + +typescript@~4.5.5: + version "4.5.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" + integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" @@ -8216,26 +7515,6 @@ unicode-property-aliases-ecmascript@^2.0.0: resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8" integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ== -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - -uniq@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" - integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= - -uniqs@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" - integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= - unique-filename@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" @@ -8255,19 +7534,6 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -upath@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" - integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== - uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -8275,12 +7541,7 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - -url-parse@^1.4.3, url-parse@^1.5.3: +url-parse@^1.4.3: version "1.5.3" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.3.tgz#71c1303d38fb6639ade183c2992c8cc0686df862" integrity sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ== @@ -8288,19 +7549,6 @@ url-parse@^1.4.3, url-parse@^1.5.3: querystringify "^2.1.1" requires-port "^1.0.0" -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -8333,11 +7581,6 @@ vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= -vendors@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" - integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w== - verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" @@ -8347,10 +7590,10 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -watchpack@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.2.0.tgz#47d78f5415fe550ecd740f99fe2882323a58b1ce" - integrity sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA== +watchpack@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25" + integrity sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" @@ -8394,75 +7637,62 @@ webdriver-manager@^12.0.6: semver "^5.3.0" xml2js "^0.4.17" -webpack-dev-middleware@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.0.0.tgz#0abe825275720e0a339978aea5f0b03b140c1584" - integrity sha512-9zng2Z60pm6A98YoRcA0wSxw1EYn7B7y5owX/Tckyt9KGyULTkLtiavjaXlWqOMkM0YtqGgL3PvMOFgyFLq8vw== +webpack-dev-middleware@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.0.tgz#8fc02dba6e72e1d373eca361623d84610f27be7c" + integrity sha512-MouJz+rXAm9B1OTOYaJnn6rtD/lWZPy2ufQCH3BPs8Rloh/Du6Jze4p7AeLYHkVi0giJnYLaSGDC7S+GM9arhg== dependencies: - colorette "^1.2.2" - mem "^8.1.1" + colorette "^2.0.10" memfs "^3.2.2" mime-types "^2.1.31" range-parser "^1.2.1" - schema-utils "^3.0.0" + schema-utils "^4.0.0" -webpack-dev-middleware@^3.7.2: - version "3.7.3" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz#0639372b143262e2b84ab95d3b91a7597061c2c5" - integrity sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ== +webpack-dev-middleware@^5.3.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz#aa079a8dedd7e58bfeab358a9af7dab304cee57f" + integrity sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg== dependencies: - memory-fs "^0.4.1" - mime "^2.4.4" - mkdirp "^0.5.1" + colorette "^2.0.10" + memfs "^3.4.1" + mime-types "^2.1.31" range-parser "^1.2.1" - webpack-log "^2.0.0" + schema-utils "^4.0.0" -webpack-dev-server@3.11.2: - version "3.11.2" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz#695ebced76a4929f0d5de7fd73fafe185fe33708" - integrity sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ== +webpack-dev-server@4.7.3: + version "4.7.3" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.7.3.tgz#4e995b141ff51fa499906eebc7906f6925d0beaa" + integrity sha512-mlxq2AsIw2ag016nixkzUkdyOE8ST2GTy34uKSABp1c4nhjZvH90D5ZRR+UOLSsG4Z3TFahAi72a3ymRtfRm+Q== dependencies: - ansi-html "0.0.7" + "@types/bonjour" "^3.5.9" + "@types/connect-history-api-fallback" "^1.3.5" + "@types/serve-index" "^1.9.1" + "@types/sockjs" "^0.3.33" + "@types/ws" "^8.2.2" + ansi-html-community "^0.0.8" bonjour "^3.5.0" - chokidar "^2.1.8" + chokidar "^3.5.2" + colorette "^2.0.10" compression "^1.7.4" connect-history-api-fallback "^1.6.0" - debug "^4.1.1" - del "^4.1.1" + default-gateway "^6.0.3" + del "^6.0.0" express "^4.17.1" - html-entities "^1.3.1" - http-proxy-middleware "0.19.1" - import-local "^2.0.0" - internal-ip "^4.3.0" - ip "^1.1.5" - is-absolute-url "^3.0.3" - killable "^1.0.1" - loglevel "^1.6.8" - opn "^5.5.0" - p-retry "^3.0.1" - portfinder "^1.0.26" - schema-utils "^1.0.0" - selfsigned "^1.10.8" - semver "^6.3.0" + graceful-fs "^4.2.6" + html-entities "^2.3.2" + http-proxy-middleware "^2.0.0" + ipaddr.js "^2.0.1" + open "^8.0.9" + p-retry "^4.5.0" + portfinder "^1.0.28" + schema-utils "^4.0.0" + selfsigned "^2.0.0" serve-index "^1.9.1" sockjs "^0.3.21" - sockjs-client "^1.5.0" spdy "^4.0.2" - strip-ansi "^3.0.1" - supports-color "^6.1.0" - url "^0.11.0" - webpack-dev-middleware "^3.7.2" - webpack-log "^2.0.0" - ws "^6.2.1" - yargs "^13.3.2" - -webpack-log@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" - integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg== - dependencies: - ansi-colors "^3.0.0" - uuid "^3.3.2" + strip-ansi "^7.0.0" + webpack-dev-middleware "^5.3.0" + ws "^8.1.0" webpack-merge@5.8.0: version "5.8.0" @@ -8472,30 +7702,22 @@ webpack-merge@5.8.0: clone-deep "^4.0.1" wildcard "^2.0.0" -webpack-sources@^1.2.0, webpack-sources@^1.3.0: - version "1.4.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" - integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== +webpack-sources@^3.0.0, webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + +webpack-subresource-integrity@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/webpack-subresource-integrity/-/webpack-subresource-integrity-5.1.0.tgz#8b7606b033c6ccac14e684267cb7fb1f5c2a132a" + integrity sha512-sacXoX+xd8r4WKsy9MvH/q/vBtEHr86cpImXwyg74pFIpERKt6FmB8cXpeuh0ZLgclOlHI4Wcll7+R5L02xk9Q== dependencies: - source-list-map "^2.0.0" - source-map "~0.6.1" + typed-assert "^1.0.8" -webpack-sources@^3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.1.tgz#251a7d9720d75ada1469ca07dbb62f3641a05b6d" - integrity sha512-t6BMVLQ0AkjBOoRTZgqrWm7xbXMBzD+XDq2EZ96+vMfn3qKgsvdXZhbPZ4ElUOpdv4u+iiGe+w3+J75iy/bYGA== - -webpack-subresource-integrity@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/webpack-subresource-integrity/-/webpack-subresource-integrity-1.5.2.tgz#e40b6578d3072e2d24104975249c52c66e9a743e" - integrity sha512-GBWYBoyalbo5YClwWop9qe6Zclp8CIXYGIz12OPclJhIrSplDxs1Ls1JDMH8xBPPrg1T6ISaTW9Y6zOrwEiAzw== - dependencies: - webpack-sources "^1.3.0" - -webpack@5.50.0: - version "5.50.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.50.0.tgz#5562d75902a749eb4d75131f5627eac3a3192527" - integrity sha512-hqxI7t/KVygs0WRv/kTgUW8Kl3YC81uyWQSo/7WUs5LsuRw0htH/fCwbVBGCuiX/t4s7qzjXFcf41O8Reiypag== +webpack@5.67.0: + version "5.67.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.67.0.tgz#cb43ca2aad5f7cc81c4cd36b626e6b819805dbfd" + integrity sha512-LjFbfMh89xBDpUMgA1W9Ur6Rn/gnr2Cq1jjHFPo4v6a79/ypznSYbAyPgGhwsxBtMIaEmDD1oJoA7BEYw/Fbrw== dependencies: "@types/eslint-scope" "^3.7.0" "@types/estree" "^0.0.50" @@ -8506,12 +7728,12 @@ webpack@5.50.0: acorn-import-assertions "^1.7.6" browserslist "^4.14.5" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.8.0" - es-module-lexer "^0.7.1" + enhanced-resolve "^5.8.3" + es-module-lexer "^0.9.0" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" - graceful-fs "^4.2.4" + graceful-fs "^4.2.9" json-parse-better-errors "^1.0.2" loader-runner "^4.2.0" mime-types "^2.1.27" @@ -8519,8 +7741,8 @@ webpack@5.50.0: schema-utils "^3.1.0" tapable "^2.1.1" terser-webpack-plugin "^5.1.3" - watchpack "^2.2.0" - webpack-sources "^3.2.0" + watchpack "^2.3.1" + webpack-sources "^3.2.3" websocket-driver@>=0.5.1, websocket-driver@^0.7.4: version "0.7.4" @@ -8548,19 +7770,19 @@ which@^1.2.9: dependencies: isexe "^2.0.0" -which@^2.0.2: +which@^2.0.1, which@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== +wide-align@^1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== dependencies: - string-width "^1.0.2 || 2" + string-width "^1.0.2 || 2 || 3 || 4" wildcard@^2.0.0: version "2.0.0" @@ -8575,15 +7797,6 @@ wrap-ansi@^2.0.0: string-width "^1.0.1" strip-ansi "^3.0.1" -wrap-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== - dependencies: - ansi-styles "^3.2.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" - wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -8598,13 +7811,18 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -ws@^6.0.0, ws@^6.2.1: +ws@^6.0.0: version "6.2.2" resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.2.tgz#dd5cdbd57a9979916097652d78f1cc5faea0c32e" integrity sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw== dependencies: async-limiter "~1.0.0" +ws@^8.1.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== + xhr2@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.2.1.tgz#4e73adc4f9cfec9cbd2157f73efdce3a5f108a93" @@ -8623,7 +7841,7 @@ xmlbuilder@~11.0.0: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== -"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: +"y18n@^3.2.1 || ^4.0.0": version "4.0.3" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== @@ -8638,7 +7856,7 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^1.10.0, yaml@^1.10.2: +yaml@^1.10.0: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== @@ -8651,18 +7869,10 @@ yargs-parser@^11.1.1: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^13.1.2: - version "13.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" - integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs-parser@^20.2.2: - version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== +yargs-parser@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.0.tgz#a485d3966be4317426dd56bdb6a30131b281dc55" + integrity sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA== yargs@^12.0.5: version "12.0.5" @@ -8682,34 +7892,18 @@ yargs@^12.0.5: y18n "^3.2.1 || ^4.0.0" yargs-parser "^11.1.1" -yargs@^13.2.4, yargs@^13.3.2: - version "13.3.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" - integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.2" - -yargs@^17.0.0: - version "17.2.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.2.1.tgz#e2c95b9796a0e1f7f3bf4427863b42e0418191ea" - integrity sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q== +yargs@^17.2.1, yargs@^17.3.1: + version "17.3.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.3.1.tgz#da56b28f32e2fd45aefb402ed9c26f42be4c07b9" + integrity sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA== dependencies: cliui "^7.0.2" escalade "^3.1.1" get-caller-file "^2.0.5" require-directory "^2.1.1" - string-width "^4.2.0" + string-width "^4.2.3" y18n "^5.0.5" - yargs-parser "^20.2.2" + yargs-parser "^21.0.0" yn@^2.0.0: version "2.0.0" diff --git a/src/Ombi/Controllers/V1/External/TesterController.cs b/src/Ombi/Controllers/V1/External/TesterController.cs index 13bf44a1d..f18547e0f 100644 --- a/src/Ombi/Controllers/V1/External/TesterController.cs +++ b/src/Ombi/Controllers/V1/External/TesterController.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Security.Principal; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; @@ -48,7 +49,7 @@ namespace Ombi.Controllers.V1.External IPlexApi plex, IEmbyApiFactory emby, IRadarrV3Api radarr, ISonarrApi sonarr, ILogger log, IEmailProvider provider, ICouchPotatoApi cpApi, ITelegramNotification telegram, ISickRageApi srApi, INewsletterJob newsletter, ILegacyMobileNotification mobileNotification, ILidarrApi lidarrApi, IGotifyNotification gotifyNotification, IWhatsAppApi whatsAppApi, OmbiUserManager um, IWebhookNotification webhookNotification, - IJellyfinApi jellyfinApi) + IJellyfinApi jellyfinApi, IPrincipal user) { Service = service; DiscordNotification = notification; @@ -74,6 +75,7 @@ namespace Ombi.Controllers.V1.External UserManager = um; WebhookNotification = webhookNotification; _jellyfinApi = jellyfinApi; + UserPrinciple = user; } private INotificationService Service { get; } @@ -100,6 +102,7 @@ namespace Ombi.Controllers.V1.External private IWhatsAppApi WhatsAppApi { get; } private OmbiUserManager UserManager {get; } private readonly IJellyfinApi _jellyfinApi; + private IPrincipal UserPrinciple { get; } /// /// Sends a test message to discord using the provided settings @@ -283,7 +286,7 @@ namespace Ombi.Controllers.V1.External { Message = "This is just a test! Success!", Subject = $"Ombi: Test", - To = settings.AdminEmail, + To = (await GetCurrentUserAsync()).Email, }; message.Other.Add("PlainTextBody", "This is just a test! Success!"); @@ -298,6 +301,11 @@ namespace Ombi.Controllers.V1.External return true; } + private async Task GetCurrentUserAsync() + { + return await UserManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == UserPrinciple.Identity.Name.ToUpper()); + } + /// /// Checks if we can connect to Plex with the provided settings /// diff --git a/src/Ombi/Controllers/V1/External/TheMovieDbController.cs b/src/Ombi/Controllers/V1/External/TheMovieDbController.cs index f5fdb996f..4017c0b42 100644 --- a/src/Ombi/Controllers/V1/External/TheMovieDbController.cs +++ b/src/Ombi/Controllers/V1/External/TheMovieDbController.cs @@ -39,14 +39,6 @@ namespace Ombi.Controllers.External return keyword == null ? NotFound() : Ok(keyword); } - /// - /// Gets the genres for either Tv or Movies depending on media type - /// - /// Either `tv` or `movie`. - [HttpGet("Genres/{media}")] - public async Task> GetGenres(string media) => - await TmdbApi.GetGenres(media, HttpContext.RequestAborted); - /// /// Searches for the watch providers matching the specified term. /// diff --git a/src/Ombi/Controllers/V1/IdentityController.cs b/src/Ombi/Controllers/V1/IdentityController.cs index fded4cacc..2a71fbbac 100644 --- a/src/Ombi/Controllers/V1/IdentityController.cs +++ b/src/Ombi/Controllers/V1/IdentityController.cs @@ -46,57 +46,36 @@ namespace Ombi.Controllers.V1 [ApiController] public class IdentityController : Controller { - public IdentityController(OmbiUserManager user, IMapper mapper, RoleManager rm, IEmailProvider prov, + public IdentityController(OmbiUserManager user, + RoleManager rm, + IEmailProvider prov, ISettingsService s, ISettingsService c, ISettingsService ombiSettings, IWelcomeEmail welcome, - IMovieRequestRepository m, - ITvRequestRepository t, ILogger l, IPlexApi plexApi, ISettingsService settings, - IRepository requestLog, - IRepository issues, - IRepository issueComments, - IRepository notificationRepository, - IRepository subscriptionRepository, ISettingsService umSettings, IRepository notificationPreferences, IRepository userProfiles, - IMusicRequestRepository musicRepo, - IMovieRequestEngine movieRequestEngine, - ITvRequestEngine tvRequestEngine, - IMusicRequestEngine musicEngine, IUserDeletionEngine deletionEngine, IRequestLimitService requestLimitService, ICacheService cacheService) { UserManager = user; - Mapper = mapper; RoleManager = rm; EmailProvider = prov; EmailSettings = s; CustomizationSettings = c; WelcomeEmail = welcome; - MovieRepo = m; - MusicRepo = musicRepo; - TvRepo = t; _log = l; _plexApi = plexApi; _plexSettings = settings; - _issuesRepository = issues; - _requestLogRepository = requestLog; - _issueCommentsRepository = issueComments; OmbiSettings = ombiSettings; - _requestSubscriptionRepository = subscriptionRepository; - _notificationRepository = notificationRepository; _userManagementSettings = umSettings; - TvRequestEngine = tvRequestEngine; - MovieRequestEngine = movieRequestEngine; _userNotificationPreferences = notificationPreferences; _userQualityProfiles = userProfiles; - MusicRequestEngine = musicEngine; _deletionEngine = deletionEngine; _requestLimitService = requestLimitService; _cacheService = cacheService; @@ -108,27 +87,15 @@ namespace Ombi.Controllers.V1 private readonly ICacheService _cacheService; private RoleManager RoleManager { get; } - private IMapper Mapper { get; } private IEmailProvider EmailProvider { get; } private ISettingsService EmailSettings { get; } private ISettingsService CustomizationSettings { get; } private readonly ISettingsService _userManagementSettings; private ISettingsService OmbiSettings { get; } private IWelcomeEmail WelcomeEmail { get; } - private IMovieRequestRepository MovieRepo { get; } - private ITvRequestRepository TvRepo { get; } - private IMovieRequestEngine MovieRequestEngine { get; } - private IMusicRequestEngine MusicRequestEngine { get; } - private ITvRequestEngine TvRequestEngine { get; } - private IMusicRequestRepository MusicRepo { get; } private readonly ILogger _log; private readonly IPlexApi _plexApi; private readonly ISettingsService _plexSettings; - private readonly IRepository _issuesRepository; - private readonly IRepository _issueCommentsRepository; - private readonly IRepository _requestLogRepository; - private readonly IRepository _notificationRepository; - private readonly IRepository _requestSubscriptionRepository; private readonly IRepository _userNotificationPreferences; private readonly IRepository _userQualityProfiles; @@ -147,7 +114,7 @@ namespace Ombi.Controllers.V1 public async Task CreateWizardUser([FromBody] CreateUserWizardModel user) { var users = UserManager.Users; - if (users.Any(x => x.UserType == UserType.LocalUser)) + if (users.Any(x => x.UserType != UserType.SystemUser)) { // No one should be calling this. Only the wizard return new SaveWizardResult { Result = false, Errors = new List { "Looks like there is an existing user!" } }; @@ -258,6 +225,8 @@ namespace Ombi.Controllers.V1 await CreateRole(OmbiRoles.ReceivesNewsletter); await CreateRole(OmbiRoles.ManageOwnRequests); await CreateRole(OmbiRoles.EditCustomPage); + await CreateRole(OmbiRoles.EditCustomPage); + await CreateRole(OmbiRoles.Request4KMovie); } private async Task CreateRole(string role) diff --git a/src/Ombi/Controllers/V1/JobController.cs b/src/Ombi/Controllers/V1/JobController.cs index 442866762..57ec060a2 100644 --- a/src/Ombi/Controllers/V1/JobController.cs +++ b/src/Ombi/Controllers/V1/JobController.cs @@ -91,6 +91,17 @@ namespace Ombi.Controllers.V1 return true; } + /// + /// Runs the Plex Watchlist Importer + /// + /// + [HttpPost("plexwatchlist")] + public async Task PlexWatchlistImport() + { + await OmbiQuartz.TriggerJob(nameof(IPlexWatchlistImport), "Plex"); + return true; + } + /// /// Runs the Emby User importer /// diff --git a/src/Ombi/Controllers/V1/RequestController.cs b/src/Ombi/Controllers/V1/RequestController.cs index cc686b506..1220c3afc 100644 --- a/src/Ombi/Controllers/V1/RequestController.cs +++ b/src/Ombi/Controllers/V1/RequestController.cs @@ -165,7 +165,7 @@ namespace Ombi.Controllers.V1 [PowerUser] public async Task ApproveMovie([FromBody] MovieUpdateModel model) { - return await MovieRequestEngine.ApproveMovieById(model.Id); + return await MovieRequestEngine.ApproveMovieById(model.Id, model.Is4K); } /// @@ -177,7 +177,7 @@ namespace Ombi.Controllers.V1 [PowerUser] public async Task MarkMovieAvailable([FromBody] MovieUpdateModel model) { - return await MovieRequestEngine.MarkAvailable(model.Id); + return await MovieRequestEngine.MarkAvailable(model.Id, model.Is4K); } /// @@ -189,7 +189,7 @@ namespace Ombi.Controllers.V1 [PowerUser] public async Task MarkMovieUnAvailable([FromBody] MovieUpdateModel model) { - return await MovieRequestEngine.MarkUnavailable(model.Id); + return await MovieRequestEngine.MarkUnavailable(model.Id, model.Is4K); } /// @@ -201,7 +201,7 @@ namespace Ombi.Controllers.V1 [PowerUser] public async Task DenyMovie([FromBody] DenyMovieModel model) { - return await MovieRequestEngine.DenyMovieById(model.Id, model.Reason); + return await MovieRequestEngine.DenyMovieById(model.Id, model.Reason, model.Is4K); } /// @@ -403,7 +403,7 @@ namespace Ombi.Controllers.V1 [PowerUser] public async Task MarkTvAvailable([FromBody] TvUpdateModel model) { - return await TvRequestEngine.MarkAvailable(model.Id); + return await TvRequestEngine.MarkAvailable(model.Id, false); } /// @@ -415,7 +415,7 @@ namespace Ombi.Controllers.V1 [PowerUser] public async Task MarkTvUnAvailable([FromBody] TvUpdateModel model) { - return await TvRequestEngine.MarkUnavailable(model.Id); + return await TvRequestEngine.MarkUnavailable(model.Id, false); } /// diff --git a/src/Ombi/Controllers/V1/SettingsController.cs b/src/Ombi/Controllers/V1/SettingsController.cs index fcd4bb1a4..0892b1dda 100644 --- a/src/Ombi/Controllers/V1/SettingsController.cs +++ b/src/Ombi/Controllers/V1/SettingsController.cs @@ -403,9 +403,13 @@ namespace Ombi.Controllers.V1 /// /// [HttpGet("radarr")] - public async Task RadarrSettings() + public async Task RadarrSettings() { - return await Get(); + return new RadarrCombinedModel + { + Radarr = await Get(), + Radarr4K = await Get(), + }; } /// @@ -474,9 +478,11 @@ namespace Ombi.Controllers.V1 /// The settings. /// [HttpPost("radarr")] - public async Task RadarrSettings([FromBody]RadarrSettings settings) + public async Task RadarrSettings([FromBody]RadarrCombinedModel settings) { - var result = await Save(settings); + var radarrResult = await Save(settings.Radarr); + var radarr4kResult = await Save(settings.Radarr4K); + var result = radarr4kResult && radarrResult; if (result) { _cache.Remove(CacheKeys.RadarrRootProfiles); @@ -620,6 +626,7 @@ namespace Ombi.Controllers.V1 j.MediaDatabaseRefresh = j.MediaDatabaseRefresh.HasValue() ? j.MediaDatabaseRefresh : JobSettingsHelper.MediaDatabaseRefresh(j); j.AutoDeleteRequests = j.AutoDeleteRequests.HasValue() ? j.AutoDeleteRequests : JobSettingsHelper.AutoDeleteRequests(j); j.EmbyRecentlyAddedSync = j.EmbyRecentlyAddedSync.HasValue() ? j.EmbyRecentlyAddedSync : JobSettingsHelper.EmbyRecentlyAddedSync(j); + j.PlexWatchlistImport = j.PlexWatchlistImport.HasValue() ? j.PlexWatchlistImport : JobSettingsHelper.PlexWatchlistImport(j); return j; } diff --git a/src/Ombi/Controllers/V1/TokenController.cs b/src/Ombi/Controllers/V1/TokenController.cs index f9ea57a5c..1dd08fcbe 100644 --- a/src/Ombi/Controllers/V1/TokenController.cs +++ b/src/Ombi/Controllers/V1/TokenController.cs @@ -6,16 +6,16 @@ using System.Security.Claims; using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Options; using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.Tokens; using Ombi.Core.Authentication; using Ombi.Helpers; using Ombi.Models; using Ombi.Models.External; -using Ombi.Models.Identity; using Ombi.Store.Entities; using Ombi.Store.Repository; +using Ombi.Core.Settings; +using Ombi.Settings.Settings.Models; namespace Ombi.Controllers.V1 { @@ -24,21 +24,21 @@ namespace Ombi.Controllers.V1 [ApiController] public class TokenController : ControllerBase { - public TokenController(OmbiUserManager um, IOptions ta, ITokenRepository token, - IPlexOAuthManager oAuthManager, ILogger logger) + public TokenController(OmbiUserManager um, ITokenRepository token, + IPlexOAuthManager oAuthManager, ILogger logger, ISettingsService auth) { _userManager = um; - _tokenAuthenticationOptions = ta.Value; _token = token; _plexOAuthManager = oAuthManager; _log = logger; + _authSettings = auth; } - private readonly TokenAuthentication _tokenAuthenticationOptions; private readonly ITokenRepository _token; private readonly OmbiUserManager _userManager; private readonly IPlexOAuthManager _plexOAuthManager; private readonly ILogger _log; + private readonly ISettingsService _authSettings; /// /// Gets the token. @@ -113,6 +113,7 @@ namespace Ombi.Controllers.V1 { return Unauthorized(); } + return await CreateToken(true, user); } @@ -143,7 +144,6 @@ namespace Ombi.Controllers.V1 var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(StartupSingleton.Instance.SecurityKey)); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); - var token = new JwtSecurityToken( claims: claims, expires: rememberMe ? DateTime.Now.AddYears(1) : DateTime.Now.AddDays(7), @@ -200,6 +200,9 @@ namespace Ombi.Controllers.V1 } } + user.MediaServerToken = account.user.authentication_token; + await _userManager.UpdateAsync(user); + return await CreateToken(true, user); } @@ -272,5 +275,38 @@ namespace Ombi.Controllers.V1 return ip; } + + [HttpPost("header_auth")] + [ProducesResponseType(401)] + [ProducesResponseType(200)] + public async Task HeaderAuth() + { + var authSettings = await _authSettings.GetSettingsAsync(); + _log.LogInformation("Logging with header: " + authSettings.HeaderAuthVariable); + if (authSettings.HeaderAuthVariable != null && authSettings.EnableHeaderAuth) + { + if (Request.HttpContext?.Request?.Headers != null && Request.HttpContext.Request.Headers.ContainsKey(authSettings.HeaderAuthVariable)) + { + var username = Request.HttpContext.Request.Headers[authSettings.HeaderAuthVariable].ToString(); + + // Check if user exists + var user = await _userManager.FindByNameAsync(username); + if (user == null) + { + return new UnauthorizedResult(); + } + + return await CreateToken(true, user); + } + else + { + return new UnauthorizedResult(); + } + } + else + { + return new UnauthorizedResult(); + } + } } } diff --git a/src/Ombi/Controllers/V2/FeaturesController.cs b/src/Ombi/Controllers/V2/FeaturesController.cs new file mode 100644 index 000000000..16c512b8c --- /dev/null +++ b/src/Ombi/Controllers/V2/FeaturesController.cs @@ -0,0 +1,88 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Ombi.Attributes; +using Ombi.Core.Settings; +using Ombi.Settings.Settings.Models; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; + +namespace Ombi.Controllers.V2 +{ + public class FeaturesController : V2Controller + { + private readonly ISettingsService _features; + + public FeaturesController(ISettingsService features) => _features = features; + + [HttpGet] + [AllowAnonymous] + public async Task> GetFeatures() + { + var features = await _features.GetSettingsAsync(); + return PopulateFeatures(features?.Features ?? new List()); + } + + [HttpPost("enable")] + [Admin] + public async Task> Enable([FromBody] FeatureEnablement feature) + { + var featureSettings = await _features.GetSettingsAsync(); + var features = PopulateFeatures(featureSettings?.Features ?? new List()); + var featureToUpdate = features.First(x => x.Name.Equals(feature.Name)); + featureToUpdate.Enabled = true; + + featureSettings.Features = features; + + await _features.SaveSettingsAsync(featureSettings); + + return PopulateFeatures(featureSettings?.Features ?? new List()); + } + + [HttpPost("disable")] + [Admin] + public async Task> Disable([FromBody] FeatureEnablement feature) + { + var featureSettings = await _features.GetSettingsAsync(); + var features = PopulateFeatures(featureSettings?.Features ?? new List()); + var featureToUpdate = features.First(x => x.Name.Equals(feature.Name)); + featureToUpdate.Enabled = false; + + featureSettings.Features = features; + + await _features.SaveSettingsAsync(featureSettings); + + return PopulateFeatures(featureSettings?.Features ?? new List()); + } + + + private List PopulateFeatures(List existingFeatures) + { + var supported = GetSupportedFeatures().ToList(); + if (supported.Count == existingFeatures.Count) + { + return existingFeatures; + } + var diff = supported.Except(existingFeatures.Select(x => x.Name)); + + foreach (var feature in diff) + { + existingFeatures.Add(new FeatureEnablement + { + Name = feature + }); + } + return existingFeatures; + } + + private IEnumerable GetSupportedFeatures() + { + FieldInfo[] fieldInfos = typeof(FeatureNames).GetFields(BindingFlags.Public | + BindingFlags.Static | BindingFlags.FlattenHierarchy); + + return fieldInfos.Where(fi => fi.IsLiteral && !fi.IsInitOnly && fi.FieldType == typeof(string)).Select(x => (string)x.GetValue(x)); + } + } +} diff --git a/src/Ombi/Controllers/V2/RequestsController.cs b/src/Ombi/Controllers/V2/RequestsController.cs index 9f26e95bf..45a060b15 100644 --- a/src/Ombi/Controllers/V2/RequestsController.cs +++ b/src/Ombi/Controllers/V2/RequestsController.cs @@ -203,15 +203,15 @@ namespace Ombi.Controllers.V2 } [PowerUser] - [HttpPost("reprocess/{type}/{requestId}")] - public async Task ReProcessRequest(RequestType type, int requestId) + [HttpPost("reprocess/{type}/{requestId}/{is4K}")] + public async Task ReProcessRequest(RequestType type, int requestId, bool? is4K) { switch (type) { case RequestType.TvShow: - return Ok(await _tvRequestEngine.ReProcessRequest(requestId, HttpContext.RequestAborted)); + return Ok(await _tvRequestEngine.ReProcessRequest(requestId, false, HttpContext.RequestAborted)); case RequestType.Movie: - return Ok(await _movieRequestEngine.ReProcessRequest(requestId, HttpContext.RequestAborted)); + return Ok(await _movieRequestEngine.ReProcessRequest(requestId, is4K ?? false, HttpContext.RequestAborted)); } return BadRequest(); diff --git a/src/Ombi/Controllers/V2/SearchController.cs b/src/Ombi/Controllers/V2/SearchController.cs index ac5905c33..fc970b793 100644 --- a/src/Ombi/Controllers/V2/SearchController.cs +++ b/src/Ombi/Controllers/V2/SearchController.cs @@ -16,6 +16,10 @@ using Ombi.Api.RottenTomatoes.Models; using Ombi.Api.RottenTomatoes; using Ombi.Helpers; +// Due to conflicting Genre models in +// Ombi.TheMovieDbApi.Models and Ombi.Api.TheMovieDb.Models +using Genre = Ombi.TheMovieDbApi.Models.Genre; + namespace Ombi.Controllers.V2 { public class SearchController : V2Controller @@ -55,6 +59,16 @@ namespace Ombi.Controllers.V2 return await _multiSearchEngine.MultiSearch(Uri.UnescapeDataString(searchTerm), filter, Request.HttpContext.RequestAborted); } + /// + /// Gets the genres for either Tv or Movies depending on media type + /// + /// Either `tv` or `movie`. + [HttpGet("Genres/{media}")] + public Task> GetGenres(string media) + { + return _multiSearchEngine.GetGenres(media, HttpContext.RequestAborted); + } + /// /// Returns details for a single movie /// diff --git a/src/Ombi/Extensions/StartupExtensions.cs b/src/Ombi/Extensions/StartupExtensions.cs index e3253045a..296339dd0 100644 --- a/src/Ombi/Extensions/StartupExtensions.cs +++ b/src/Ombi/Extensions/StartupExtensions.cs @@ -41,6 +41,21 @@ namespace Ombi Type = SecuritySchemeType.ApiKey }); + c.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "ApiKey" + } + }, + new string[] {} + } + }); + c.CustomSchemaIds(x => x.FullName); try diff --git a/src/Ombi/Models/MovieUpdateModel.cs b/src/Ombi/Models/MovieUpdateModel.cs index db52d4f2b..72638db98 100644 --- a/src/Ombi/Models/MovieUpdateModel.cs +++ b/src/Ombi/Models/MovieUpdateModel.cs @@ -29,5 +29,6 @@ namespace Ombi.Core.Models.Requests public class MovieUpdateModel { public int Id { get; set; } + public bool Is4K { get; set; } } } \ No newline at end of file diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj index 1f10c1058..69ee6b233 100644 --- a/src/Ombi/Ombi.csproj +++ b/src/Ombi/Ombi.csproj @@ -75,9 +75,10 @@ - + + @@ -95,6 +96,7 @@ + @@ -104,7 +106,7 @@ - + diff --git a/src/Ombi/Properties/launchSettings.json b/src/Ombi/Properties/launchSettings.json index 213b92518..b3899f8c3 100644 --- a/src/Ombi/Properties/launchSettings.json +++ b/src/Ombi/Properties/launchSettings.json @@ -22,7 +22,7 @@ }, "Ombi": { "commandName": "Project", - "commandLineArgs": "--host http://localhost:3577 --demo true", + "commandLineArgs": "--host http://localhost:3577", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }, diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index a37c1d230..9fe01019e 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -49,7 +49,7 @@ namespace Ombi Configuration = builder.Build(); ILogger config = new LoggerConfiguration() - .MinimumLevel.Debug() + .ReadFrom.Configuration(Configuration) .WriteTo.RollingFile(Path.Combine(StoragePath.StoragePath.IsNullOrEmpty() ? env.ContentRootPath : StoragePath.StoragePath, "Logs", "log-{Date}.txt")) .CreateLogger(); diff --git a/src/Ombi/appsettings.Development.json b/src/Ombi/appsettings.Development.json index 645fb3aaa..0a2a2974c 100644 --- a/src/Ombi/appsettings.Development.json +++ b/src/Ombi/appsettings.Development.json @@ -8,5 +8,8 @@ "System.Net.Http.HttpClient.health-checks": "Information", "HealthChecks": "Information" } + }, + "Serilog": { + "MinimumLevel": "Debug" } } diff --git a/src/Ombi/appsettings.json b/src/Ombi/appsettings.json index 869428806..b27b627a9 100644 --- a/src/Ombi/appsettings.json +++ b/src/Ombi/appsettings.json @@ -10,6 +10,9 @@ "HealthChecks": "Warning" } }, + "Serilog": { + "MinimumLevel": "Information" + }, "ApplicationSettings": { "NotificationService": "https://ombinotifications.azurewebsites.net/api/", "OmbiService": "?" diff --git a/src/Ombi/wwwroot/images/trakt.svg b/src/Ombi/wwwroot/images/trakt.svg new file mode 100644 index 000000000..782305d6a --- /dev/null +++ b/src/Ombi/wwwroot/images/trakt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Ombi/wwwroot/translations/bg.json b/src/Ombi/wwwroot/translations/bg.json index 9242cd30a..fd207e4bb 100644 --- a/src/Ombi/wwwroot/translations/bg.json +++ b/src/Ombi/wwwroot/translations/bg.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Продължаване", "Available": "Налично", - "Approved": "Approved", + "Available4K": "Available 4K", + "Approved": "Одобрени", + "Approve4K": "Approve 4K", "Pending": "Pending", "PartiallyAvailable": "Частично налично", "Monitored": "Наблюдавано", @@ -24,8 +26,10 @@ "RequestDenied": "Заявката е отказана", "NotRequested": "Не е заявено", "Requested": "Заявено", + "Requested4K": "Requested 4K", "Search": "Търсене", "Request": "Заявка", + "Request4K": "Request 4K", "Denied": "Отказано", "Approve": "Одобряване", "PartlyAvailable": "Частично налично", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Основна папка", "ChangeQualityProfile": "Профил на качеството", "MarkUnavailable": "Означаване като неналично", + "MarkUnavailable4K": "Mark Unavailable 4K", "MarkAvailable": "Означаване като налично", + "MarkAvailable4K": "Mark Available 4K", "Remove": "Премахване", "Deny": "Отказване", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", "DenyReason": "Причина за отхвърляне", "DeniedReason": "Причина за отхвърляне", "Season": "Сезон", @@ -199,9 +207,13 @@ "RequestPanel": { "Delete": "Изтриване на заявка", "Approve": "Одобряване на заявка", + "Deny": "Deny Request", + "Approve4K": "Approve 4K Request", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Маркиране като налично", "Deleted": "Избраните елементи са изтрити успешно", - "Approved": "Избраните елементи са одобрени успешно" + "Approved": "Избраните елементи са одобрени успешно", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Successfully Approved", "SuccessfullyDeleted": "Request successfully deleted", @@ -212,7 +224,7 @@ "RequestCollection": "Request Collection", "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", "NeedToSelectEpisodes": "You need to select some episodes!", - "RequestAddedSuccessfully": "Request for {{title}} has been added successfully", + "RequestAddedSuccessfully": "Заявката за {{title}} е успешно добавена", "ErrorCodes": { "AlreadyRequested": "This has already been requested", "EpisodesAlreadyRequested": "We already have episodes requested from this series", @@ -295,6 +307,7 @@ }, "MediaDetails": { "Denied": "Отказано", + "Denied4K": "Denied 4K", "Trailers": "Trailers", "RecommendationsTitle": "Препоръчани", "SimilarTitle": "Подобни", @@ -312,7 +325,7 @@ "QualityProfilesSelect": "Изберете профил на качеството", "RootFolderSelect": "Изберете основна папка", "LanguageProfileSelect": "Изберете езиков профил", - "Status": "Status:", + "Status": "Състояние:", "StatusValues": { "Rumored": "Rumored", "Planned": "Planned", @@ -326,23 +339,23 @@ }, "Seasons": "Seasons:", "Episodes": "Episodes:", - "Availability": "Availability:", + "Availability": "Наличност:", "RequestStatus": "Състояние на заявката", - "Quality": "Quality:", - "RootFolderOverride": "Root Folder Override:", - "QualityOverride": "Quality Override:", - "Network": "Network:", - "GenresLabel": "Genres:", - "Genres": "Genres", - "FirstAired": "First Aired:", - "TheatricalRelease": "Release:", - "DigitalRelease": "Digital Release:", - "Votes": "Votes:", - "Runtime": "Runtime:", + "Quality": "Качество:", + "RootFolderOverride": "Ръчно задаване на основната папка:", + "QualityOverride": "Ръчно задаване на качеството:", + "Network": "Мрежа:", + "GenresLabel": "Жанрове:", + "Genres": "Жанрове", + "FirstAired": "Първо излъчено:", + "TheatricalRelease": "Кино премиера:", + "DigitalRelease": "Дигитална версия:", + "Votes": "Гласове:", + "Runtime": "Продължителност:", "Minutes": "{{runtime}} Минути", - "Revenue": "Revenue:", - "Budget": "Budget:", - "Keywords": "Keywords/Tags:", + "Revenue": "Приходи:", + "Budget": "Бюджет:", + "Keywords": "Ключови думи/тагове:", "Casts": { "CastTitle": "В ролите" }, @@ -351,24 +364,26 @@ "FirstSeasonTooltip": "Това ще заяви само първия сезон на това предаване", "LatestSeasonTooltip": "Това ще заяви само последния сезон на това предаване", "NoEpisodes": "За съжаление все още няма данни за епизоди на това предаване!", - "SeasonNumber": "Season {{number}}" + "SeasonNumber": "Сезон {{number}}" }, "SonarrConfiguration": "Конфигурация на Sonarr", "RadarrConfiguration": "Конфигурация на Radarr", "RequestOnBehalf": "Заявете от името на", "PleaseSelectUser": "Моля, изберете потребител", - "StreamingOn": "Streaming On:", - "RequestedBy": "Requested By:", + "StreamingOn": "Поточното изпълнение е включено:", + "RequestedBy": "Заявено от:", "RequestedByOn": "Requested By {{user}} on {{date}}", - "RequestDate": "Request Date:", - "DeniedReason": "Denied Reason:", + "RequestDate": "Дата на заявка:", + "DeniedReason": "Причина за отхвърляне:", "ReProcessRequest": "Повтаряне на заявка", + "ReProcessRequest4K": "Re-Process 4K Request", "Music": { "Type": "Type:", "Country": "Country:", "StartDate": "Start Date:", "EndDate": "EndDate:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Популярни", @@ -408,7 +423,7 @@ "ChangeDetails": "Change Details", "NeedCurrentPassword": "You need your current password to make any changes here", "CurrentPassword": "Current Password", - "EmailAddress": "Email Address", + "EmailAddress": "Електронна поща", "NewPassword": "New Password", "NewPasswordConfirm": "New Password Confirm", "Security": "Security", diff --git a/src/Ombi/wwwroot/translations/cs.json b/src/Ombi/wwwroot/translations/cs.json index b3234f471..c1dec8f37 100644 --- a/src/Ombi/wwwroot/translations/cs.json +++ b/src/Ombi/wwwroot/translations/cs.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Pokračovat", "Available": "Dostupný", + "Available4K": "4K Dostupné", "Approved": "Schváleno", + "Approve4K": "Schválit 4K", "Pending": "Čeká na vyřízení", "PartiallyAvailable": "Částečně dostupné", "Monitored": "Monitorováno", @@ -24,31 +26,33 @@ "RequestDenied": "Žádost zamítnuta", "NotRequested": "Nevyžádáno", "Requested": "Vyžádáno", + "Requested4K": "Požádáno o 4K", "Search": "Hledat", "Request": "Žádost", + "Request4K": "Požádat o 4K", "Denied": "Zamítnuto", "Approve": "Schválit", "PartlyAvailable": "Částečně k dispozici", - "ViewDetails": "View Details", + "ViewDetails": "Zobrazit Podrobnosti", "Errors": { - "Validation": "Please check your entered values" + "Validation": "Zkontrolujte prosím zadané hodnoty" }, - "Cancel": "Cancel", - "Submit": "Submit", - "Update": "Update", - "tvShow": "TV Show", - "movie": "Movie", + "Cancel": "Zrušit", + "Submit": "Potvrdit", + "Update": "Upravit", + "tvShow": "TV Pořad", + "movie": "Film", "album": "Album" }, "PasswordReset": { - "EmailAddressPlaceholder": "Email Address", - "ResetPasswordButton": "Reset Password" + "EmailAddressPlaceholder": "Emailová Adresa", + "ResetPasswordButton": "Obnovit Heslo" }, "LandingPage": { - "OnlineHeading": "Currently Online", - "OnlineParagraph": "The media server is currently online", - "PartiallyOnlineHeading": "Partially Online", - "PartiallyOnlineParagraph": "The media server is partially online.", + "OnlineHeading": "Právě Online", + "OnlineParagraph": "Server je momentálně offline", + "PartiallyOnlineHeading": "Částečně online", + "PartiallyOnlineParagraph": "Mediální server je částečně online.", "MultipleServersUnavailable": "There are {{serversUnavailable}} servers offline out of {{totalServers}}.", "SingleServerUnavailable": "There is {{serversUnavailable}} server offline out of {{totalServers}}.", "OfflineHeading": "Currently Offline", @@ -56,172 +60,180 @@ "CheckPageForUpdates": "Check this page for continuous site updates." }, "ErrorPages": { - "NotFound": "Page not found" + "NotFound": "Stránka nenalezena" }, "NavigationBar": { - "Discover": "Discover", - "Search": "Search", - "Requests": "Requests", - "UserManagement": "Users", - "Issues": "Issues", - "Vote": "Vote", - "Donate": "Donate!", - "DonateLibraryMaintainer": "Donate to Library Maintainer", + "Discover": "Objevit nové", + "Search": "Hledat", + "Requests": "Žádosti", + "UserManagement": "Uživatelé", + "Issues": "Problémy", + "Vote": "Hlasuj", + "Donate": "Přispějte!", + "DonateLibraryMaintainer": "Podpořte správce knihovny", "DonateTooltip": "This is how I convince my wife to let me spend my spare time developing Ombi 😁", "UpdateAvailableTooltip": "Update Available!", - "Settings": "Settings", - "Welcome": "Welcome {{username}}", - "UpdateDetails": "Update Details", - "Logout": "Logout", - "OpenMobileApp": "Open Mobile App", - "RecentlyAdded": "Recently Added", - "ChangeTheme": "Change Theme", - "Calendar": "Calendar", - "UserPreferences": "Preferences", - "FeatureSuggestion": "Features", + "Settings": "Nastavení", + "Welcome": "Vítejte zpět, {{username}}!", + "UpdateDetails": "Upravit detaily", + "Logout": "Odhlásit se", + "OpenMobileApp": "Otevřít mobilní aplikaci", + "RecentlyAdded": "Naposledy přidané", + "ChangeTheme": "Změnit motiv", + "Calendar": "Kalendář", + "UserPreferences": "Nastavení", + "FeatureSuggestion": "Funkce", "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", "Filter": { - "Movies": "Movies", - "TvShows": "TV Shows", - "Music": "Music", - "People": "People" + "Movies": "Filmy", + "TvShows": "TV pořady", + "Music": "Hudba", + "People": "Lidé" }, - "MorningWelcome": "Good morning!", - "AfternoonWelcome": "Good afternoon!", - "EveningWelcome": "Good evening!" + "MorningWelcome": "Dobré ráno!", + "AfternoonWelcome": "Dobré odpoledne!", + "EveningWelcome": "Dobrý večer!" }, "Search": { - "Title": "Search", - "Paragraph": "Want to watch something that is not currently available? No problem, just search for it below and request it!", - "MoviesTab": "Movies", - "TvTab": "TV Shows", - "MusicTab": "Music", - "AdvancedSearch": "You can fill in any of the below to discover new media. All of the results are sorted by popularity", - "AdvancedSearchHeader": "Advanced Search", - "Suggestions": "Suggestions", - "NoResults": "Sorry, we didn't find any results!", - "DigitalDate": "Digital Release: {{date}}", - "TheatricalRelease": "Theatrical Release: {{date}}", - "ViewOnPlex": "Play On Plex", - "ViewOnEmby": "Play On Emby", - "ViewOnJellyfin": "Play On Jellyfin", - "RequestAdded": "Request for {{title}} has been added successfully", - "Similar": "Similar", - "Refine": "Refine", - "SearchBarPlaceholder": "Type Here to Search", + "Title": "Hledat", + "Paragraph": "Chcete sledovat něco co je aktuálně nedostupné? Není problém, zkuste to najít a požádat o to!", + "MoviesTab": "Filmy", + "TvTab": "TV pořady", + "MusicTab": "Hudba", + "AdvancedSearch": "Můžete vyplnit některou z níže uvedených možností pro objevení nových médií. Všechny výsledky jsou seřazeny podle oblíbenosti", + "AdvancedSearchHeader": "Pokročilé vyhledávání", + "Suggestions": "Návrhy", + "NoResults": "Omlouváme se, ale nenašli jsme žádné výsledky!", + "DigitalDate": "Digitální vydání: {{date}}", + "TheatricalRelease": "V kinech: {{date}}", + "ViewOnPlex": "Přehrát v Plex", + "ViewOnEmby": "Přehrát v Emby", + "ViewOnJellyfin": "Přehrát v Jellyfiny", + "RequestAdded": "Žádost o {{title}} byl úspěšně přidán", + "Similar": "Podobné", + "Refine": "Zpřesnit", + "SearchBarPlaceholder": "Pište sem pro vyhledávání", "Movies": { - "PopularMovies": "Popular Movies", - "UpcomingMovies": "Upcoming Movies", - "TopRatedMovies": "Top Rated Movies", - "NowPlayingMovies": "Now Playing Movies", - "HomePage": "Home Page", - "Trailer": "Trailer" + "PopularMovies": "Populární filmy", + "UpcomingMovies": "Nadcházející filmy", + "TopRatedMovies": "Nejlépe hodnocené filmy", + "NowPlayingMovies": "Právě hrajeme", + "HomePage": "Úvodní stránka", + "Trailer": "Upoutávka" }, "TvShows": { - "Popular": "Popular", - "Trending": "Trending", - "MostWatched": "Most Watched", - "MostAnticipated": "Most Anticipated", - "Results": "Results", - "AirDate": "Air Date:", - "AllSeasons": "All Seasons", - "FirstSeason": "First Season", - "LatestSeason": "Latest Season", - "Select": "Select ...", - "SubmitRequest": "Submit Request", - "Season": "Season {{seasonNumber}}", - "SelectAllInSeason": "Select All in Season {{seasonNumber}}" + "Popular": "Oblíbené", + "Trending": "Žhavé", + "MostWatched": "Nejsledovanější", + "MostAnticipated": "Nejočekávanější", + "Results": "Výsledky", + "AirDate": "Odvysíláno:", + "AllSeasons": "Všechny série", + "FirstSeason": "První série", + "LatestSeason": "Nejnovější série", + "Select": "Vyberte ...", + "SubmitRequest": "Odeslat žádost", + "Season": "Série {{seasonNumber}}", + "SelectAllInSeason": "Vybrat vše v sérii {{seasonNumber}}" }, - "AdvancedSearchInstructions": "Please choose what type of media you are searching for:", - "YearOfRelease": "Year of Release", - "SearchGenre": "Search Genre", - "SearchKeyword": "Search Keyword", + "AdvancedSearchInstructions": "Vyberte prosím jaký typ médií hledáte:", + "YearOfRelease": "Rok vydání", + "SearchGenre": "Vyhledávání podle žánru", + "SearchKeyword": "Vyhledávání podle klíčových slov", "SearchProvider": "Search Provider", "KeywordSearchingDisclaimer": "Please note that Keyword Searching is very hit and miss due to the inconsistent data in TheMovieDb" }, "Requests": { - "Title": "Requests", + "Title": "Žádosti", "Paragraph": "Below you can see yours and all other requests, as well as their download and approval status.", - "MoviesTab": "Movies", - "ArtistName": "Artist", - "AlbumName": "Album Name", - "TvTab": "TV Shows", - "MusicTab": "Music", - "RequestedBy": "Requested By", - "Status": "Status", - "RequestStatus": "Request status", - "Denied": " Denied:", - "TheatricalRelease": "Theatrical Release: {{date}}", - "ReleaseDate": "Released: {{date}}", - "TheatricalReleaseSort": "Theatrical Release", - "DigitalRelease": "Digital Release: {{date}}", - "RequestDate": "Request Date", + "MoviesTab": "Filmy", + "ArtistName": "Umělec", + "AlbumName": "Název alba", + "TvTab": "TV pořady", + "MusicTab": "Hudba", + "RequestedBy": "Požadováno od", + "Status": "Stav", + "RequestStatus": "Stav požadavku", + "Denied": " Zamítnuto:", + "TheatricalRelease": "V kinech od: {{date}}", + "ReleaseDate": "Vydáno: {{date}}", + "TheatricalReleaseSort": "Vydáno v Kinech", + "DigitalRelease": "Digitální vydání: {{date}}", + "RequestDate": "Datum požadavku", "QualityOverride": "Quality Override:", "RootFolderOverride": "Root Folder Override:", "ChangeRootFolder": "Root Folder", "ChangeQualityProfile": "Quality Profile", - "MarkUnavailable": "Mark Unavailable", - "MarkAvailable": "Mark Available", - "Remove": "Remove", - "Deny": "Deny", - "DenyReason": "Deny Reason", - "DeniedReason": "Denied Reason", - "Season": "Season", - "GridTitle": "Title", - "AirDate": "Air Date", - "GridStatus": "Status", - "ReportIssue": "Report Issue", - "Filter": "Filter", - "Sort": "Sort", - "SeasonNumberHeading": "Season: {seasonNumber}", - "SortTitleAsc": "Title ▲", - "SortTitleDesc": "Title ▼", - "SortRequestDateAsc": "Request Date ▲", - "SortRequestDateDesc": "Request Date ▼", - "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼", + "MarkUnavailable": "Označit jako nedostupné", + "MarkUnavailable4K": "Označit jako nedostupné ve 4K", + "MarkAvailable": "Označit jako dostupné", + "MarkAvailable4K": "Označit jako dostupné ve 4K", + "Remove": "Odstranit", + "Deny": "Zamítnout", + "Deny4K": "Zamítnout 4 K", + "Has4KRequest": "Má 4K požadavek", + "DenyReason": "Důvod zamítnutí", + "DeniedReason": "Důvod zamítnutí", + "Season": "Série", + "GridTitle": "Název", + "AirDate": "Odvysíláno", + "GridStatus": "Stav", + "ReportIssue": "Nahlásit problém", + "Filter": "Třídit", + "Sort": "Seřadit", + "SeasonNumberHeading": "Série: {{seasonNumber}}", + "SortTitleAsc": "Název ▲", + "SortTitleDesc": "Název ▼", + "SortRequestDateAsc": "Datum žádosti ▲", + "SortRequestDateDesc": "Datum žádosti ▼", + "SortStatusAsc": "Stav ▲", + "SortStatusDesc": "Stav ▼", "Remaining": { - "Quota": "{{remaining}}/{{total}} requests remaining", + "Quota": "Zbývá {{remaining}}/{{total}} požadavků", "NextDays": "Another request will be added in {{time}} days", "NextHours": "Another request will be added in {{time}} hours", "NextMinutes": "Another request will be added in {{time}} minutes", "NextMinute": "Another request will be added in {{time}} minute" }, - "AllRequests": "All Requests", - "PendingRequests": "Pending Requests", - "ProcessingRequests": "Processing Requests", - "AvailableRequests": "Available Requests", - "DeniedRequests": "Denied Requests", - "RequestsToDisplay": "Requests to display", - "RequestsTitle": "Title", - "Details": "Details", - "Options": "Options", + "AllRequests": "Všechny požadavky", + "PendingRequests": "Nevyřízené požadavky", + "ProcessingRequests": "Zpracovávání požadavku", + "AvailableRequests": "Dostupné požadavky", + "DeniedRequests": "Zamítnuté požadavky", + "RequestsToDisplay": "Požadavky na zobrazení", + "RequestsTitle": "Název", + "Details": "Podrobnosti", + "Options": "Možnosti", "RequestPanel": { - "Delete": "Delete Request", - "Approve": "Approve Request", - "ChangeAvailability": "Mark Available", - "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Delete": "Odstranit požadavek", + "Approve": "Schválit požadavek", + "Deny": "Deny Request", + "Approve4K": "Schválit 4K požadavek", + "Deny4K": "Deny 4K Request", + "ChangeAvailability": "Označit jako dostupné", + "Deleted": "Vybrané položky úspěšně odstraněny", + "Approved": "Vybrané položky byly úspěšně schváleny", + "Denied": "Successfully denied selected items" }, - "SuccessfullyApproved": "Successfully Approved", - "SuccessfullyDeleted": "Request successfully deleted", - "NowAvailable": "Request is now available", - "NowUnavailable": "Request is now unavailable", - "SuccessfullyReprocessed": "Successfully Re-processed the request", - "DeniedRequest": "Denied Request", - "RequestCollection": "Request Collection", - "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", - "NeedToSelectEpisodes": "You need to select some episodes!", - "RequestAddedSuccessfully": "Request for {{title}} has been added successfully", + "SuccessfullyApproved": "Úspěšně schváleno", + "SuccessfullyDeleted": "Požadavek byl úspěšně odstraněn", + "NowAvailable": "Požadavek je nyní k dispozici", + "NowUnavailable": "Požadavek je nyní nedostupný", + "SuccessfullyReprocessed": "Požadavek úspěšně znovu zprocesován", + "DeniedRequest": "Odmítnutý požadavek", + "RequestCollection": "Požádat o kolekci", + "CollectionSuccesfullyAdded": "Kolekce {{name}} byla úspěšně přidána!", + "NeedToSelectEpisodes": "Musíte vybrat nějaké epizody!", + "RequestAddedSuccessfully": "Žádost o {{title}} byla úspěšně přidána", "ErrorCodes": { - "AlreadyRequested": "This has already been requested", - "EpisodesAlreadyRequested": "We already have episodes requested from this series", + "AlreadyRequested": "O toto již bylo požádáno", + "EpisodesAlreadyRequested": "Již máme epizody od této série vyžádány", "NoPermissionsOnBehalf": "You do not have the correct permissions to request on behalf of users!", - "NoPermissions": "You do not have the correct permissions!", - "RequestDoesNotExist": "Request does not exist", + "NoPermissions": "Nemáte dostatečná oprávnění!", + "RequestDoesNotExist": "Požadavek neexistuje", "ChildRequestDoesNotExist": "Child Request does not exist", - "NoPermissionsRequestMovie": "You do not have permissions to Request a Movie", - "NoPermissionsRequestTV": "You do not have permissions to Request a TV Show", + "NoPermissionsRequestMovie": "Nemáte oprávnění k vyžádání filmu", + "NoPermissionsRequestTV": "Nemáte oprávnění požádat o TV Pořad", "NoPermissionsRequestAlbum": "You do not have permissions to Request an Album", "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", @@ -239,197 +251,200 @@ "PendingTitle": "Pending Issues", "InProgressTitle": "In Progress Issues", "ResolvedTitle": "Resolved Issues", - "ColumnTitle": "Title", - "Count": "Count", - "Category": "Category", - "Status": "Status", - "Details": "Details", - "Description": "Description", - "NoComments": "No Comments!", - "MarkInProgress": "Mark In Progress", - "MarkResolved": "Mark Resolved", - "SendMessageButton": "Send", - "Subject": "Subject", - "Comments": "Comments", - "WriteMessagePlaceholder": "Write your message here...", - "ReportedBy": "Reported By", + "ColumnTitle": "Název", + "Count": "Počet", + "Category": "Kategorie", + "Status": "Stav", + "Details": "Podrobnosti", + "Description": "Popis", + "NoComments": "Žádné komentáře!", + "MarkInProgress": "Označit jako probíhající", + "MarkResolved": "Označit jako vyřešené", + "SendMessageButton": "Odeslat", + "Subject": "Předmět", + "Comments": "Komentáře", + "WriteMessagePlaceholder": "Sem napište zprávu…", + "ReportedBy": "Nahlášeno", "IssueDialog": { - "Title": "Report an issue", - "DescriptionPlaceholder": "Please describe the issue", - "TitlePlaceholder": "Short title of your issue", - "SelectCategory": "Select Category", - "IssueCreated": "Issue has been created" + "Title": "Náhlásit chybu", + "DescriptionPlaceholder": "Popište problém", + "TitlePlaceholder": "Krátký název vašeho problému", + "SelectCategory": "Vybrat kategorii", + "IssueCreated": "Problém byl vytvořen" }, "Outstanding": "There are outstanding issues", "ResolvedDate": "Resolved date", "CreatedDate": "Raised on", "MarkedAsResolved": "This issue has now been marked as resolved!", "MarkedAsInProgress": "This issue has now been marked as in progress!", - "Delete": "Delete issue", + "Delete": "Smazat případ", "DeletedIssue": "Issue has been deleted", "Chat": "Chat", "EnterYourMessage": "Enter Your Message", - "Requested": "Requested", - "UserOnDate": "{{user}} on {{date}}" + "Requested": "Vyžádáno", + "UserOnDate": "{{user}} dne {{date}}" }, "Filter": { - "ClearFilter": "Clear Filter", - "FilterHeaderAvailability": "Availability", - "FilterHeaderRequestStatus": "Status", - "Approved": "Approved", - "PendingApproval": "Pending Approval", - "WatchProviders": "Watch Providers", - "Keywords": "Keywords" + "ClearFilter": "Zrušit filtry", + "FilterHeaderAvailability": "Dostupnost", + "FilterHeaderRequestStatus": "Stav", + "Approved": "Schváleno", + "PendingApproval": "Čeká na schválení", + "WatchProviders": "Online poskytovatelé", + "Keywords": "Klíčová slova" }, "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} remaining", - "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", - "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", + "TvRemaining": "TV: {{remaining}}/{{total}} zbývá", + "MovieRemaining": "Filmy: {{remaining}}/{{total}} zbývá", + "MusicRemaining": "Hudba: {{remaining}}/{{total}} zbývá", "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}", - "MusicDue": "Music: {{date}}" + "MovieDue": "Film: {{date}}", + "MusicDue": "Hudba: {{date}}" }, "Votes": { - "CompletedVotesTab": "Voted", - "VotesTab": "Votes Needed" + "CompletedVotesTab": "Odhlasováno", + "VotesTab": "Potřebné hlasy" }, "MediaDetails": { - "Denied": "Denied", - "Trailers": "Trailers", - "RecommendationsTitle": "Recommendations", - "SimilarTitle": "Similar", - "VideosTitle": "Videos", - "AlbumsTitle": "Albums", - "RequestAllAlbums": "Request All Albums", - "ClearSelection": "Clear Selection", - "RequestSelectedAlbums": "Request Selected Albums", - "ViewCollection": "View Collection", - "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", - "AdvancedOptions": "Advanced Options", + "Denied": "Zamítnuto", + "Denied4K": "4K Zamítnuto", + "Trailers": "Upoutávky", + "RecommendationsTitle": "Doporučení", + "SimilarTitle": "Podobné", + "VideosTitle": "Videa", + "AlbumsTitle": "Alba", + "RequestAllAlbums": "Požádat o všechna alba", + "ClearSelection": "Vyčistit výběr", + "RequestSelectedAlbums": "Požádat o vybraná alba", + "ViewCollection": "Zobrazit kolekci", + "NotEnoughInfo": "Bohužel o tomto seriálu zatím není dostatek informací!", + "AdvancedOptions": "Pokročilá nastavení", "AutoApproveOptions": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! Please note, this is optional, just press Request to skip!", "AutoApproveOptionsTv": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", "AutoApproveOptionsTvShort": "You can configure the request here, once requested it will be sent to your DVR application! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", - "QualityProfilesSelect": "Select A Quality Profile", - "RootFolderSelect": "Select A Root Folder", - "LanguageProfileSelect": "Select A Language Profile", - "Status": "Status:", + "QualityProfilesSelect": "Vyberte Profil kvality", + "RootFolderSelect": "Vyberte kořenovou složku", + "LanguageProfileSelect": "Vyberte jazykový profil", + "Status": "Stav:", "StatusValues": { "Rumored": "Rumored", - "Planned": "Planned", - "In Production": "In Production", - "Post Production": "Post Production", - "Released": "Released", - "Running": "Running", - "Returning Series": "Returning Series", - "Ended": "Ended", - "Canceled": "Canceled" + "Planned": "Naplánováno", + "In Production": "V produkci", + "Post Production": "V post-produkci", + "Released": "Vydáno", + "Running": "Právě probíhá", + "Returning Series": "Vracející se seriál", + "Ended": "Ukončeno", + "Canceled": "Zrušeno" }, - "Seasons": "Seasons:", - "Episodes": "Episodes:", - "Availability": "Availability:", - "RequestStatus": "Request Status", - "Quality": "Quality:", + "Seasons": "Série:", + "Episodes": "Epizody:", + "Availability": "Dostupnost:", + "RequestStatus": "Stav požadavku", + "Quality": "Kvalita:", "RootFolderOverride": "Root Folder Override:", "QualityOverride": "Quality Override:", - "Network": "Network:", - "GenresLabel": "Genres:", - "Genres": "Genres", - "FirstAired": "First Aired:", - "TheatricalRelease": "Release:", - "DigitalRelease": "Digital Release:", - "Votes": "Votes:", - "Runtime": "Runtime:", - "Minutes": "{{runtime}} Minutes", - "Revenue": "Revenue:", - "Budget": "Budget:", - "Keywords": "Keywords/Tags:", + "Network": "Síť:", + "GenresLabel": "Žánry:", + "Genres": "Žánry", + "FirstAired": "Poprvé vysíláno:", + "TheatricalRelease": "Vydáno:", + "DigitalRelease": "Digitální vydání:", + "Votes": "Hlasy:", + "Runtime": "Délka:", + "Minutes": "{{runtime}} minut", + "Revenue": "Příjmy:", + "Budget": "Rozpočet:", + "Keywords": "Klíčová slova/Tagy:", "Casts": { - "CastTitle": "Cast" + "CastTitle": "Hrají" }, "EpisodeSelector": { - "AllSeasonsTooltip": "This will request every season for this show", - "FirstSeasonTooltip": "This will only request the First Season for this show", - "LatestSeasonTooltip": "This will only request the Latest Season for this show", + "AllSeasonsTooltip": "Toto vyžádá všechny serie pro tento pořad", + "FirstSeasonTooltip": "Toto vyžádá jen první sérii pro tento pořad", + "LatestSeasonTooltip": "Toto vyžádá jen poslední sérii pro tento pořad", "NoEpisodes": "There unfortunately is no episode data for this show yet!", - "SeasonNumber": "Season {{number}}" + "SeasonNumber": "Série {{number}}" }, "SonarrConfiguration": "Sonarr Configuration", "RadarrConfiguration": "Radarr Configuration", "RequestOnBehalf": "Request on behalf of", "PleaseSelectUser": "Please select a user", - "StreamingOn": "Streaming On:", - "RequestedBy": "Requested By:", - "RequestedByOn": "Requested By {{user}} on {{date}}", - "RequestDate": "Request Date:", - "DeniedReason": "Denied Reason:", - "ReProcessRequest": "Re-Process Request", + "StreamingOn": "Streamuje na:", + "RequestedBy": "Požadováno od:", + "RequestedByOn": "Požádáno uživatelem {{user}} dne {{date}}", + "RequestDate": "Datum požadavku:", + "DeniedReason": "Důvod zamítnutí:", + "ReProcessRequest": "Znovu zpracovat žádost", + "ReProcessRequest4K": "Znovu zpracovat 4K žádost", "Music": { - "Type": "Type:", - "Country": "Country:", - "StartDate": "Start Date:", - "EndDate": "EndDate:" - } + "Type": "Typ:", + "Country": "Stát:", + "StartDate": "Datum zahájení:", + "EndDate": "Datum ukončení:" + }, + "RequestSource": "Source:" }, "Discovery": { - "PopularTab": "Popular", - "TrendingTab": "Trending", - "UpcomingTab": "Upcoming", - "SeasonalTab": "Seasonal", - "RecentlyRequestedTab": "Recently Requested", - "Movies": "Movies", - "Combined": "Combined", + "PopularTab": "Oblíbené", + "TrendingTab": "Žhavé", + "UpcomingTab": "Nadcházející", + "SeasonalTab": "Sezónní", + "RecentlyRequestedTab": "Nedávno vyžádané", + "Movies": "Filmy", + "Combined": "Kombinované", "Tv": "TV", "CardDetails": { - "Availability": "Availability", + "Availability": "Dostupnost", "Studio": "Studio", - "Network": "Network", - "UnknownNetwork": "Unknown", - "RequestStatus": "Request Status", - "Director": "Director", - "InCinemas": "In Cinemas", - "FirstAired": "First Aired", - "Writer": "Writer", - "ExecProducer": "Exec Producer" + "Network": "Síť", + "UnknownNetwork": "Neznámé", + "RequestStatus": "Stav požadavku", + "Director": "Režisér", + "InCinemas": "V Kinech", + "FirstAired": "Poprvé vysíláno", + "Writer": "Autor", + "ExecProducer": "Exekutivní Producent" }, - "NoSearch": "Sorry, nothing matches your search!" + "NoSearch": "Vašemu hledání neodpovídají žádné shody!" }, "UserPreferences": { - "Welcome": "Welcome {{username}}!", - "OmbiLanguage": "Language", - "DarkMode": "Dark Mode", - "Updated": "Successfully Updated", + "Welcome": "Vítejte, {{username}}!", + "OmbiLanguage": "Jazyk", + "DarkMode": "Tmavý režim", + "Updated": "Úspěšně upraveno", "StreamingCountry": "Streaming Country", "StreamingCountryDescription": "This is the country code that we will display streaming information for. If you are in the US please select US and you will get US related streaming information.", "LanguageDescription": "This is the language you would like the Ombi interface to be displayed in.", - "MobileQRCode": "Mobile QR Code", + "MobileQRCode": "Mobilní QR Code", "LegacyApp": "Launch Legacy App", - "NoQrCode": "Please contact your administrator to enable QR codes", - "UserType": "User Type:", - "ChangeDetails": "Change Details", - "NeedCurrentPassword": "You need your current password to make any changes here", - "CurrentPassword": "Current Password", - "EmailAddress": "Email Address", - "NewPassword": "New Password", - "NewPasswordConfirm": "New Password Confirm", - "Security": "Security", - "Profile": "Profile", - "UpdatedYourInformation": "Updated your information", - "Unsubscribed": "Unsubscribed!" + "NoQrCode": "Pro povolení QR kódů kontaktujte svého administrátora", + "UserType": "Typ uživatele:", + "ChangeDetails": "Změnit podrobnosti", + "NeedCurrentPassword": "K provedení změn potřebujete své současné heslo", + "CurrentPassword": "Aktuální heslo", + "EmailAddress": "Emailová Adresa", + "NewPassword": "Nové heslo", + "NewPasswordConfirm": "Potvrzení nového hesla", + "Security": "Bezpečnost", + "Profile": "Profil", + "UpdatedYourInformation": "Informace aktualizovány", + "Unsubscribed": "Odhlášeno!" }, "UserTypeLabel": { - "1": "Local User", - "2": "Plex User", + "1": "Místní Uživatel", + "2": "Plex uživatel", "3": "Emby User", - "4": "Emby Connect User", - "5": "Jellyfin User" + "4": "Emby Connect uživatel", + "5": "Jellyfin uživatel" }, "Paginator": { - "itemsPerPageLabel": "Items per page:", - "nextPageLabel": "Next page", - "previousPageLabel": "Previous page", - "firstPageLabel": "First page", - "lastPageLabel": "Last page", - "rangePageLabel1": "0 of {{length}}", - "rangePageLabel2": "{{startIndex}} – {{endIndex}} of {{length}}" + "itemsPerPageLabel": "Položek na stránce:", + "nextPageLabel": "Další stránka", + "previousPageLabel": "Předchozí stránka", + "firstPageLabel": "První stránka", + "lastPageLabel": "Poslední strana", + "rangePageLabel1": "0 z {{length}}", + "rangePageLabel2": "{{startIndex}} – {{endIndex}} z {{length}}" } } diff --git a/src/Ombi/wwwroot/translations/da.json b/src/Ombi/wwwroot/translations/da.json index 1598df272..1486bcfae 100644 --- a/src/Ombi/wwwroot/translations/da.json +++ b/src/Ombi/wwwroot/translations/da.json @@ -4,8 +4,8 @@ "UsernamePlaceholder": "Brugernavn", "PasswordPlaceholder": "Adgangskode", "RememberMe": "Husk mig", - "SignInWith": "Sign in with {{appName}}", - "SignInWithPlex": "Sign in with Plex", + "SignInWith": "Log ind med {{appName}}", + "SignInWithPlex": "Log ind med Plex", "ForgottenPassword": "Glemt adgangskode?", "Errors": { "IncorrectCredentials": "Forkert brugernavn eller adgangskode" @@ -14,8 +14,10 @@ "Common": { "ContinueButton": "Fortsæt", "Available": "Tilgængelig", - "Approved": "Approved", - "Pending": "Pending", + "Available4K": "Tilgængelig 4K", + "Approved": "Godkendt", + "Approve4K": "Godkend 4K", + "Pending": "Afventer", "PartiallyAvailable": "Delvist tilgængelig", "Monitored": "Overvåget", "NotAvailable": "Ikke tilgængelig", @@ -24,20 +26,22 @@ "RequestDenied": "Anmodning afvist", "NotRequested": "Ikke anmodet", "Requested": "Anmodet", - "Search": "Search", + "Requested4K": "Anmodet 4K", + "Search": "Søg", "Request": "Anmod", + "Request4K": "Anmod 4K", "Denied": "Afvist", "Approve": "Godkendt", "PartlyAvailable": "Delvist tilgængelig", - "ViewDetails": "View Details", + "ViewDetails": "Vis detaljer", "Errors": { "Validation": "Tjek venligst dine indtastede værdier" }, - "Cancel": "Cancel", - "Submit": "Submit", - "Update": "Update", - "tvShow": "TV Show", - "movie": "Movie", + "Cancel": "Annuller", + "Submit": "Send", + "Update": "Opdater", + "tvShow": "TV-Serier", + "movie": "Film", "album": "Album" }, "PasswordReset": { @@ -56,10 +60,10 @@ "CheckPageForUpdates": "Tjek denne side for løbende opdateringer." }, "ErrorPages": { - "NotFound": "Page not found" + "NotFound": "Siden blev ikke fundet" }, "NavigationBar": { - "Discover": "Discover", + "Discover": "Opdag", "Search": "Søg", "Requests": "Anmodninger", "UserManagement": "Brugeradministration", @@ -75,20 +79,20 @@ "Logout": "Log af", "OpenMobileApp": "Åbn mobilapp", "RecentlyAdded": "Senest tilføjet", - "ChangeTheme": "Change Theme", - "Calendar": "Calendar", - "UserPreferences": "Preferences", + "ChangeTheme": "Skift tema", + "Calendar": "Kalender", + "UserPreferences": "Præferencer", "FeatureSuggestion": "Feature Suggestion", - "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", + "FeatureSuggestionTooltip": "Har du en god ny idé? Foreslå den her!", "Filter": { "Movies": "Film", "TvShows": "Tv-serier", "Music": "Musik", - "People": "People" + "People": "Personer" }, - "MorningWelcome": "Good morning!", - "AfternoonWelcome": "Good afternoon!", - "EveningWelcome": "Good evening!" + "MorningWelcome": "Godmorgen!", + "AfternoonWelcome": "Godeftermiddag!", + "EveningWelcome": "Godaften!" }, "Search": { "Title": "Søg", @@ -96,19 +100,19 @@ "MoviesTab": "Film", "TvTab": "Tv-serier", "MusicTab": "Musik", - "AdvancedSearch": "You can fill in any of the below to discover new media. All of the results are sorted by popularity", - "AdvancedSearchHeader": "Advanced Search", + "AdvancedSearch": "Du kan udfylde en eller flere af nedenstående for at opdage nye medier. Alle resultater er sorteret efter popularitet", + "AdvancedSearchHeader": "Avanceret Søgning", "Suggestions": "Forslag", "NoResults": "Beklager, vi fandt ingen resultater!", "DigitalDate": "Digital udgivelse: {{date}}", "TheatricalRelease": "Biografudgivelse: {{date}}", "ViewOnPlex": "Se på Plex", "ViewOnEmby": "Se på Emby", - "ViewOnJellyfin": "Play On Jellyfin", + "ViewOnJellyfin": "Afspil på Jellyfin", "RequestAdded": "{{title}} er anmodet med succes", "Similar": "Lignende", - "Refine": "Refine", - "SearchBarPlaceholder": "Type Here to Search", + "Refine": "Specificer", + "SearchBarPlaceholder": "Indtast her for at søge", "Movies": { "PopularMovies": "Populære film", "UpcomingMovies": "Kommende film", @@ -132,19 +136,19 @@ "Season": "Sæson {{seasonNumber}}", "SelectAllInSeason": "Vælg alle i sæson {{seasonNumber}}" }, - "AdvancedSearchInstructions": "Please choose what type of media you are searching for:", - "YearOfRelease": "Year of Release", - "SearchGenre": "Search Genre", - "SearchKeyword": "Search Keyword", - "SearchProvider": "Search Provider", - "KeywordSearchingDisclaimer": "Please note that Keyword Searching is very hit and miss due to the inconsistent data in TheMovieDb" + "AdvancedSearchInstructions": "Vælg venligst hvilken type medier, du søger efter:", + "YearOfRelease": "Udgivelsesår", + "SearchGenre": "Søg efter genre", + "SearchKeyword": "Søg efter nøgleord", + "SearchProvider": "Søgemaskiner", + "KeywordSearchingDisclaimer": "Bemærk venligst, at Nøgleord-søgning ikke altid er pålideligt grundet de inkonsistente data i TheMovieDb" }, "Requests": { "Title": "Anmodninger", "Paragraph": "Herunder kan du se dine og alle andre anmodninger, samt status for download og godkendelse.", "MoviesTab": "Film", - "ArtistName": "Artist", - "AlbumName": "Album Name", + "ArtistName": "Kunstner", + "AlbumName": "Albumnavn", "TvTab": "Tv-serier", "MusicTab": "Musik", "RequestedBy": "Anmodet af", @@ -161,11 +165,15 @@ "ChangeRootFolder": "Skift rodmappe", "ChangeQualityProfile": "Skift kvalitetsprofil", "MarkUnavailable": "Markér som utilgængelig", + "MarkUnavailable4K": "Marker Utilgængelig 4K", "MarkAvailable": "Markér som tilgængelig", + "MarkAvailable4K": "Marker Tilgængelig 4K", "Remove": "Fjern", "Deny": "Afvis", - "DenyReason": "Deny Reason", - "DeniedReason": "Denied Reason", + "Deny4K": "Afvis 4K", + "Has4KRequest": "Har 4K Anmodning", + "DenyReason": "Afvisningsårsag", + "DeniedReason": "Afvisningsårsag", "Season": "Sæson", "GridTitle": "Titel", "AirDate": "Sendt", @@ -187,60 +195,64 @@ "NextMinutes": "En anden anmodning vil blive tilføjet i {{time}} Minutter", "NextMinute": "En anden anmodning vil blive tilføjet i {{time}} Minut" }, - "AllRequests": "All Requests", - "PendingRequests": "Pending Requests", - "ProcessingRequests": "Processing Requests", - "AvailableRequests": "Available Requests", - "DeniedRequests": "Denied Requests", - "RequestsToDisplay": "Requests to display", + "AllRequests": "Alle anmodninger", + "PendingRequests": "Afventende anmodninger", + "ProcessingRequests": "Behandler anmodninger", + "AvailableRequests": "Tilgængelige anmodninger", + "DeniedRequests": "Afviste anmodninger", + "RequestsToDisplay": "Anmodninger at vise", "RequestsTitle": "Titel", "Details": "Detaljer", - "Options": "Options", + "Options": "Indstillinger", "RequestPanel": { - "Delete": "Delete Request", - "Approve": "Approve Request", - "ChangeAvailability": "Mark Available", - "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Delete": "Slet Anmodning", + "Approve": "Godkend Andmodning", + "Deny": "Deny Request", + "Approve4K": "Godkend 4K Anmodning", + "Deny4K": "Deny 4K Request", + "ChangeAvailability": "Markér som tilgængelig", + "Deleted": "De valgte elementer blev slettet", + "Approved": "De valgte elementer blev godkendt", + "Denied": "Successfully denied selected items" }, - "SuccessfullyApproved": "Successfully Approved", - "SuccessfullyDeleted": "Request successfully deleted", - "NowAvailable": "Request is now available", - "NowUnavailable": "Request is now unavailable", - "SuccessfullyReprocessed": "Successfully Re-processed the request", - "DeniedRequest": "Denied Request", - "RequestCollection": "Request Collection", - "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", - "NeedToSelectEpisodes": "You need to select some episodes!", - "RequestAddedSuccessfully": "Request for {{title}} has been added successfully", + "SuccessfullyApproved": "Godkendt", + "SuccessfullyDeleted": "Anmodningen blev slettet", + "NowAvailable": "Anmodningen er nu tilgængelig", + "NowUnavailable": "Anmodningen er nu utilgængelig", + "SuccessfullyReprocessed": "Anmodningen blev genbehandlet", + "DeniedRequest": "Anmodningen blev afvist", + "RequestCollection": "Anmod Om Samling", + "CollectionSuccesfullyAdded": "Samlingen {{name}} er blevet tilføjet!", + "NeedToSelectEpisodes": "Du skal vælge nogle episoder!", + "RequestAddedSuccessfully": "{{title}} er anmodet med succes", "ErrorCodes": { - "AlreadyRequested": "This has already been requested", - "EpisodesAlreadyRequested": "We already have episodes requested from this series", - "NoPermissionsOnBehalf": "You do not have the correct permissions to request on behalf of users!", - "NoPermissions": "You do not have the correct permissions!", - "RequestDoesNotExist": "Request does not exist", - "ChildRequestDoesNotExist": "Child Request does not exist", - "NoPermissionsRequestMovie": "You do not have permissions to Request a Movie", - "NoPermissionsRequestTV": "You do not have permissions to Request a TV Show", - "NoPermissionsRequestAlbum": "You do not have permissions to Request an Album", - "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", - "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", - "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" + "AlreadyRequested": "Dette er allerede blevet anmodet om", + "EpisodesAlreadyRequested": "Vi har allerede episoder anmodet fra denne serie", + "NoPermissionsOnBehalf": "Du har ikke de korrekte tilladelser til at anmode på vegne af brugere!", + "NoPermissions": "Du har ikke de nødvendige tilladelser!", + "RequestDoesNotExist": "Anmodningen eksisterer ikke", + "ChildRequestDoesNotExist": "Child-anmodning eksisterer ikke", + "NoPermissionsRequestMovie": "Du har ikke tilladelse til at anmode om en film", + "NoPermissionsRequestTV": "Du har ikke tilladelse til at anmode om en tv-serie", + "NoPermissionsRequestAlbum": "Du har ikke tilladelse til at anmode om et album", + "MovieRequestQuotaExceeded": "Du har overskredet din film-anmodningskvote!", + "TvRequestQuotaExceeded": "Du har overskredet din episode-anmodningskvote!", + "AlbumRequestQuotaExceeded": "Du har overskredet din album-anmodningskvote!" }, - "Notify": "Notify", - "RemoveNotification": "Remove Notifications", - "SuccessfulNotify": "You will now be notified for title {{title}}", - "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", - "CouldntNotify": "Couldn't notify title {{title}}" + "Notify": "Giv besked", + "RemoveNotification": "Fjern Notifikationer", + "SuccessfulNotify": "Du vil nu få besked om titlen {{title}}", + "SuccessfulUnNotify": "Du vil ikke længere få besked om titlen {{title}}", + "CouldntNotify": "Titlen {{title}} kunne ikke meddeles" }, "Issues": { "Title": "Problemer", - "IssuesForTitle": "Issues for {{title}}", + "IssuesForTitle": "Problemer for {{title}}", "PendingTitle": "Afventende problemer", "InProgressTitle": "Igangværende probemer", "ResolvedTitle": "Løste problemer", "ColumnTitle": "Titel", - "Count": "Count", + "Count": "Antal", "Category": "Kategori", "Status": "Status", "Details": "Detaljer", @@ -254,23 +266,23 @@ "WriteMessagePlaceholder": "Indtast din besked her...", "ReportedBy": "Anmeldt af", "IssueDialog": { - "Title": "Report an issue", - "DescriptionPlaceholder": "Please describe the issue", - "TitlePlaceholder": "Short title of your issue", - "SelectCategory": "Select Category", - "IssueCreated": "Issue has been created" + "Title": "Rapporter en fejl", + "DescriptionPlaceholder": "Beskriv venligst problemet", + "TitlePlaceholder": "Kort titel på dit problem", + "SelectCategory": "Vælg kategori", + "IssueCreated": "Problemet er oprettet" }, - "Outstanding": "There are outstanding issues", - "ResolvedDate": "Resolved date", - "CreatedDate": "Raised on", - "MarkedAsResolved": "This issue has now been marked as resolved!", - "MarkedAsInProgress": "This issue has now been marked as in progress!", - "Delete": "Delete issue", - "DeletedIssue": "Issue has been deleted", + "Outstanding": "Der er uafklarede problemer", + "ResolvedDate": "Løst dato", + "CreatedDate": "Oprettet den", + "MarkedAsResolved": "Dette problem er nu blevet markeret som løst!", + "MarkedAsInProgress": "Dette problem er markeret som igangværende!", + "Delete": "Slet problem", + "DeletedIssue": "Problemet er slettet", "Chat": "Chat", - "EnterYourMessage": "Enter Your Message", - "Requested": "Requested", - "UserOnDate": "{{user}} on {{date}}" + "EnterYourMessage": "Indtast din besked", + "Requested": "Anmodet", + "UserOnDate": "{{user}} d. {{date}}" }, "Filter": { "ClearFilter": "Nulstil filter", @@ -278,8 +290,8 @@ "FilterHeaderRequestStatus": "Status", "Approved": "Godkendt", "PendingApproval": "Afventer godkendelse", - "WatchProviders": "Watch Providers", - "Keywords": "Keywords" + "WatchProviders": "Vælg udbydere", + "Keywords": "Nøgleord" }, "UserManagment": { "TvRemaining": "Tv: {{remaining}}/{{total}} Resterende", @@ -295,141 +307,144 @@ }, "MediaDetails": { "Denied": "Afvist", + "Denied4K": "Afvist 4K", "Trailers": "Trailers", - "RecommendationsTitle": "Recommendations", + "RecommendationsTitle": "Anbefalinger", "SimilarTitle": "Lignende", - "VideosTitle": "Videos", - "AlbumsTitle": "Albums", - "RequestAllAlbums": "Request All Albums", - "ClearSelection": "Clear Selection", - "RequestSelectedAlbums": "Request Selected Albums", - "ViewCollection": "View Collection", - "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", - "AdvancedOptions": "Advanced Options", - "AutoApproveOptions": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! Please note, this is optional, just press Request to skip!", - "AutoApproveOptionsTv": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", - "AutoApproveOptionsTvShort": "You can configure the request here, once requested it will be sent to your DVR application! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", - "QualityProfilesSelect": "Select A Quality Profile", - "RootFolderSelect": "Select A Root Folder", - "LanguageProfileSelect": "Select A Language Profile", + "VideosTitle": "Video", + "AlbumsTitle": "Album", + "RequestAllAlbums": "Anmod Om Alle Albums", + "ClearSelection": "Ryd valgte", + "RequestSelectedAlbums": "Anmod Om Valgte Album", + "ViewCollection": "Vis Samling", + "NotEnoughInfo": "Der er desværre ikke nok information om dette show endnu!", + "AdvancedOptions": "Avancerede Indstillinger", + "AutoApproveOptions": "Du kan konfigurere anmodningen her. Når du har anmodet, vil den blive sendt til dit DVR program og vil blive godkendt automatisk! Bemærk venligst, at dette er valgfrit. Tryk blot på Anmodning for at springe over!", + "AutoApproveOptionsTv": "Du kan konfigurere anmodningen her. Når du har anmodet vil den blive sendt til dit DVR program og vil blive auto godkendt automatisk! Hvis anmodningen allerede er i Sonarr, vil vi ikke ændre root-mappen eller kvalitetsprofilen, hvis du indstiller den! Bemærk venligst, at dette er valgfrit. Tryk blot på Anmodning om at springe over!", + "AutoApproveOptionsTvShort": "Du kan konfigurere anmodningen her. Når du har anmodet vil den blive sendt til dit DVR program og vil blive auto godkendt automatisk! Hvis anmodningen allerede er i Sonarr, vil vi ikke ændre root-mappen eller kvalitetsprofilen, hvis du indstiller den! Bemærk venligst, at dette er valgfrit. Tryk blot på Anmodning om at springe over!", + "QualityProfilesSelect": "Vælg En kvalitetsprofil", + "RootFolderSelect": "Vælg en root mappe", + "LanguageProfileSelect": "Vælg En Sprogprofil", "Status": "Status:", "StatusValues": { - "Rumored": "Rumored", - "Planned": "Planned", - "In Production": "In Production", - "Post Production": "Post Production", - "Released": "Released", - "Running": "Running", - "Returning Series": "Returning Series", - "Ended": "Ended", - "Canceled": "Canceled" + "Rumored": "Rygtet", + "Planned": "Planlagt", + "In Production": "I Produktion", + "Post Production": "Postproduktion", + "Released": "Udgivet", + "Running": "Aktiv", + "Returning Series": "Tilbagevendende Serier", + "Ended": "Afsluttet", + "Canceled": "Annulleret" }, - "Seasons": "Seasons:", - "Episodes": "Episodes:", - "Availability": "Availability:", - "RequestStatus": "Request Status", - "Quality": "Quality:", - "RootFolderOverride": "Root Folder Override:", - "QualityOverride": "Quality Override:", - "Network": "Network:", - "GenresLabel": "Genres:", - "Genres": "Genres", - "FirstAired": "First Aired:", - "TheatricalRelease": "Release:", - "DigitalRelease": "Digital Release:", - "Votes": "Votes:", - "Runtime": "Runtime:", - "Minutes": "{{runtime}} Minutes", - "Revenue": "Revenue:", + "Seasons": "Sæsoner:", + "Episodes": "Episoder:", + "Availability": "Tilgængelighed:", + "RequestStatus": "Status for anmodning", + "Quality": "Kvalitet:", + "RootFolderOverride": "Tilsidesæt rodmappe:", + "QualityOverride": "Tilsidesæt kvalitet:", + "Network": "Netværk:", + "GenresLabel": "Genre:", + "Genres": "Genre", + "FirstAired": "Sendt første gang:", + "TheatricalRelease": "Biografudgivelse:", + "DigitalRelease": "Digital Udgivelse:", + "Votes": "Stemmer:", + "Runtime": "Spilletid:", + "Minutes": "{{runtime}} minutter", + "Revenue": "Indtægter:", "Budget": "Budget:", - "Keywords": "Keywords/Tags:", + "Keywords": "Nøgleord/Tags:", "Casts": { - "CastTitle": "Cast" + "CastTitle": "Medvirkende" }, "EpisodeSelector": { - "AllSeasonsTooltip": "This will request every season for this show", - "FirstSeasonTooltip": "This will only request the First Season for this show", - "LatestSeasonTooltip": "This will only request the Latest Season for this show", - "NoEpisodes": "There unfortunately is no episode data for this show yet!", - "SeasonNumber": "Season {{number}}" + "AllSeasonsTooltip": "Dette vil anmode om hver sæson for denne tv-serie", + "FirstSeasonTooltip": "Dette vil kun anmode om den første sæson for denne tv-serie", + "LatestSeasonTooltip": "Dette vil kun anmode den seneste sæson for denne tv-serie", + "NoEpisodes": "Der er desværre ingen episode data for denne tv-serie endnu!", + "SeasonNumber": "Sæson {{number}}" }, - "SonarrConfiguration": "Sonarr Configuration", - "RadarrConfiguration": "Radarr Configuration", - "RequestOnBehalf": "Request on behalf of", - "PleaseSelectUser": "Please select a user", - "StreamingOn": "Streaming On:", - "RequestedBy": "Requested By:", - "RequestedByOn": "Requested By {{user}} on {{date}}", - "RequestDate": "Request Date:", - "DeniedReason": "Denied Reason:", - "ReProcessRequest": "Re-Process Request", + "SonarrConfiguration": "Konfiguration Af Sonarr", + "RadarrConfiguration": "Konfiguration Af Radarr", + "RequestOnBehalf": "Anmod på vegne af", + "PleaseSelectUser": "Vælg venligst en bruger", + "StreamingOn": "Streaming På:", + "RequestedBy": "Anmodet af:", + "RequestedByOn": "Anmodet af {{user}} d. {{date}}", + "RequestDate": "Dato for anmodning:", + "DeniedReason": "Afvisningsårsag:", + "ReProcessRequest": "Anmodning Om Genbehandling", + "ReProcessRequest4K": "Genbehandling af 4K Anmodning", "Music": { "Type": "Type:", - "Country": "Country:", - "StartDate": "Start Date:", - "EndDate": "EndDate:" - } + "Country": "Land:", + "StartDate": "Startdato:", + "EndDate": "Slutdato:" + }, + "RequestSource": "Kilde:" }, "Discovery": { "PopularTab": "Populære", "TrendingTab": "Aktuelle", - "UpcomingTab": "Upcoming", - "SeasonalTab": "Seasonal", - "RecentlyRequestedTab": "Recently Requested", + "UpcomingTab": "Kommende", + "SeasonalTab": "Sæsonbestemt", + "RecentlyRequestedTab": "Anmodet For Nyligt", "Movies": "Film", - "Combined": "Combined", + "Combined": "Kombineret", "Tv": "TV", "CardDetails": { "Availability": "Tilgængelighed", - "Studio": "Studio", - "Network": "Network", - "UnknownNetwork": "Unknown", - "RequestStatus": "Request Status", - "Director": "Director", - "InCinemas": "In Cinemas", - "FirstAired": "First Aired", - "Writer": "Writer", - "ExecProducer": "Exec Producer" + "Studio": "Studie", + "Network": "TV-netværk", + "UnknownNetwork": "Ukendt", + "RequestStatus": "Status for anmodning", + "Director": "Instruktør", + "InCinemas": "I Biografer", + "FirstAired": "Sendt første gang", + "Writer": "Skribent", + "ExecProducer": "Producer" }, - "NoSearch": "Sorry, nothing matches your search!" + "NoSearch": "Vi fandt desværre ikke noget, der matcher din søgning!" }, "UserPreferences": { "Welcome": "Velkommen til {{username}}!", - "OmbiLanguage": "Language", - "DarkMode": "Dark Mode", - "Updated": "Successfully Updated", - "StreamingCountry": "Streaming Country", - "StreamingCountryDescription": "This is the country code that we will display streaming information for. If you are in the US please select US and you will get US related streaming information.", - "LanguageDescription": "This is the language you would like the Ombi interface to be displayed in.", - "MobileQRCode": "Mobile QR Code", - "LegacyApp": "Launch Legacy App", - "NoQrCode": "Please contact your administrator to enable QR codes", - "UserType": "User Type:", - "ChangeDetails": "Change Details", - "NeedCurrentPassword": "You need your current password to make any changes here", - "CurrentPassword": "Current Password", - "EmailAddress": "Email Address", - "NewPassword": "New Password", - "NewPasswordConfirm": "New Password Confirm", - "Security": "Security", - "Profile": "Profile", - "UpdatedYourInformation": "Updated your information", - "Unsubscribed": "Unsubscribed!" + "OmbiLanguage": "Sprog", + "DarkMode": "Mørk tilstand", + "Updated": "Opdateret", + "StreamingCountry": "Streaming Land", + "StreamingCountryDescription": "Dette er den landekode, som vi vil vise streaming information for. Hvis du er i USA, skal du vælge USA, og du vil få amerikanske relaterede streaming oplysninger.", + "LanguageDescription": "Dette er det sprog du gerne vil have Ombi grænsefladen skal vises i.", + "MobileQRCode": "Mobil QR Code", + "LegacyApp": "Start Gammel App", + "NoQrCode": "Kontakt venligst din administrator for at få adgang til QR koder", + "UserType": "Brugertype:", + "ChangeDetails": "Ændre detaljer", + "NeedCurrentPassword": "Vi behøver din nuværende adgangskode for at bekræfte dine ændringer", + "CurrentPassword": "Nuværende adgangskode", + "EmailAddress": "E-mail-adresse", + "NewPassword": "Ny adgangskode", + "NewPasswordConfirm": "Bekræft ny adgangskode", + "Security": "Sikkerhed", + "Profile": "Profil", + "UpdatedYourInformation": "Dine informationer blev opdateret", + "Unsubscribed": "Afmeldt!" }, "UserTypeLabel": { - "1": "Local User", - "2": "Plex User", - "3": "Emby User", - "4": "Emby Connect User", - "5": "Jellyfin User" + "1": "Lokal Bruger", + "2": "Plex Bruger", + "3": "Emby Bruger", + "4": "Forbind Emby Bruger", + "5": "Jellyfin Bruger" }, "Paginator": { - "itemsPerPageLabel": "Items per page:", - "nextPageLabel": "Next page", - "previousPageLabel": "Previous page", - "firstPageLabel": "First page", - "lastPageLabel": "Last page", - "rangePageLabel1": "0 of {{length}}", - "rangePageLabel2": "{{startIndex}} – {{endIndex}} of {{length}}" + "itemsPerPageLabel": "Elementer per side:", + "nextPageLabel": "Næste side", + "previousPageLabel": "Forrige side", + "firstPageLabel": "Første side", + "lastPageLabel": "Sidste side", + "rangePageLabel1": "0 af {{length}}", + "rangePageLabel2": "{{startIndex}} – {{endIndex}} af {{length}}" } } diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index 9ed748ac5..d397f0c55 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -4,8 +4,8 @@ "UsernamePlaceholder": "Benutzername", "PasswordPlaceholder": "Passwort", "RememberMe": "Eingeloggt bleiben", - "SignInWith": "Sign in with {{appName}}", - "SignInWithPlex": "Sign in with Plex", + "SignInWith": "Mit {{appName}} anmelden", + "SignInWithPlex": "Mit Plex anmelden", "ForgottenPassword": "Passwort vergessen?", "Errors": { "IncorrectCredentials": "Falscher Benutzername oder falsches Passwort" @@ -14,8 +14,10 @@ "Common": { "ContinueButton": "Weiter", "Available": "Verfügbar", - "Approved": "Approved", - "Pending": "Pending", + "Available4K": "In 4K verfügbar", + "Approved": "Genehmigt", + "Approve4K": "4K genehmigen", + "Pending": "steht aus", "PartiallyAvailable": "Teilweise verfügbar", "Monitored": "Überwacht", "NotAvailable": "Nicht verfügbar", @@ -24,8 +26,10 @@ "RequestDenied": "Anfrage abgelehnt", "NotRequested": "Nicht angefordert", "Requested": "Angefordert", - "Search": "Search", + "Requested4K": "In 4K angefragt", + "Search": "Suche", "Request": "Anfrage", + "Request4K": "In 4K anfragen", "Denied": "Abgelehnt", "Approve": "Genehmigen", "PartlyAvailable": "Teilweise verfügbar", @@ -33,11 +37,11 @@ "Errors": { "Validation": "Bitte überprüfen Sie die eingegebenen Werte" }, - "Cancel": "Cancel", - "Submit": "Submit", - "Update": "Update", - "tvShow": "TV Show", - "movie": "Movie", + "Cancel": "Abbrechen", + "Submit": "Senden", + "Update": "Aktualisierung", + "tvShow": "TV-Serie", + "movie": "Filme", "album": "Album" }, "PasswordReset": { @@ -56,7 +60,7 @@ "CheckPageForUpdates": "Überprüfe diese Seite für kontinuierliche Website-Updates." }, "ErrorPages": { - "NotFound": "Page not found" + "NotFound": "Seite nicht gefunden" }, "NavigationBar": { "Discover": "Entdecken", @@ -66,7 +70,7 @@ "Issues": "Probleme", "Vote": "Bewerten", "Donate": "Spenden!", - "DonateLibraryMaintainer": "Spende sie an den Bibliotheks Betreuer", + "DonateLibraryMaintainer": "Spende Sie an den Bibliotheks Betreuer", "DonateTooltip": "So überzeuge ich meine Frau, meine Freizeit mit der Entwicklung von Ombi zu verbringen ;)", "UpdateAvailableTooltip": "Update verfügbar!", "Settings": "Einstellungen", @@ -79,32 +83,32 @@ "Calendar": "Kalneder", "UserPreferences": "Einstellungen", "FeatureSuggestion": "Feature Suggestion", - "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", + "FeatureSuggestionTooltip": "Sie haben eine tolle neue Idee? Schlagen Sie sie hier vor!", "Filter": { "Movies": "Filme", "TvShows": "Serien", "Music": "Musik", - "People": "People" + "People": "Personen" }, - "MorningWelcome": "Good morning!", - "AfternoonWelcome": "Good afternoon!", - "EveningWelcome": "Good evening!" + "MorningWelcome": "Guten Morgen!", + "AfternoonWelcome": "Guten Tag!", + "EveningWelcome": "Guten Abend!" }, "Search": { "Title": "Suche", - "Paragraph": "Möchtest du etwas sehen, das nicht verfügbar ist? Kein Problem, benutze einfach die Suchbox und fordere es an!", + "Paragraph": "Sie möchten etwas sehen, das nicht verfügbar ist? Kein Problem, benutzen Sie einfach das Suchfeld und fordern Sie es an!", "MoviesTab": "Filme", "TvTab": "Serien", "MusicTab": "Musik", - "AdvancedSearch": "You can fill in any of the below to discover new media. All of the results are sorted by popularity", - "AdvancedSearchHeader": "Advanced Search", + "AdvancedSearch": "Sie können die unten stehenden Felder ausfüllen, um neue Medien zu entdecken. Alle Ergebnisse sind nach Beliebtheit sortiert", + "AdvancedSearchHeader": "Erweiterte Suche", "Suggestions": "Vorschläge", "NoResults": "Es tut uns leid, wir haben keine Ergebnisse gefunden!", "DigitalDate": "Veröffentlichung der digitalen Version: {{date}}", "TheatricalRelease": "Kinostart: {{date}}", "ViewOnPlex": "In Plex anschauen", "ViewOnEmby": "In Emby anschauen", - "ViewOnJellyfin": "Play On Jellyfin", + "ViewOnJellyfin": "Auf Jellyfin ansehen", "RequestAdded": "Anfrage für {{title}} wurde erfolgreich hinzugefügt", "Similar": "Ähnliche", "Refine": "Auswahl verfeinern", @@ -119,32 +123,32 @@ }, "TvShows": { "Popular": "Beliebt", - "Trending": "im Trend", + "Trending": "Im Trend", "MostWatched": "Meist gesehen", "MostAnticipated": "Meist erwartet", "Results": "Ergebnisse", "AirDate": "Veröffentlicht am:", "AllSeasons": "Alle Staffeln", - "FirstSeason": "erste Staffel", - "LatestSeason": "aktuellste Staffel", + "FirstSeason": "Erste Staffel", + "LatestSeason": "Aktuellste Staffel", "Select": "Wähle...", "SubmitRequest": "Anfrage einreichen", "Season": "Staffel {{seasonNumber}}", "SelectAllInSeason": "Markiere alles in Staffel {{seasonNumber}}" }, - "AdvancedSearchInstructions": "Please choose what type of media you are searching for:", - "YearOfRelease": "Year of Release", - "SearchGenre": "Search Genre", - "SearchKeyword": "Search Keyword", - "SearchProvider": "Search Provider", - "KeywordSearchingDisclaimer": "Please note that Keyword Searching is very hit and miss due to the inconsistent data in TheMovieDb" + "AdvancedSearchInstructions": "Bitte wählen Sie aus, welche Art von Medien Sie suchen:", + "YearOfRelease": "Erscheinungsjahr", + "SearchGenre": "Genre suchen", + "SearchKeyword": "Schlagwort suchen", + "SearchProvider": "Anbieter suchen", + "KeywordSearchingDisclaimer": "Bitte beachten Sie, dass die Schlagwortsuche aufgrund der inkonsistenten Daten in TheMovieDb sehr unpräzise ist" }, "Requests": { "Title": "Anfragen", "Paragraph": "Unten sehen Sie Ihre und alle anderen Anfragen, sowie deren Download und Genehmigungsstatus.", "MoviesTab": "Filme", - "ArtistName": "Artist", - "AlbumName": "Album Name", + "ArtistName": "Künstler", + "AlbumName": "Albumname", "TvTab": "Serien", "MusicTab": "Musik", "RequestedBy": "Angefordert von", @@ -161,11 +165,15 @@ "ChangeRootFolder": "Stammordner ändern", "ChangeQualityProfile": "Qualitätsprofil ändern", "MarkUnavailable": "Als Nicht verfügbar markieren", + "MarkUnavailable4K": "4K als nicht verfügbar markieren", "MarkAvailable": "Als verfügbar markieren", + "MarkAvailable4K": "4K als verfügbar markieren", "Remove": "Entfernen", "Deny": "Ablehnen", + "Deny4K": "4K ablehnen", + "Has4KRequest": "Hat eine 4K Anfrage", "DenyReason": "Ablehnungsgrund", - "DeniedReason": "Denied Reason", + "DeniedReason": "Ablehnungsgrund", "Season": "Staffel", "GridTitle": "Titel", "AirDate": "Erstausstrahlung", @@ -187,60 +195,64 @@ "NextMinutes": "Eine weitere Anfrage wird in {{time}} Minuten hinzugefügt", "NextMinute": "Eine weitere Anfrage wird in {{time}} Minute hinzugefügt" }, - "AllRequests": "All Requests", - "PendingRequests": "Pending Requests", - "ProcessingRequests": "Processing Requests", - "AvailableRequests": "Available Requests", - "DeniedRequests": "Denied Requests", - "RequestsToDisplay": "Requests to display", + "AllRequests": "Alle Anfragen", + "PendingRequests": "Ausstehende Anfragen", + "ProcessingRequests": "Anfrage wird bearbeitet", + "AvailableRequests": "Verfügbare Anfragen", + "DeniedRequests": "Abgelehnte Anfragen", + "RequestsToDisplay": "Anzuzeigende Anfragen", "RequestsTitle": "Titel", "Details": "Details", - "Options": "Options", + "Options": "Optionen", "RequestPanel": { - "Delete": "Delete Request", - "Approve": "Approve Request", - "ChangeAvailability": "Mark Available", - "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Delete": "Anfrage löschen", + "Approve": "Anfrage genehmigen", + "Deny": "Deny Request", + "Approve4K": "4K Anfrage genehmigen", + "Deny4K": "Deny 4K Request", + "ChangeAvailability": "Als verfügbar markieren", + "Deleted": "Ausgewählte Elemente erfolgreich gelöscht", + "Approved": "Ausgewählte Elemente erfolgreich freigegeben", + "Denied": "Successfully denied selected items" }, - "SuccessfullyApproved": "Successfully Approved", - "SuccessfullyDeleted": "Request successfully deleted", - "NowAvailable": "Request is now available", - "NowUnavailable": "Request is now unavailable", - "SuccessfullyReprocessed": "Successfully Re-processed the request", - "DeniedRequest": "Denied Request", - "RequestCollection": "Request Collection", - "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", - "NeedToSelectEpisodes": "You need to select some episodes!", - "RequestAddedSuccessfully": "Request for {{title}} has been added successfully", + "SuccessfullyApproved": "Erfolgreich genehmigt", + "SuccessfullyDeleted": "Anfrage erfolgreich gelöscht", + "NowAvailable": "Anfrage ist jetzt verfügbar", + "NowUnavailable": "Anfrage ist jetzt verfügbar", + "SuccessfullyReprocessed": "Die Anfrage wurde erfolgreich neu verarbeitet", + "DeniedRequest": "Abgelehnte Anfrage", + "RequestCollection": "Anfrage Sammlung", + "CollectionSuccesfullyAdded": "Die Sammlung {{name}} wurde erfolgreich hinzugefügt!", + "NeedToSelectEpisodes": "Sie müssen einige Episoden auswählen!", + "RequestAddedSuccessfully": "Anfrage für {{title}} wurde erfolgreich hinzugefügt", "ErrorCodes": { - "AlreadyRequested": "This has already been requested", - "EpisodesAlreadyRequested": "We already have episodes requested from this series", - "NoPermissionsOnBehalf": "You do not have the correct permissions to request on behalf of users!", - "NoPermissions": "You do not have the correct permissions!", - "RequestDoesNotExist": "Request does not exist", - "ChildRequestDoesNotExist": "Child Request does not exist", - "NoPermissionsRequestMovie": "You do not have permissions to Request a Movie", - "NoPermissionsRequestTV": "You do not have permissions to Request a TV Show", - "NoPermissionsRequestAlbum": "You do not have permissions to Request an Album", - "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", - "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", - "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" + "AlreadyRequested": "Dies ist bereits beantragt worden", + "EpisodesAlreadyRequested": "Wir haben bereits Episoden aus dieser Serie angefordert", + "NoPermissionsOnBehalf": "Sie haben nicht die richtigen Berechtigungen, um im Namen von Benutzern anzufragen!", + "NoPermissions": "Sie haben nicht die nötigen Rechte!", + "RequestDoesNotExist": "Die Anfrage existiert nicht", + "ChildRequestDoesNotExist": "Untergeordnete Anfrage existiert nicht", + "NoPermissionsRequestMovie": "Sie haben keine Berechtigung, um einen Film anzufordern", + "NoPermissionsRequestTV": "Sie haben keine Berechtigung, um eine TV-Sendung anzufordern", + "NoPermissionsRequestAlbum": "Sie haben keine Berechtigung, um ein Album anzufordern", + "MovieRequestQuotaExceeded": "Sie haben Ihr Kontingent für Filmanfragen überschritten!", + "TvRequestQuotaExceeded": "Sie haben Ihr Kontingent für Episodenanfragen überschritten!", + "AlbumRequestQuotaExceeded": "Sie haben Ihr Kontingent für Albumanfragen überschritten!" }, - "Notify": "Notify", - "RemoveNotification": "Remove Notifications", - "SuccessfulNotify": "You will now be notified for title {{title}}", - "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", - "CouldntNotify": "Couldn't notify title {{title}}" + "Notify": "Benachrichtigen", + "RemoveNotification": "Benachrichtigungen entfernen", + "SuccessfulNotify": "Sie werden nun für den Titel {{title}} benachrichtigt", + "SuccessfulUnNotify": "Sie werden für den Titel {{title}} nicht mehr benachrichtigt", + "CouldntNotify": "Konnte für den Titel {{title}} nicht benachrichtigen" }, "Issues": { "Title": "Probleme", - "IssuesForTitle": "Issues for {{title}}", + "IssuesForTitle": "Probleme mit {{title}}", "PendingTitle": "Ausstehende Probleme", "InProgressTitle": "Probleme in bearbeitung", "ResolvedTitle": "Behobene Probleme", "ColumnTitle": "Titel", - "Count": "Count", + "Count": "Anzahl", "Category": "Kategorie", "Status": "Status", "Details": "Details", @@ -254,23 +266,23 @@ "WriteMessagePlaceholder": "Nachricht eingeben...", "ReportedBy": "Gemeldet von", "IssueDialog": { - "Title": "Report an issue", - "DescriptionPlaceholder": "Please describe the issue", - "TitlePlaceholder": "Short title of your issue", - "SelectCategory": "Select Category", - "IssueCreated": "Issue has been created" + "Title": "Ein Problem melden", + "DescriptionPlaceholder": "Bitte beschreibe dein Problem", + "TitlePlaceholder": "Kurzer Titel Ihres Tickets", + "SelectCategory": "Kategorie auswählen", + "IssueCreated": "Ticket wurde erstellt" }, - "Outstanding": "There are outstanding issues", - "ResolvedDate": "Resolved date", - "CreatedDate": "Raised on", - "MarkedAsResolved": "This issue has now been marked as resolved!", - "MarkedAsInProgress": "This issue has now been marked as in progress!", - "Delete": "Delete issue", - "DeletedIssue": "Issue has been deleted", + "Outstanding": "Es gibt ausstehende Probleme", + "ResolvedDate": "Gelöst am", + "CreatedDate": "Erstellt am", + "MarkedAsResolved": "Dieses Problem wurde jetzt als gelöst markiert!", + "MarkedAsInProgress": "Dieses Problem wurde jetzt als in Bearbeitung markiert!", + "Delete": "Problem löschen", + "DeletedIssue": "Ticket wurde gelöscht", "Chat": "Chat", - "EnterYourMessage": "Enter Your Message", - "Requested": "Requested", - "UserOnDate": "{{user}} on {{date}}" + "EnterYourMessage": "Geben Sie Ihre Nachricht ein", + "Requested": "Angefordert", + "UserOnDate": "{{user}} am {{date}}" }, "Filter": { "ClearFilter": "Filter zurücksetzen", @@ -278,8 +290,8 @@ "FilterHeaderRequestStatus": "Status", "Approved": "Bestätigt", "PendingApproval": "Genehmigung ausstehend", - "WatchProviders": "Watch Providers", - "Keywords": "Keywords" + "WatchProviders": "Anbieter", + "Keywords": "Schlagwörter" }, "UserManagment": { "TvRemaining": "TV: {{remaining}}/{{total}} verbleibend", @@ -295,54 +307,55 @@ }, "MediaDetails": { "Denied": "Abgelehnt", + "Denied4K": "4K Abgelehnt", "Trailers": "Trailers", "RecommendationsTitle": "Empfehlungen", "SimilarTitle": "Ähnliche", "VideosTitle": "Videos", - "AlbumsTitle": "Albums", - "RequestAllAlbums": "Request All Albums", - "ClearSelection": "Clear Selection", - "RequestSelectedAlbums": "Request Selected Albums", - "ViewCollection": "View Collection", - "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", - "AdvancedOptions": "Advanced Options", - "AutoApproveOptions": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! Please note, this is optional, just press Request to skip!", - "AutoApproveOptionsTv": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", - "AutoApproveOptionsTvShort": "You can configure the request here, once requested it will be sent to your DVR application! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", - "QualityProfilesSelect": "Select A Quality Profile", - "RootFolderSelect": "Select A Root Folder", - "LanguageProfileSelect": "Select A Language Profile", + "AlbumsTitle": "Alben", + "RequestAllAlbums": "Alle Alben anfragen", + "ClearSelection": "Auswahl leeren", + "RequestSelectedAlbums": "Ausgewählte Alben anfordern", + "ViewCollection": "Sammlung ansehen", + "NotEnoughInfo": "Leider gibt es noch nicht genügend Informationen über diese Serie!", + "AdvancedOptions": "Erweiterte Optionen", + "AutoApproveOptions": "Sie können die Anfrage hier konfigurieren. Sobald die Anfrage gestellt ist, wird sie an Ihre DVR-Anwendung gesendet und automatisch genehmigt! Bitte beachten Sie, dass dies optional ist, drücken Sie einfach auf Anfrage zum Überspringen!", + "AutoApproveOptionsTv": "Sie können die Anfrage hier konfigurieren. Sobald die Anfrage gestellt ist, wird sie an Ihre DVR-Anwendung gesendet und automatisch genehmigt! Wenn die Anfrage bereits in Sonarr ist, werden wir den Stammordner oder das Qualitätsprofil nicht ändern, wenn Sie es einstellen! Bitte beachten Sie, dass dies optional ist, drücken Sie einfach auf Anfrage zum Überspringen!", + "AutoApproveOptionsTvShort": "Sie können die Anfrage hier konfigurieren. Sobald die Anfrage gestellt ist, wird sie an Ihre DVR-Anwendung gesendet! Wenn die Anfrage bereits in Sonarr ist, werden wir den Stammordner oder das Qualitätsprofil nicht ändern, wenn Sie es einstellen! Bitte beachten Sie, dass dies optional ist, drücken Sie einfach auf Anfrage zum Überspringen!", + "QualityProfilesSelect": "Wähle ein Qualitätsprofil", + "RootFolderSelect": "Hauptverzeichnis auswählen", + "LanguageProfileSelect": "Wählen Sie ein Sprachprofil", "Status": "Status:", "StatusValues": { "Rumored": "Rumored", - "Planned": "Planned", - "In Production": "In Production", - "Post Production": "Post Production", - "Released": "Released", + "Planned": "Geplant", + "In Production": "In Produktion", + "Post Production": "Postproduktion", + "Released": "Veröffentlicht", "Running": "Running", - "Returning Series": "Returning Series", - "Ended": "Ended", - "Canceled": "Canceled" + "Returning Series": "Wiederkehrende Serie", + "Ended": "Beendet", + "Canceled": "Abgesagt" }, - "Seasons": "Seasons:", - "Episodes": "Episodes:", - "Availability": "Availability:", + "Seasons": "Staffeln:", + "Episodes": "Episoden:", + "Availability": "Verfügbarkeit:", "RequestStatus": "Anfrage Status", - "Quality": "Quality:", - "RootFolderOverride": "Root Folder Override:", - "QualityOverride": "Quality Override:", - "Network": "Network:", + "Quality": "Qualität:", + "RootFolderOverride": "Stammverzeichnis Überschreiben:", + "QualityOverride": "Qualitäts Überschreiben:", + "Network": "Netzwerk:", "GenresLabel": "Genres:", "Genres": "Genres", - "FirstAired": "First Aired:", - "TheatricalRelease": "Release:", - "DigitalRelease": "Digital Release:", - "Votes": "Votes:", - "Runtime": "Runtime:", - "Minutes": "{{runtime}} Minutes", - "Revenue": "Revenue:", + "FirstAired": "Erstausstrahlung:", + "TheatricalRelease": "Kinostart:", + "DigitalRelease": "Digitale Veröffentlichung:", + "Votes": "Abstimmungen:", + "Runtime": "Laufzeit:", + "Minutes": "{{runtime}} Minuten", + "Revenue": "Einspielergebnis:", "Budget": "Budget:", - "Keywords": "Keywords/Tags:", + "Keywords": "Schlagwörter/Tags:", "Casts": { "CastTitle": "Besetzung" }, @@ -350,34 +363,36 @@ "AllSeasonsTooltip": "Dies wird jede Saison für diese Show anfordern", "FirstSeasonTooltip": "Dies wird nur die erste Saison für diese Show anfordern", "LatestSeasonTooltip": "Dies wird nur die letzte Saison für diese Show anfordern", - "NoEpisodes": "There unfortunately is no episode data for this show yet!", - "SeasonNumber": "Season {{number}}" + "NoEpisodes": "Es gibt leider noch keine Episodendaten für diese Sendung!", + "SeasonNumber": "Staffel {{number}}" }, - "SonarrConfiguration": "Sonarr Configuration", - "RadarrConfiguration": "Radarr Configuration", - "RequestOnBehalf": "Request on behalf of", - "PleaseSelectUser": "Please select a user", - "StreamingOn": "Streaming On:", - "RequestedBy": "Requested By:", - "RequestedByOn": "Requested By {{user}} on {{date}}", - "RequestDate": "Request Date:", - "DeniedReason": "Denied Reason:", - "ReProcessRequest": "Re-Process Request", + "SonarrConfiguration": "Sonarr Konfiguration", + "RadarrConfiguration": "Radarr Konfiguration", + "RequestOnBehalf": "Anfange im Namen von", + "PleaseSelectUser": "Bitte Benutzer auswählen", + "StreamingOn": "Wird gestreamt auf:", + "RequestedBy": "Angefordert von:", + "RequestedByOn": "Angefragt von {{user}} am {{date}}", + "RequestDate": "Datum der Anfrage:", + "DeniedReason": "Ablehnungsgrund:", + "ReProcessRequest": "Anfrage erneut bearbeiten", + "ReProcessRequest4K": "4K Anfrage erneut bearbeiten", "Music": { - "Type": "Type:", - "Country": "Country:", - "StartDate": "Start Date:", - "EndDate": "EndDate:" - } + "Type": "Typ:", + "Country": "Land:", + "StartDate": "Startdatum:", + "EndDate": "Enddatum:" + }, + "RequestSource": "Quelle:" }, "Discovery": { "PopularTab": "Beliebt", "TrendingTab": "Angesagt", "UpcomingTab": "Demnächst", - "SeasonalTab": "Seasonal", - "RecentlyRequestedTab": "Recently Requested", + "SeasonalTab": "Saisonal", + "RecentlyRequestedTab": "Kürzlich angefragt", "Movies": "Filme", - "Combined": "Combined", + "Combined": "Kombiniert", "Tv": "TV", "CardDetails": { "Availability": "Verfügbarkeit", @@ -391,45 +406,45 @@ "Writer": "AutorIn", "ExecProducer": "Ausführender Produzent" }, - "NoSearch": "Sorry, nothing matches your search!" + "NoSearch": "Entschuldigung, nichts stimmt mit deiner Suche überein!" }, "UserPreferences": { "Welcome": "Willkommen {{username}}!", - "OmbiLanguage": "Language", - "DarkMode": "Dark Mode", - "Updated": "Successfully Updated", - "StreamingCountry": "Streaming Country", - "StreamingCountryDescription": "This is the country code that we will display streaming information for. If you are in the US please select US and you will get US related streaming information.", - "LanguageDescription": "This is the language you would like the Ombi interface to be displayed in.", - "MobileQRCode": "Mobile QR Code", - "LegacyApp": "Launch Legacy App", - "NoQrCode": "Please contact your administrator to enable QR codes", - "UserType": "User Type:", - "ChangeDetails": "Change Details", - "NeedCurrentPassword": "You need your current password to make any changes here", - "CurrentPassword": "Current Password", - "EmailAddress": "Email Address", - "NewPassword": "New Password", - "NewPasswordConfirm": "New Password Confirm", - "Security": "Security", - "Profile": "Profile", - "UpdatedYourInformation": "Updated your information", - "Unsubscribed": "Unsubscribed!" + "OmbiLanguage": "Sprache", + "DarkMode": "Dunkler Modus", + "Updated": "Erfolgreich aktualisiert", + "StreamingCountry": "Streaming Land", + "StreamingCountryDescription": "Dies ist der Ländercode, für den wir Streaming-Informationen anzeigen. Wenn Sie sich in den USA befinden, wählen Sie bitte US und Sie erhalten Streaming-Informationen für die USA.", + "LanguageDescription": "Dies ist die Sprache, in der Ombi angezeigt werden soll.", + "MobileQRCode": "Mobiler QR Code", + "LegacyApp": "Legacy-App starten", + "NoQrCode": "Bitte kontaktieren Sie Ihren Administrator, um QR-Codes zu aktivieren", + "UserType": "Benutzertyp:", + "ChangeDetails": "Details ändern", + "NeedCurrentPassword": "Sie benötigen Ihr aktuelles Passwort, um hier Änderungen vorzunehmen", + "CurrentPassword": "Aktuelles Passwort", + "EmailAddress": "E-Mail-Adresse", + "NewPassword": "Neues Passwort", + "NewPasswordConfirm": "Neues Passwort bestätigen", + "Security": "Sicherheit", + "Profile": "Profil", + "UpdatedYourInformation": "Aktualisieren Sie Ihre Informationen", + "Unsubscribed": "Abbestellt!" }, "UserTypeLabel": { "1": "Local User", "2": "Plex User", "3": "Emby User", "4": "Emby Connect User", - "5": "Jellyfin User" + "5": "Jellyfin Server" }, "Paginator": { - "itemsPerPageLabel": "Items per page:", - "nextPageLabel": "Next page", - "previousPageLabel": "Previous page", - "firstPageLabel": "First page", - "lastPageLabel": "Last page", - "rangePageLabel1": "0 of {{length}}", - "rangePageLabel2": "{{startIndex}} – {{endIndex}} of {{length}}" + "itemsPerPageLabel": "Elemente pro Seite:", + "nextPageLabel": "Nächste Seite", + "previousPageLabel": "Vorherige Seite", + "firstPageLabel": "Erste Seite", + "lastPageLabel": "Letzte Seite", + "rangePageLabel1": "0 von {{length}}", + "rangePageLabel2": "{{startIndex}} – {{endIndex}} von {{length}}" } } diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index a6d9cb25a..a9c40c197 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Continue", "Available": "Available", + "Available4K": "Available 4K", "Approved": "Approved", + "Approve4K": "Approve 4K", "Pending": "Pending", "PartiallyAvailable": "Partially Available", "Monitored": "Monitored", @@ -24,8 +26,10 @@ "RequestDenied": "Request Denied", "NotRequested": "Not Requested", "Requested": "Requested", + "Requested4K": "Requested 4K", "Search":"Search", "Request": "Request", + "Request4K": "Request 4K", "Denied": "Denied", "Approve": "Approve", "PartlyAvailable": "Partly Available", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Root Folder", "ChangeQualityProfile": "Quality Profile", "MarkUnavailable": "Mark Unavailable", + "MarkUnavailable4K": "Mark Unavailable 4K", "MarkAvailable": "Mark Available", + "MarkAvailable4K": "Mark Available 4K", "Remove": "Remove", "Deny": "Deny", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", "DenyReason": "Deny Reason", "DeniedReason": "Denied Reason", "Season": "Season", @@ -199,9 +207,13 @@ "RequestPanel": { "Delete":"Delete Request", "Approve":"Approve Request", + "Deny":"Deny Request", + "Approve4K":"Approve 4K Request", + "Deny4K":"Deny 4K Request", "ChangeAvailability":"Mark Available", "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Approved": "Successfully approved selected items", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Successfully Approved", "SuccessfullyDeleted": "Request successfully deleted", @@ -295,6 +307,7 @@ }, "MediaDetails": { "Denied": "Denied", + "Denied4K": "Denied 4K", "Trailers": "Trailers", "RecommendationsTitle": "Recommendations", "SimilarTitle": "Similar", @@ -363,12 +376,14 @@ "RequestDate": "Request Date:", "DeniedReason": "Denied Reason:", "ReProcessRequest": "Re-Process Request", + "ReProcessRequest4K": "Re-Process 4K Request", "Music": { "Type": "Type:", "Country": "Country:", "StartDate": "Start Date:", "EndDate": "EndDate:" - } + }, + "RequestSource":"Source:" }, "Discovery": { "PopularTab": "Popular", diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index 8bf684664..bb8cb4a9a 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Continuar", "Available": "Disponible", + "Available4K": "Disponible 4K", "Approved": "Aprobado", + "Approve4K": "Aprobar 4K", "Pending": "Pendiente", "PartiallyAvailable": "Disponible parcialmente", "Monitored": "Monitoreado", @@ -24,8 +26,10 @@ "RequestDenied": "Solicitud denegada", "NotRequested": "No solicitado", "Requested": "Solicitado", + "Requested4K": "Solicitado 4K", "Search": "Buscar", "Request": "Solicitar", + "Request4K": "Solicitar 4K", "Denied": "Denegado", "Approve": "Aprobar", "PartlyAvailable": "Disponible parcialmente", @@ -38,7 +42,7 @@ "Update": "Actualización", "tvShow": "Programa de televisión", "movie": "Película", - "album": "Album" + "album": "Álbum" }, "PasswordReset": { "EmailAddressPlaceholder": "Correo electrónico", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Carpeta raíz", "ChangeQualityProfile": "Perfil de calidad", "MarkUnavailable": "Marcar como no disponible", + "MarkUnavailable4K": "Marcar No Disponible 4K", "MarkAvailable": "Marcar Disponible", + "MarkAvailable4K": "Marcar Disponible 4K", "Remove": "Eliminar", "Deny": "Denegar", + "Deny4K": "Rechazar 4K", + "Has4KRequest": "Tiene Solicitud 4K", "DenyReason": "Razón Denegada", "DeniedReason": "Motivo de denegación", "Season": "Temporada", @@ -199,12 +207,16 @@ "RequestPanel": { "Delete": "Eliminar solicitud", "Approve": "Aprobar Solicitud", + "Deny": "Rechazar Solicitud", + "Approve4K": "Aprobar Solicitud 4K", + "Deny4K": "Rechazar Solicitud 4K", "ChangeAvailability": "Marcar como disponible", "Deleted": "Los elementos seleccionados ha sido eliminados correctamente", - "Approved": "Los elementos seleccionados ha sido aprobados correctamente" + "Approved": "Los elementos seleccionados ha sido aprobados correctamente", + "Denied": "Elementos seleccionados rechazados con éxito" }, "SuccessfullyApproved": "Se ha aprobado con éxito", - "SuccessfullyDeleted": "Request successfully deleted", + "SuccessfullyDeleted": "Solicitud eliminada con éxito", "NowAvailable": "La solicitud está disponible", "NowUnavailable": "La solicitud no está disponible", "SuccessfullyReprocessed": "La solicitud ha sido procesada correctamente", @@ -214,24 +226,24 @@ "NeedToSelectEpisodes": "¡Necesitas seleccionar algunos episodios!", "RequestAddedSuccessfully": "La solicitud de {{title}} se ha añadido correctamente", "ErrorCodes": { - "AlreadyRequested": "This has already been requested", - "EpisodesAlreadyRequested": "We already have episodes requested from this series", - "NoPermissionsOnBehalf": "You do not have the correct permissions to request on behalf of users!", - "NoPermissions": "You do not have the correct permissions!", - "RequestDoesNotExist": "Request does not exist", - "ChildRequestDoesNotExist": "Child Request does not exist", - "NoPermissionsRequestMovie": "You do not have permissions to Request a Movie", - "NoPermissionsRequestTV": "You do not have permissions to Request a TV Show", - "NoPermissionsRequestAlbum": "You do not have permissions to Request an Album", - "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", - "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", - "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" + "AlreadyRequested": "Ya se ha solicitado", + "EpisodesAlreadyRequested": "Ya tenemos episodios solicitados de esta serie", + "NoPermissionsOnBehalf": "No tienes los permisos correctos para solicitar en nombre de los usuarios!", + "NoPermissions": "¡No tienes los permisos apropiados!", + "RequestDoesNotExist": "Esta petición no existe", + "ChildRequestDoesNotExist": "Esta petición no existe", + "NoPermissionsRequestMovie": "No tienes permiso para solicitar una película", + "NoPermissionsRequestTV": "No tienes permiso para solicitar un Programa de televisión", + "NoPermissionsRequestAlbum": "No tienes permiso para solicitar un Álbum", + "MovieRequestQuotaExceeded": "¡Has superado tu cuota de solicitudes de películas!", + "TvRequestQuotaExceeded": "¡Has superado tu cuota de solicitudes de series!", + "AlbumRequestQuotaExceeded": "¡Has superado tu cuota de solicitudes de álbumes!" }, - "Notify": "Notify", - "RemoveNotification": "Remove Notifications", - "SuccessfulNotify": "You will now be notified for title {{title}}", - "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", - "CouldntNotify": "Couldn't notify title {{title}}" + "Notify": "Notificar", + "RemoveNotification": "Eliminar notificación", + "SuccessfulNotify": "Se te notificará para el título {{title}}", + "SuccessfulUnNotify": "No se te notificará para el título {{title}}", + "CouldntNotify": "No se pudo notificar el título {{title}}" }, "Issues": { "Title": "Problemas", @@ -295,6 +307,7 @@ }, "MediaDetails": { "Denied": "Denegado", + "Denied4K": "Rechazado 4K", "Trailers": "Trailer", "RecommendationsTitle": "Recomendaciones", "SimilarTitle": "Similar", @@ -306,21 +319,21 @@ "ViewCollection": "Ver Colección", "NotEnoughInfo": "Desafortunadamente todavía no hay suficiente información sobre este programa!", "AdvancedOptions": "Opciones Avanzadas", - "AutoApproveOptions": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! Please note, this is optional, just press Request to skip!", - "AutoApproveOptionsTv": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", - "AutoApproveOptionsTvShort": "You can configure the request here, once requested it will be sent to your DVR application! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", + "AutoApproveOptions": "Puede configurar la solicitud aquí. Una vez solicitado, se te enviará a tu aplicación DVR y se aprobará automáticamente. Ten en cuenta que esto es opcional, presiona \"Solicitar\" para saltar!", + "AutoApproveOptionsTv": "Puede configurar la solicitud aquí, una vez solicitada será enviada a su aplicación DVR y será aprobada automáticamente! Si la solicitud ya está en Sonarr, no cambiaremos la carpeta raíz o el perfil de calidad! Ten en cuenta que esto es opcional, pulsa Solicitar para saltar!", + "AutoApproveOptionsTvShort": "Puede configurar la solicitud aquí. Una vez solicitado, se te enviará a tu aplicación DVR. Si la solicitud ya está en Sonarr, no cambiaremos la carpeta raíz o el perfil de calidad. Ten en cuenta que esto es opcional, presiona \"Solicitar\" para saltar!", "QualityProfilesSelect": "Seleccione un Perfil de Calidad", "RootFolderSelect": "Seleccione una Carpeta Raíz", - "LanguageProfileSelect": "Select A Language Profile", + "LanguageProfileSelect": "Seleccione un perfil de idioma", "Status": "Estado:", "StatusValues": { - "Rumored": "Rumored", + "Rumored": "Rumoreada", "Planned": "Planificado", "In Production": "En Producción", - "Post Production": "Post Production", + "Post Production": "Post-Producción", "Released": "En cines", - "Running": "Running", - "Returning Series": "Returning Series", + "Running": "En emisión", + "Returning Series": "Serie que regresa", "Ended": "Finalizada", "Canceled": "Cancelada" }, @@ -329,20 +342,20 @@ "Availability": "Disponibilidad:", "RequestStatus": "Estado de solicitud", "Quality": "Calidad:", - "RootFolderOverride": "Root Folder Override:", - "QualityOverride": "Quality Override:", - "Network": "Network:", + "RootFolderOverride": "Sobreescribir carpeta raíz:", + "QualityOverride": "Sobreescribir calidad:", + "Network": "Cadena:", "GenresLabel": "Géneros:", "Genres": "Géneros", - "FirstAired": "First Aired:", - "TheatricalRelease": "Release:", - "DigitalRelease": "Digital Release:", - "Votes": "Votes:", - "Runtime": "Runtime:", + "FirstAired": "Emitido por primera vez:", + "TheatricalRelease": "Lanzamiento:", + "DigitalRelease": "Estreno Digital:", + "Votes": "Votos:", + "Runtime": "Duración:", "Minutes": "{{runtime}} Minutos", - "Revenue": "Revenue:", - "Budget": "Budget:", - "Keywords": "Keywords/Tags:", + "Revenue": "Ingresos:", + "Budget": "Presupuesto:", + "Keywords": "Palabras clave/Etiquetas:", "Casts": { "CastTitle": "Enviar pantalla" }, @@ -350,32 +363,34 @@ "AllSeasonsTooltip": "Esto solicitará cada temporada para este programa", "FirstSeasonTooltip": "Esto solo solicitará la primera temporada para este programa", "LatestSeasonTooltip": "Esto solo solicitará la última temporada para este programa", - "NoEpisodes": "There unfortunately is no episode data for this show yet!", - "SeasonNumber": "Season {{number}}" + "NoEpisodes": "Lamentablemente, no hay datos de episodio para este programa de televisión todavía!", + "SeasonNumber": "Temporada {{number}}" }, - "SonarrConfiguration": "Sonarr Configuration", - "RadarrConfiguration": "Radarr Configuration", - "RequestOnBehalf": "Request on behalf of", - "PleaseSelectUser": "Please select a user", - "StreamingOn": "Streaming On:", - "RequestedBy": "Requested By:", + "SonarrConfiguration": "Configuración de Sonarr", + "RadarrConfiguration": "Configuración de Radarr", + "RequestOnBehalf": "Solicitar en nombre de", + "PleaseSelectUser": "Seleccione un usuario", + "StreamingOn": "Emitido en:", + "RequestedBy": "Solicitado por:", "RequestedByOn": "Solicitado por {{user}} el {{date}}", - "RequestDate": "Request Date:", - "DeniedReason": "Denied Reason:", - "ReProcessRequest": "Re-Process Request", + "RequestDate": "Fecha de solicitud:", + "DeniedReason": "Motivo de denegación:", + "ReProcessRequest": "Re-procesar solicitud", + "ReProcessRequest4K": "Reprocesar Solicitud 4K", "Music": { - "Type": "Type:", - "Country": "Country:", - "StartDate": "Start Date:", - "EndDate": "EndDate:" - } + "Type": "Tipo:", + "Country": "País:", + "StartDate": "Fecha de inicio:", + "EndDate": "Fecha de finalización:" + }, + "RequestSource": "Fuente:" }, "Discovery": { "PopularTab": "Popular", "TrendingTab": "Tendencias", "UpcomingTab": "Próximamente", - "SeasonalTab": "Seasonal", - "RecentlyRequestedTab": "Recently Requested", + "SeasonalTab": "Por Temporada", + "RecentlyRequestedTab": "Solicitudes recientes", "Movies": "Películas", "Combined": "Combinado", "Tv": "TV", @@ -391,36 +406,36 @@ "Writer": "Guionistas", "ExecProducer": "Productor ejecutivo" }, - "NoSearch": "Sorry, nothing matches your search!" + "NoSearch": "¡Lo sentimos, nada coincide con tu búsqueda!" }, "UserPreferences": { "Welcome": "Bienvenido {{username}}!", "OmbiLanguage": "Idioma", "DarkMode": "Modo Oscuro", - "Updated": "Successfully Updated", - "StreamingCountry": "Streaming Country", - "StreamingCountryDescription": "This is the country code that we will display streaming information for. If you are in the US please select US and you will get US related streaming information.", - "LanguageDescription": "This is the language you would like the Ombi interface to be displayed in.", - "MobileQRCode": "Mobile QR Code", - "LegacyApp": "Launch Legacy App", - "NoQrCode": "Please contact your administrator to enable QR codes", - "UserType": "User Type:", - "ChangeDetails": "Change Details", - "NeedCurrentPassword": "You need your current password to make any changes here", - "CurrentPassword": "Current Password", - "EmailAddress": "Email Address", - "NewPassword": "New Password", - "NewPasswordConfirm": "New Password Confirm", - "Security": "Security", - "Profile": "Profile", - "UpdatedYourInformation": "Updated your information", + "Updated": "Actualizado correctamente", + "StreamingCountry": "País de emisión", + "StreamingCountryDescription": "Este es el código de país desde el que mostraremos información de emisión. Si estás en España, por favor selecciona ES y tendrás información relacionada con la emisión en España.", + "LanguageDescription": "Este es el idioma en el que desea mostrar la interfaz de Ombi.", + "MobileQRCode": "Código QR móvil", + "LegacyApp": "Iniciar aplicación antigua", + "NoQrCode": "Ponte en contacto con tu administrador para habilitar los códigos QR", + "UserType": "Tipo de usuario:", + "ChangeDetails": "Modificar mis datos", + "NeedCurrentPassword": "Necesitamos tu contraseña actual para confirmar los cambios", + "CurrentPassword": "Contraseña actual", + "EmailAddress": "Correo electrónico", + "NewPassword": "Nueva Contraseña", + "NewPasswordConfirm": "Confirmar contraseña", + "Security": "Seguridad", + "Profile": "Perfil", + "UpdatedYourInformation": "Información actualizada", "Unsubscribed": "No suscrito!" }, "UserTypeLabel": { "1": "Usuario local", "2": "Usuario de Plex", "3": "Usuario de Emby", - "4": "Emby Connect User", + "4": "Conectar usuario de Emby", "5": "Usuario de Jellyfin" }, "Paginator": { diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index 298a87aba..ec7e1c27d 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Continuer", "Available": "Disponible", + "Available4K": "4K disponible", "Approved": "Approuvée", + "Approve4K": "Approuver 4K", "Pending": "En attente", "PartiallyAvailable": "Partiellement disponible", "Monitored": "Suivi", @@ -24,8 +26,10 @@ "RequestDenied": "Demande refusée", "NotRequested": "Non demandé", "Requested": "Demandé", + "Requested4K": "4K demandée", "Search": "Rechercher", "Request": "Demander", + "Request4K": "Demander en 4K", "Denied": "Refusé", "Approve": "Approuver", "PartlyAvailable": "Partiellement disponible", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Répertoire racine", "ChangeQualityProfile": "Profil de qualité", "MarkUnavailable": "Marquer indisponible", + "MarkUnavailable4K": "Marquer 4K indisponible", "MarkAvailable": "Marquer disponible", + "MarkAvailable4K": "Marquer 4K disponible", "Remove": "Supprimer", "Deny": "Refuser", + "Deny4K": "Refuser 4K", + "Has4KRequest": "A une demande 4K", "DenyReason": "Motif de refus", "DeniedReason": "Motif de refus", "Season": "Saison", @@ -199,9 +207,13 @@ "RequestPanel": { "Delete": "Supprimer la demande", "Approve": "Approuver la demande", + "Deny": "Refuser la demande", + "Approve4K": "Approuver la demande 4K", + "Deny4K": "Refuser la demande 4K", "ChangeAvailability": "Marquer comme Disponible", "Deleted": "Éléments sélectionnés supprimés avec succès", - "Approved": "Éléments sélectionnés approuvés avec succès" + "Approved": "Éléments sélectionnés approuvés avec succès", + "Denied": "Les éléments sélectionnés ont été refusés" }, "SuccessfullyApproved": "Approuvée avec succès", "SuccessfullyDeleted": "Demande supprimée avec succès", @@ -295,6 +307,7 @@ }, "MediaDetails": { "Denied": "Refusé", + "Denied4K": "4K refusée", "Trailers": "Bandes-annonces", "RecommendationsTitle": "Recommandations", "SimilarTitle": "Similaires", @@ -363,12 +376,14 @@ "RequestDate": "Date de la demande :", "DeniedReason": "Motif de refus :", "ReProcessRequest": "Refaire une demande", + "ReProcessRequest4K": "Retraiter la demande 4K", "Music": { "Type": "Type :", "Country": "Pays :", "StartDate": "Date de début :", "EndDate": "Date de fin :" - } + }, + "RequestSource": "Source :" }, "Discovery": { "PopularTab": "Populaire", diff --git a/src/Ombi/wwwroot/translations/hu.json b/src/Ombi/wwwroot/translations/hu.json index 7797e1318..9a9013317 100644 --- a/src/Ombi/wwwroot/translations/hu.json +++ b/src/Ombi/wwwroot/translations/hu.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Tovább", "Available": "Elérhető", + "Available4K": "Available 4K", "Approved": "Jóváhagyva", + "Approve4K": "Approve 4K", "Pending": "Függőben", "PartiallyAvailable": "Részlegesen elérhető", "Monitored": "Figyelve", @@ -24,8 +26,10 @@ "RequestDenied": "Kérés megtagadva", "NotRequested": "Nincs kérve", "Requested": "Kérve", + "Requested4K": "Requested 4K", "Search": "Keresés", "Request": "Kérés", + "Request4K": "Request 4K", "Denied": "Megtagadva", "Approve": "Jóváhagyva", "PartlyAvailable": "Részlegesen elérhető", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Gyökér mappa", "ChangeQualityProfile": "Minőség profil", "MarkUnavailable": "Megjelölés nem elérhetőnek", + "MarkUnavailable4K": "Mark Unavailable 4K", "MarkAvailable": "Megjelölés elérhetőnek", + "MarkAvailable4K": "Mark Available 4K", "Remove": "Törlés", "Deny": "Elutasítás", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", "DenyReason": "Elutasítási ok", "DeniedReason": "Elutasítás oka", "Season": "Évad", @@ -199,9 +207,13 @@ "RequestPanel": { "Delete": "Kérés törlése", "Approve": "Kérés elfogadása", + "Deny": "Deny Request", + "Approve4K": "Approve 4K Request", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Elérhetőnek jelölés", "Deleted": "A kijelölt elemek törlésre kerultek", - "Approved": "A kijelölt elemek jóváhagyásra kerultek" + "Approved": "A kijelölt elemek jóváhagyásra kerultek", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Sikeresen jóváhagyva", "SuccessfullyDeleted": "Kérés sikeresen törölve", @@ -295,6 +307,7 @@ }, "MediaDetails": { "Denied": "Megtagadva", + "Denied4K": "Denied 4K", "Trailers": "Előzetesek", "RecommendationsTitle": "Ajánlások", "SimilarTitle": "Hasonló", @@ -363,12 +376,14 @@ "RequestDate": "Kérés ideje:", "DeniedReason": "Elutasítás oka:", "ReProcessRequest": "Kérés újrafeldolgozása", + "ReProcessRequest4K": "Re-Process 4K Request", "Music": { "Type": "Típus:", "Country": "Ország:", "StartDate": "Kezdés dátuma:", "EndDate": "Befejezés dátuma:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Népszerű", diff --git a/src/Ombi/wwwroot/translations/it.json b/src/Ombi/wwwroot/translations/it.json index d1c910b66..71b7c121f 100644 --- a/src/Ombi/wwwroot/translations/it.json +++ b/src/Ombi/wwwroot/translations/it.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Continua", "Available": "Disponibile", + "Available4K": "Disponibile in 4K", "Approved": "Approvato", + "Approve4K": "Approva 4K", "Pending": "In Sospeso", "PartiallyAvailable": "Parzialmente disponibile", "Monitored": "Monitorato", @@ -24,8 +26,10 @@ "RequestDenied": "Richiesta negata", "NotRequested": "Non richiesta", "Requested": "Richiesta", + "Requested4K": "Richiesto 4K", "Search": "Cerca", "Request": "Richiesta", + "Request4K": "Richiedi 4K", "Denied": "Negata", "Approve": "Approva", "PartlyAvailable": "Parzialmente disponibile", @@ -62,7 +66,7 @@ "Discover": "Scopri", "Search": "Cerca", "Requests": "Richieste", - "UserManagement": "Gestione degli utenti", + "UserManagement": "Utenti", "Issues": "Problemi", "Vote": "Vota", "Donate": "Dona!", @@ -70,7 +74,7 @@ "DonateTooltip": "Questo è come convinco mia moglie a farmi spendere il mio tempo libero nello sviluppo di Ombi ;)", "UpdateAvailableTooltip": "Aggiornamento disponibile!", "Settings": "Impostazioni", - "Welcome": "Ti diamo il benvenuto {{username}}", + "Welcome": "Benvenuto {{username}}", "UpdateDetails": "Aggiorna dettagli", "Logout": "Esci", "OpenMobileApp": "Apri l'app Mobile", @@ -86,9 +90,9 @@ "Music": "Musica", "People": "Persone" }, - "MorningWelcome": "Buona mattina!", + "MorningWelcome": "Buongiorno!", "AfternoonWelcome": "Buon pomeriggio!", - "EveningWelcome": "Buona sera!" + "EveningWelcome": "Buonasera!" }, "Search": { "Title": "Cerca", @@ -96,10 +100,10 @@ "MoviesTab": "Film", "TvTab": "Serie TV", "MusicTab": "Musica", - "AdvancedSearch": "Puoi compilare uno dei seguenti per scoprire nuovi media. Tutti i risultati sono ordinati per popolarità", + "AdvancedSearch": "Compila uno dei seguenti campi per cercare nuovi media. I risultati sono in ordine di popolarità", "AdvancedSearchHeader": "Ricerca Avanzata", "Suggestions": "Suggerimenti", - "NoResults": "Spiacenti, non abbiamo trovato nulla!", + "NoResults": "Nessun risultato trovato!", "DigitalDate": "Uscita in digitale: {{date}}", "TheatricalRelease": "Uscita nei cinema: {{date}}", "ViewOnPlex": "Guarda su Plex", @@ -132,12 +136,12 @@ "Season": "Stagione {{seasonNumber}}", "SelectAllInSeason": "Seleziona tutto nella stagione {{seasonNumber}}" }, - "AdvancedSearchInstructions": "Sei pregato di scegliere che tipo di media stai cercando:", + "AdvancedSearchInstructions": "Scegli che tipo di media cercare:", "YearOfRelease": "Anno di Rilascio", "SearchGenre": "Cerca per genere", - "SearchKeyword": "Termini di ricerca", + "SearchKeyword": "Cerca per parola chiave", "SearchProvider": "Provider di ricerca", - "KeywordSearchingDisclaimer": "Sei pregato di notare che la Ricerca per Parola chiave è molto a fortuna a causa di dati non coerenti nel TheMovieDb" + "KeywordSearchingDisclaimer": "Attenzione: La ricerca per parola chiave è incostante a causa di dati non coerenti su TheMovieDb" }, "Requests": { "Title": "Richieste", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Cartella radice", "ChangeQualityProfile": "Profilo qualità", "MarkUnavailable": "Rendi non disponibile", + "MarkUnavailable4K": "Rendi 4K non disponibile", "MarkAvailable": "Rendi disponibile", + "MarkAvailable4K": "Rendi 4K disponibile", "Remove": "Rimuovi", "Deny": "Nega", + "Deny4K": "Nega 4K", + "Has4KRequest": "Ha una Richiesta 4K", "DenyReason": "Nega Motivo", "DeniedReason": "Motivo di Negazione", "Season": "Stagione", @@ -199,16 +207,20 @@ "RequestPanel": { "Delete": "Elimina Richiesta", "Approve": "Approva Richiesta", + "Deny": "Rifiuta Richiesta", + "Approve4K": "Approva Richiesta 4K", + "Deny4K": "Rifiuta Richiesta 4K", "ChangeAvailability": "Segna come Disponibile", "Deleted": "Elementi selezionati eliminati correttamente", - "Approved": "Elementi selezionati approvati correttamente" + "Approved": "Elementi selezionati approvati correttamente", + "Denied": "Elementi selezionati rifiutati con successo" }, - "SuccessfullyApproved": "Approvato Correttamente", + "SuccessfullyApproved": "Approvata", "SuccessfullyDeleted": "Richiesta eliminata correttamente", "NowAvailable": "Richiesta ora disponibile", "NowUnavailable": "Richiesta ora non disponibile", - "SuccessfullyReprocessed": "Richiesta ri-elaborata correttamente", - "DeniedRequest": "Richiesta Negata", + "SuccessfullyReprocessed": "Richiesta rielaborata correttamente", + "DeniedRequest": "Richiesta Rifiutata", "RequestCollection": "Richiedi Raccolta", "CollectionSuccesfullyAdded": "La raccolta {{name}} è stata aggiunta correttamente!", "NeedToSelectEpisodes": "Devi selezionare degli episodi!", @@ -234,20 +246,20 @@ "CouldntNotify": "Impossibile notificare il titolo {{title}}" }, "Issues": { - "Title": "Problemi", - "IssuesForTitle": "Problemi per {{title}}", - "PendingTitle": "Problemi In Attesa", - "InProgressTitle": "Problemi In Corso", - "ResolvedTitle": "Problemi Risolti", + "Title": "Segnalazioni", + "IssuesForTitle": "Segnalazioni per {{title}}", + "PendingTitle": "Segnalazioni In Attesa", + "InProgressTitle": "Segnalazioni In Risoluzione", + "ResolvedTitle": "Segnalazioni Risolte", "ColumnTitle": "Titolo", - "Count": "Conteggio", + "Count": "Totale", "Category": "Categoria", "Status": "Stato", "Details": "Dettagli", "Description": "Descrizione", "NoComments": "Nessun Commento!", - "MarkInProgress": "Senza In Corso", - "MarkResolved": "Segna Risolto", + "MarkInProgress": "Approva", + "MarkResolved": "Risolvi", "SendMessageButton": "Invia", "Subject": "Oggetto", "Comments": "Commenti", @@ -295,23 +307,24 @@ }, "MediaDetails": { "Denied": "Rifiutato", + "Denied4K": "4K Negato", "Trailers": "Trailer", - "RecommendationsTitle": "Raccomandazioni", + "RecommendationsTitle": "Raccomandati", "SimilarTitle": "Simili", "VideosTitle": "Video", "AlbumsTitle": "Album", - "RequestAllAlbums": "Richiedi Tutti gli Album", + "RequestAllAlbums": "Richiedi tutti gli Album", "ClearSelection": "Cancella Selezione", - "RequestSelectedAlbums": "Richiesta degli Album Selezionati", + "RequestSelectedAlbums": "Richiedi gli Album Selezionati", "ViewCollection": "Visualizza Raccolta", - "NotEnoughInfo": "Sfortunatamente ancora non ci sono abbastanza informazioni su questo show!", + "NotEnoughInfo": "Purtroppo ancora non ci sono abbastanza informazioni su questa serie!", "AdvancedOptions": "Opzioni Avanzate", "AutoApproveOptions": "Puoi configurare qui la tua richiesta, che verrà inviata alla tua applicazione DVR e automaticamente approvata! La configurazione è facoltativa, basta premere Richiedi per saltarla!", "AutoApproveOptionsTv": "Puoi configurare qui la tua richiesta, che verrà inviata alla tua applicazione DVR e automaticamente approvata! Se la richiesta è già presente in Sonarr, la cartella radice o il profilo qualità non verrà cambiato! La configurazione è facoltativa, basta premere Richiedi per saltarla!", "AutoApproveOptionsTvShort": "Puoi configurare qui la tua richiesta, che verrà inviata alla tua applicazione DVR! Se la richiesta è già presente in Sonarr, la cartella radice o il profilo qualità non verrà cambiato! La configurazione è facoltativa, basta premere Richiedi per saltarla!", - "QualityProfilesSelect": "Seleziona Un Profilo di Qualità", - "RootFolderSelect": "Seleziona Una Cartella di Root", - "LanguageProfileSelect": "Seleziona Un Profilo della Lingua", + "QualityProfilesSelect": "Seleziona un Profilo per la Qualità", + "RootFolderSelect": "Seleziona una Cartella Principale", + "LanguageProfileSelect": "Seleziona un profilo per la Lingua", "Status": "Stato:", "StatusValues": { "Rumored": "Rumor", @@ -321,16 +334,16 @@ "Released": "Rilasciato", "Running": "In Corso", "Returning Series": "Serie Rinnovate", - "Ended": "Terminata", - "Canceled": "Annullata" + "Ended": "Conclusa", + "Canceled": "Cancellata" }, "Seasons": "Stagioni:", "Episodes": "Episodi:", "Availability": "Disponibilità:", "RequestStatus": "Stato Richiesta", "Quality": "Qualità:", - "RootFolderOverride": "Sovrascrizione Cartella di Root:", - "QualityOverride": "Sovrascrizione Qualità:", + "RootFolderOverride": "Sovrascrivi Cartella Principale:", + "QualityOverride": "Sovrascrivi Qualità:", "Network": "Rete:", "GenresLabel": "Generi:", "Genres": "Generi", @@ -347,9 +360,9 @@ "CastTitle": "Trasmetti" }, "EpisodeSelector": { - "AllSeasonsTooltip": "Questo richiederà ogni stagione per questo show", - "FirstSeasonTooltip": "Questo richiederà solo la Prima Stagione per questo show", - "LatestSeasonTooltip": "Questo richiederà solo l'Ultima Stagione per questo show", + "AllSeasonsTooltip": "Richiederà tutte le stagioni per questa serie", + "FirstSeasonTooltip": "Richiederà solo la Prima Stagione per questa serie", + "LatestSeasonTooltip": "Richiederà solo l'Ultima Stagione per questa serie", "NoEpisodes": "Sfortunatamente, non c'è ancora alcun dato dell'episodio per questa serie!", "SeasonNumber": "Stagione {{number}}" }, @@ -363,12 +376,14 @@ "RequestDate": "Data di Richiesta:", "DeniedReason": "Motivo di Negazione:", "ReProcessRequest": "Ri-Elabora Richiesta", + "ReProcessRequest4K": "Ri-Elabora Richiesta 4K", "Music": { "Type": "Tipo:", "Country": "Paese:", "StartDate": "Data Iniziale:", "EndDate": "Data Finale:" - } + }, + "RequestSource": "Sorgente:" }, "Discovery": { "PopularTab": "Popolare", @@ -399,14 +414,14 @@ "DarkMode": "Modalità Scura", "Updated": "Aggiornate Correttamente", "StreamingCountry": "Paese di Streaming", - "StreamingCountryDescription": "Questo è il codice paese per cui mostreremo le informazioni di streaming. Se sei negli USA, selezionando US riceverai le informazioni di streaming correlate agli USA.", + "StreamingCountryDescription": "Questo è il codice del paese per cui mostreremo le informazioni dei media. Se sei in Italia, seleziona IT e ti mostreremo le informazioni dei media in Italiano.", "LanguageDescription": "Questa è la lingua in cui vorresti fosse visualizzata l'interfaccia di Ombi.", "MobileQRCode": "Codice QR Mobile", "LegacyApp": "Avvia l'App Legacy", - "NoQrCode": "Sei pregato di contattare il tuo amministratore per abilitare i codici QR", + "NoQrCode": "Contatta l'amministratore per abilitare i codici QR", "UserType": "Tipo di Utente:", "ChangeDetails": "Modifica i Dettagli", - "NeedCurrentPassword": "Necessiti la tua password corrente per effettuare qualsiasi modifica qui", + "NeedCurrentPassword": "Hai bisogno della tua password attuale per apportare qualsiasi modifica qui", "CurrentPassword": "Password Corrente", "EmailAddress": "Indirizzo Email", "NewPassword": "Nuova Password", @@ -418,8 +433,8 @@ }, "UserTypeLabel": { "1": "Utente Locale", - "2": "Utente di Plex", - "3": "Utente di Emby", + "2": "Utente Plex", + "3": "Utente Emby", "4": "Connetti Utente di Emby", "5": "Utente di Jellyfin" }, diff --git a/src/Ombi/wwwroot/translations/nl.json b/src/Ombi/wwwroot/translations/nl.json index 801f48479..932bbff9c 100644 --- a/src/Ombi/wwwroot/translations/nl.json +++ b/src/Ombi/wwwroot/translations/nl.json @@ -4,8 +4,8 @@ "UsernamePlaceholder": "Gebruikersnaam", "PasswordPlaceholder": "Wachtwoord", "RememberMe": "Onthoud Mij", - "SignInWith": "Sign in with {{appName}}", - "SignInWithPlex": "Sign in with Plex", + "SignInWith": "Inloggen met {{appName}}", + "SignInWithPlex": "Inloggen met Plex", "ForgottenPassword": "Wachtwoord vergeten?", "Errors": { "IncorrectCredentials": "Onjuiste gebruikersnaam of wachtwoord" @@ -14,8 +14,10 @@ "Common": { "ContinueButton": "Doorgaan", "Available": "Beschikbaar", - "Approved": "Approved", - "Pending": "Pending", + "Available4K": "Available 4K", + "Approved": "Goedgekeurd", + "Approve4K": "Approve 4K", + "Pending": "In afwachting", "PartiallyAvailable": "Deels Beschikbaar", "Monitored": "Gemonitord", "NotAvailable": "Niet Beschikbaar", @@ -24,8 +26,10 @@ "RequestDenied": "Verzoek geweigerd", "NotRequested": "Niet verzocht", "Requested": "Aangevraagd", - "Search": "Search", + "Requested4K": "Requested 4K", + "Search": "Zoeken", "Request": "Aanvragen", + "Request4K": "Request 4K", "Denied": "Afgewezen", "Approve": "Accepteer", "PartlyAvailable": "Deels Beschikbaar", @@ -33,11 +37,11 @@ "Errors": { "Validation": "Controleer de ingevulde waardes" }, - "Cancel": "Cancel", - "Submit": "Submit", + "Cancel": "Annuleren", + "Submit": "Verzenden", "Update": "Update", - "tvShow": "TV Show", - "movie": "Movie", + "tvShow": "Tv programma", + "movie": "Film", "album": "Album" }, "PasswordReset": { @@ -79,16 +83,16 @@ "Calendar": "Agenda", "UserPreferences": "Instellingen", "FeatureSuggestion": "Feature Suggestion", - "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", + "FeatureSuggestionTooltip": "Heb je een geweldig nieuw idee? Stel het hier voor!", "Filter": { "Movies": "Films", "TvShows": "TV Series", "Music": "Muziek", - "People": "People" + "People": "Personen" }, - "MorningWelcome": "Good morning!", - "AfternoonWelcome": "Good afternoon!", - "EveningWelcome": "Good evening!" + "MorningWelcome": "Goedemorgen!", + "AfternoonWelcome": "Goedemiddag!", + "EveningWelcome": "Goedenavond!" }, "Search": { "Title": "Zoeken", @@ -104,7 +108,7 @@ "TheatricalRelease": "Bioscoop Uitgave: {{date}}", "ViewOnPlex": "Bekijk op Plex", "ViewOnEmby": "Bekijk op Emby", - "ViewOnJellyfin": "Play On Jellyfin", + "ViewOnJellyfin": "Afspelen op Jellyfin", "RequestAdded": "Aanvraag voor {{title}} is succesvol toegevoegd", "Similar": "Vergelijkbaar", "Refine": "Verfijn", @@ -143,8 +147,8 @@ "Title": "Verzoeken", "Paragraph": "Hieronder zie je jouw en alle andere verzoeken, evenals hun download en goedkeuring status.", "MoviesTab": "Films", - "ArtistName": "Artist", - "AlbumName": "Album Name", + "ArtistName": "Artiest", + "AlbumName": "Albumnaam", "TvTab": "TV Series", "MusicTab": "Muziek", "RequestedBy": "Verzocht Door", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Hoofdmap wijzigen", "ChangeQualityProfile": "Kwaliteitsprofiel wijzigen", "MarkUnavailable": "Markeren als onbeschikbaar", + "MarkUnavailable4K": "Mark Unavailable 4K", "MarkAvailable": "Markeren als beschikbaar", + "MarkAvailable4K": "Mark Available 4K", "Remove": "Verwijderen", "Deny": "Weigeren", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", "DenyReason": "Reden van afwijzing", "DeniedReason": "Denied Reason", "Season": "Seizoen", @@ -187,21 +195,25 @@ "NextMinutes": "Een ander verzoek zal worden toegevoegd in {{time}} Minuten", "NextMinute": "Een ander verzoek zal worden toegevoegd in {{time}} Minuut" }, - "AllRequests": "All Requests", - "PendingRequests": "Pending Requests", - "ProcessingRequests": "Processing Requests", - "AvailableRequests": "Available Requests", - "DeniedRequests": "Denied Requests", - "RequestsToDisplay": "Requests to display", + "AllRequests": "Alle verzoeken", + "PendingRequests": "Lopende verzoeken", + "ProcessingRequests": "Verzoeken in behandeling", + "AvailableRequests": "Beschikbare verzoeken", + "DeniedRequests": "Geweigerde verzoeken", + "RequestsToDisplay": "Verzoeken om weer te geven", "RequestsTitle": "Titel", "Details": "Details", - "Options": "Options", + "Options": "Opties", "RequestPanel": { - "Delete": "Delete Request", - "Approve": "Approve Request", - "ChangeAvailability": "Mark Available", + "Delete": "Verwijder Verzoek", + "Approve": "Verzoek Goedkeuren", + "Deny": "Deny Request", + "Approve4K": "Approve 4K Request", + "Deny4K": "Deny 4K Request", + "ChangeAvailability": "Markeer beschikbaar", "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Approved": "Successfully approved selected items", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Successfully Approved", "SuccessfullyDeleted": "Request successfully deleted", @@ -212,7 +224,7 @@ "RequestCollection": "Request Collection", "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", "NeedToSelectEpisodes": "You need to select some episodes!", - "RequestAddedSuccessfully": "Request for {{title}} has been added successfully", + "RequestAddedSuccessfully": "Aanvraag voor {{title}} is succesvol toegevoegd", "ErrorCodes": { "AlreadyRequested": "This has already been requested", "EpisodesAlreadyRequested": "We already have episodes requested from this series", @@ -254,22 +266,22 @@ "WriteMessagePlaceholder": "Schrijf hier je bericht...", "ReportedBy": "Gerapporteerd door", "IssueDialog": { - "Title": "Report an issue", - "DescriptionPlaceholder": "Please describe the issue", - "TitlePlaceholder": "Short title of your issue", - "SelectCategory": "Select Category", - "IssueCreated": "Issue has been created" + "Title": "Meld een probleem", + "DescriptionPlaceholder": "Beschrijf het probleem", + "TitlePlaceholder": "Korte titel van het probleem", + "SelectCategory": "Selecteer categorie", + "IssueCreated": "Probleem is ingediend" }, - "Outstanding": "There are outstanding issues", - "ResolvedDate": "Resolved date", - "CreatedDate": "Raised on", - "MarkedAsResolved": "This issue has now been marked as resolved!", - "MarkedAsInProgress": "This issue has now been marked as in progress!", - "Delete": "Delete issue", - "DeletedIssue": "Issue has been deleted", + "Outstanding": "Er zijn nog openstaande problemen", + "ResolvedDate": "Oplosdatum", + "CreatedDate": "Ingediend op", + "MarkedAsResolved": "Dit probleem is nu gemarkeerd als opgelost!", + "MarkedAsInProgress": "Dit probleem is nu gemarkeerd als in behandeling!", + "Delete": "Verwijder probleem", + "DeletedIssue": "Probleem is verwijderd", "Chat": "Chat", "EnterYourMessage": "Enter Your Message", - "Requested": "Requested", + "Requested": "Aangevraagd", "UserOnDate": "{{user}} on {{date}}" }, "Filter": { @@ -295,22 +307,23 @@ }, "MediaDetails": { "Denied": "Afgewezen", + "Denied4K": "Denied 4K", "Trailers": "Trailers", "RecommendationsTitle": "Aanbevelingen", "SimilarTitle": "Vergelijkbaar", "VideosTitle": "Video's", "AlbumsTitle": "Albums", - "RequestAllAlbums": "Request All Albums", - "ClearSelection": "Clear Selection", - "RequestSelectedAlbums": "Request Selected Albums", - "ViewCollection": "View Collection", - "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", - "AdvancedOptions": "Advanced Options", + "RequestAllAlbums": "Verzoek alle albums", + "ClearSelection": "Wis selectie", + "RequestSelectedAlbums": "Verzoek geselecteerde albums", + "ViewCollection": "Bekijk collectie", + "NotEnoughInfo": "Helaas is er nog niet genoeg informatie over deze tv-serie!", + "AdvancedOptions": "Geavanceerde opties", "AutoApproveOptions": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! Please note, this is optional, just press Request to skip!", "AutoApproveOptionsTv": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", "AutoApproveOptionsTvShort": "You can configure the request here, once requested it will be sent to your DVR application! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", - "QualityProfilesSelect": "Select A Quality Profile", - "RootFolderSelect": "Select A Root Folder", + "QualityProfilesSelect": "Selecteer een kwaliteitsprofiel", + "RootFolderSelect": "Selecteer een hoofdmap", "LanguageProfileSelect": "Select A Language Profile", "Status": "Status:", "StatusValues": { @@ -325,24 +338,24 @@ "Canceled": "Canceled" }, "Seasons": "Seasons:", - "Episodes": "Episodes:", - "Availability": "Availability:", + "Episodes": "Afleveringen:", + "Availability": "Beschikbaarheid:", "RequestStatus": "Aanvraagstatus", - "Quality": "Quality:", - "RootFolderOverride": "Root Folder Override:", - "QualityOverride": "Quality Override:", - "Network": "Network:", + "Quality": "Kwaliteit:", + "RootFolderOverride": "Hoofdmap overschrijven:", + "QualityOverride": "Kwaliteit overschrijven:", + "Network": "Netwerk:", "GenresLabel": "Genres:", "Genres": "Genres", - "FirstAired": "First Aired:", + "FirstAired": "Eerste uitzending:", "TheatricalRelease": "Release:", - "DigitalRelease": "Digital Release:", - "Votes": "Votes:", - "Runtime": "Runtime:", - "Minutes": "{{runtime}} Minutes", - "Revenue": "Revenue:", + "DigitalRelease": "Digitale release:", + "Votes": "Stemmen:", + "Runtime": "Looptijd:", + "Minutes": "{{runtime}} minuten", + "Revenue": "Omzet:", "Budget": "Budget:", - "Keywords": "Keywords/Tags:", + "Keywords": "Trefwoorden/Labels:", "Casts": { "CastTitle": "Acteurs" }, @@ -351,24 +364,26 @@ "FirstSeasonTooltip": "Dit verzoekt alleen het eerste seizoen van deze serie", "LatestSeasonTooltip": "Dit verzoekt alleen het laatste seizoen van deze show", "NoEpisodes": "There unfortunately is no episode data for this show yet!", - "SeasonNumber": "Season {{number}}" + "SeasonNumber": "Seizoen {{number}}" }, - "SonarrConfiguration": "Sonarr Configuration", - "RadarrConfiguration": "Radarr Configuration", - "RequestOnBehalf": "Request on behalf of", - "PleaseSelectUser": "Please select a user", - "StreamingOn": "Streaming On:", - "RequestedBy": "Requested By:", + "SonarrConfiguration": "Sonarr configuratie", + "RadarrConfiguration": "Radarr configuratie", + "RequestOnBehalf": "Verzoek namens", + "PleaseSelectUser": "Selecteer een gebruiker", + "StreamingOn": "Streamt op:", + "RequestedBy": "Verzocht Door:", "RequestedByOn": "Requested By {{user}} on {{date}}", - "RequestDate": "Request Date:", + "RequestDate": "Aanvraag Datum:", "DeniedReason": "Denied Reason:", "ReProcessRequest": "Re-Process Request", + "ReProcessRequest4K": "Re-Process 4K Request", "Music": { "Type": "Type:", "Country": "Country:", "StartDate": "Start Date:", "EndDate": "EndDate:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Populair", @@ -377,7 +392,7 @@ "SeasonalTab": "Seasonal", "RecentlyRequestedTab": "Recently Requested", "Movies": "Films", - "Combined": "Combined", + "Combined": "Gecombineerd", "Tv": "TV", "CardDetails": { "Availability": "Beschikbaarheid", @@ -391,24 +406,24 @@ "Writer": "Schrijver", "ExecProducer": "Uitvoerende producent" }, - "NoSearch": "Sorry, nothing matches your search!" + "NoSearch": "Sorry, niks komt overeen met jou zoekopdracht!" }, "UserPreferences": { "Welcome": "Welkom {{username}}!", - "OmbiLanguage": "Language", - "DarkMode": "Dark Mode", - "Updated": "Successfully Updated", - "StreamingCountry": "Streaming Country", + "OmbiLanguage": "Taal", + "DarkMode": "Donkere Modus", + "Updated": "Succesvol bijgewerkt", + "StreamingCountry": "Streaming Land", "StreamingCountryDescription": "This is the country code that we will display streaming information for. If you are in the US please select US and you will get US related streaming information.", - "LanguageDescription": "This is the language you would like the Ombi interface to be displayed in.", - "MobileQRCode": "Mobile QR Code", - "LegacyApp": "Launch Legacy App", + "LanguageDescription": "Dit is de taal waarin Ombi in wordt weergegeven.", + "MobileQRCode": "QR code voor mobiel", + "LegacyApp": "Start legacy app", "NoQrCode": "Please contact your administrator to enable QR codes", "UserType": "User Type:", "ChangeDetails": "Change Details", "NeedCurrentPassword": "You need your current password to make any changes here", "CurrentPassword": "Current Password", - "EmailAddress": "Email Address", + "EmailAddress": "E-mail adres", "NewPassword": "New Password", "NewPasswordConfirm": "New Password Confirm", "Security": "Security", diff --git a/src/Ombi/wwwroot/translations/no.json b/src/Ombi/wwwroot/translations/no.json index 41e027c37..fcb16d35b 100644 --- a/src/Ombi/wwwroot/translations/no.json +++ b/src/Ombi/wwwroot/translations/no.json @@ -4,8 +4,8 @@ "UsernamePlaceholder": "Brukernavn", "PasswordPlaceholder": "Passord", "RememberMe": "Husk meg", - "SignInWith": "Sign in with {{appName}}", - "SignInWithPlex": "Sign in with Plex", + "SignInWith": "Logg inn med {{appName}}", + "SignInWithPlex": "Logg inn med Plex", "ForgottenPassword": "Glemt passord?", "Errors": { "IncorrectCredentials": "Ugyldig brukernavn eller passord" @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Gå videre", "Available": "Tilgjengelig", - "Approved": "Approved", + "Available4K": "Available 4K", + "Approved": "Godkjent", + "Approve4K": "Approve 4K", "Pending": "Pending", "PartiallyAvailable": "Delvis tilgjengelig", "Monitored": "Overvåket", @@ -24,16 +26,18 @@ "RequestDenied": "Forespørsel avslått", "NotRequested": "Ikke forespurt", "Requested": "Forespurt", - "Search": "Search", + "Requested4K": "Requested 4K", + "Search": "Søk", "Request": "Forespørsel", + "Request4K": "Request 4K", "Denied": "Avslått", "Approve": "Godkjenn", "PartlyAvailable": "Delvis tilgjengelig", - "ViewDetails": "View Details", + "ViewDetails": "Vis detaljer", "Errors": { "Validation": "Kontroller de angitte verdiene" }, - "Cancel": "Cancel", + "Cancel": "Avbryt", "Submit": "Submit", "Update": "Update", "tvShow": "TV Show", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Endre rotmappe", "ChangeQualityProfile": "Endre kvalitetsprofil", "MarkUnavailable": "Merk utilgjengelig", + "MarkUnavailable4K": "Mark Unavailable 4K", "MarkAvailable": "Merk tilgjengelig", + "MarkAvailable4K": "Mark Available 4K", "Remove": "Fjern", "Deny": "Avslå", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", "DenyReason": "Deny Reason", "DeniedReason": "Denied Reason", "Season": "Sesong", @@ -199,9 +207,13 @@ "RequestPanel": { "Delete": "Delete Request", "Approve": "Approve Request", - "ChangeAvailability": "Mark Available", + "Deny": "Deny Request", + "Approve4K": "Approve 4K Request", + "Deny4K": "Deny 4K Request", + "ChangeAvailability": "Merk tilgjengelig", "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Approved": "Successfully approved selected items", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Successfully Approved", "SuccessfullyDeleted": "Request successfully deleted", @@ -212,7 +224,7 @@ "RequestCollection": "Request Collection", "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", "NeedToSelectEpisodes": "You need to select some episodes!", - "RequestAddedSuccessfully": "Request for {{title}} has been added successfully", + "RequestAddedSuccessfully": "Forespørsel om {{title}} er lagt til", "ErrorCodes": { "AlreadyRequested": "This has already been requested", "EpisodesAlreadyRequested": "We already have episodes requested from this series", @@ -269,7 +281,7 @@ "DeletedIssue": "Issue has been deleted", "Chat": "Chat", "EnterYourMessage": "Enter Your Message", - "Requested": "Requested", + "Requested": "Forespurt", "UserOnDate": "{{user}} on {{date}}" }, "Filter": { @@ -295,6 +307,7 @@ }, "MediaDetails": { "Denied": "Avslått", + "Denied4K": "Denied 4K", "Trailers": "Trailers", "RecommendationsTitle": "Recommendations", "SimilarTitle": "Lignende", @@ -326,16 +339,16 @@ }, "Seasons": "Seasons:", "Episodes": "Episodes:", - "Availability": "Availability:", + "Availability": "Tilgjengelighet:", "RequestStatus": "Request Status", "Quality": "Quality:", - "RootFolderOverride": "Root Folder Override:", - "QualityOverride": "Quality Override:", + "RootFolderOverride": "Overstyring av rotmappe:", + "QualityOverride": "Overstyr kvalitet:", "Network": "Network:", "GenresLabel": "Genres:", "Genres": "Genres", "FirstAired": "First Aired:", - "TheatricalRelease": "Release:", + "TheatricalRelease": "Kinopremiere:", "DigitalRelease": "Digital Release:", "Votes": "Votes:", "Runtime": "Runtime:", @@ -351,24 +364,26 @@ "FirstSeasonTooltip": "This will only request the First Season for this show", "LatestSeasonTooltip": "This will only request the Latest Season for this show", "NoEpisodes": "There unfortunately is no episode data for this show yet!", - "SeasonNumber": "Season {{number}}" + "SeasonNumber": "Sesong {{number}}" }, "SonarrConfiguration": "Sonarr Configuration", "RadarrConfiguration": "Radarr Configuration", "RequestOnBehalf": "Request on behalf of", "PleaseSelectUser": "Please select a user", "StreamingOn": "Streaming On:", - "RequestedBy": "Requested By:", + "RequestedBy": "Etterspurt av:", "RequestedByOn": "Requested By {{user}} on {{date}}", - "RequestDate": "Request Date:", + "RequestDate": "Dato for forespørsel:", "DeniedReason": "Denied Reason:", "ReProcessRequest": "Re-Process Request", + "ReProcessRequest4K": "Re-Process 4K Request", "Music": { "Type": "Type:", "Country": "Country:", "StartDate": "Start Date:", "EndDate": "EndDate:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Populært", @@ -408,7 +423,7 @@ "ChangeDetails": "Change Details", "NeedCurrentPassword": "You need your current password to make any changes here", "CurrentPassword": "Current Password", - "EmailAddress": "Email Address", + "EmailAddress": "E-postadresse", "NewPassword": "New Password", "NewPasswordConfirm": "New Password Confirm", "Security": "Security", diff --git a/src/Ombi/wwwroot/translations/pl.json b/src/Ombi/wwwroot/translations/pl.json index e1a2ad62e..869feaac1 100644 --- a/src/Ombi/wwwroot/translations/pl.json +++ b/src/Ombi/wwwroot/translations/pl.json @@ -4,8 +4,8 @@ "UsernamePlaceholder": "Nazwa użytkownika", "PasswordPlaceholder": "Hasło", "RememberMe": "Zapamiętaj mnie", - "SignInWith": "Sign in with {{appName}}", - "SignInWithPlex": "Sign in with Plex", + "SignInWith": "Zaloguj się z {{appName}}", + "SignInWithPlex": "Zaloguj się z Plex", "ForgottenPassword": "Nie pamiętasz hasła?", "Errors": { "IncorrectCredentials": "Nieprawidłowa nazwa użytkownika lub hasło" @@ -14,8 +14,10 @@ "Common": { "ContinueButton": "Kontynuuj", "Available": "Dostępne", - "Approved": "Approved", - "Pending": "Pending", + "Available4K": "Dostępne 4K", + "Approved": "Zatwierdzone", + "Approve4K": "Zatwierdź 4K", + "Pending": "Oczekuje", "PartiallyAvailable": "Częściowo dostępne", "Monitored": "Monitorowane", "NotAvailable": "Niedostępne", @@ -24,8 +26,10 @@ "RequestDenied": "Zgłoszenie odrzucone", "NotRequested": "Niezgłoszone", "Requested": "Zgłoszone", - "Search": "Search", + "Requested4K": "Żądane 4K", + "Search": "Szukaj", "Request": "Zgłoszenie", + "Request4K": "Żądanie 4K", "Denied": "Odrzucone", "Approve": "Zatwierdź", "PartlyAvailable": "Częściowo dostępne", @@ -33,11 +37,11 @@ "Errors": { "Validation": "Proszę sprawdzić wprowadzone wartości" }, - "Cancel": "Cancel", - "Submit": "Submit", - "Update": "Update", - "tvShow": "TV Show", - "movie": "Movie", + "Cancel": "Anuluj", + "Submit": "Wyślij", + "Update": "Aktualizacja", + "tvShow": "Serial", + "movie": "Film", "album": "Album" }, "PasswordReset": { @@ -56,7 +60,7 @@ "CheckPageForUpdates": "Tutaj znajdziesz aktualizacje dotyczące tej strony." }, "ErrorPages": { - "NotFound": "Page not found" + "NotFound": "Nie znaleziono strony" }, "NavigationBar": { "Discover": "Odkryj", @@ -79,16 +83,16 @@ "Calendar": "Kalendarz", "UserPreferences": "Preferencje", "FeatureSuggestion": "Feature Suggestion", - "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", + "FeatureSuggestionTooltip": "Masz świetny nowy pomysł? Zaproponuj go tutaj!", "Filter": { "Movies": "Filmy", "TvShows": "Programy TV", "Music": "Muzyka", - "People": "People" + "People": "Osoby" }, - "MorningWelcome": "Good morning!", - "AfternoonWelcome": "Good afternoon!", - "EveningWelcome": "Good evening!" + "MorningWelcome": "Dzień dobry!", + "AfternoonWelcome": "Dzień dobry!", + "EveningWelcome": "Dobry wieczór!" }, "Search": { "Title": "Szukaj", @@ -96,15 +100,15 @@ "MoviesTab": "Filmy", "TvTab": "Seriale", "MusicTab": "Muzyka", - "AdvancedSearch": "You can fill in any of the below to discover new media. All of the results are sorted by popularity", - "AdvancedSearchHeader": "Advanced Search", + "AdvancedSearch": "Możesz wypełnić dowolny z poniższych wpisów, aby odkryć nowe media. Wszystkie wyniki są posortowane według popularności", + "AdvancedSearchHeader": "Zaawansowane wyszukiwanie", "Suggestions": "Sugestie", "NoResults": "Niestety nic nie znaleziono!", "DigitalDate": "Wydanie cyfrowe: {{date}}", "TheatricalRelease": "Premiera kinowa: {{date}}", "ViewOnPlex": "Obejrzyj w Plex", "ViewOnEmby": "Obejrzyj w Emby", - "ViewOnJellyfin": "Play On Jellyfin", + "ViewOnJellyfin": "Odtwórz w Jellyfin", "RequestAdded": "Zgłoszenie dla {{title}} zostało pomyślnie dodane", "Similar": "Podobne", "Refine": "Zawęź", @@ -132,19 +136,19 @@ "Season": "Sezon {{seasonNumber}}", "SelectAllInSeason": "Wybierz wszystkie w sezonie {{seasonNumber}}" }, - "AdvancedSearchInstructions": "Please choose what type of media you are searching for:", - "YearOfRelease": "Year of Release", + "AdvancedSearchInstructions": "Wybierz jakiego rodzaju mediów szukasz:", + "YearOfRelease": "Rok wydania", "SearchGenre": "Search Genre", "SearchKeyword": "Search Keyword", - "SearchProvider": "Search Provider", + "SearchProvider": "Dostawcy wyszukiwania", "KeywordSearchingDisclaimer": "Please note that Keyword Searching is very hit and miss due to the inconsistent data in TheMovieDb" }, "Requests": { "Title": "Zgłoszenia", "Paragraph": "Poniżej znajdują się Twoje i wszystkie inne zgłoszenia, a także ich status akceptacji i pobierania.", "MoviesTab": "Filmy", - "ArtistName": "Artist", - "AlbumName": "Album Name", + "ArtistName": "Wykonawca", + "AlbumName": "Nazwa albumu", "TvTab": "Seriale", "MusicTab": "Muzyka", "RequestedBy": "Zgłoszone przez", @@ -161,11 +165,15 @@ "ChangeRootFolder": "Folder główny", "ChangeQualityProfile": "Profil jakości", "MarkUnavailable": "Oznacz jako niedostępne", + "MarkUnavailable4K": "Oznacz jako niedostępne 4K", "MarkAvailable": "Oznacz jako dostępne", + "MarkAvailable4K": "Oznacz jako Dostępne 4K", "Remove": "Usuń", "Deny": "Odrzuć", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", "DenyReason": "Powód odrzucenia", - "DeniedReason": "Denied Reason", + "DeniedReason": "Powód odrzucenia", "Season": "Sezon", "GridTitle": "Tytuł", "AirDate": "Data emisji", @@ -187,55 +195,59 @@ "NextMinutes": "Kolejne zgłoszenie zostanie dodane za {{time}} minut(y)", "NextMinute": "Kolejne zgłoszenie zostanie dodane za {{time}} minut(y)" }, - "AllRequests": "All Requests", - "PendingRequests": "Pending Requests", - "ProcessingRequests": "Processing Requests", - "AvailableRequests": "Available Requests", - "DeniedRequests": "Denied Requests", - "RequestsToDisplay": "Requests to display", + "AllRequests": "Wszystkie zgłoszenia", + "PendingRequests": "Zgłoszenia oczekujące", + "ProcessingRequests": "Zgłoszenia przetwarzane", + "AvailableRequests": "Zgłoszenia dostępne", + "DeniedRequests": "Zgłoszenia odrzucone", + "RequestsToDisplay": "Zgłoszenia do wyświetlenia", "RequestsTitle": "Tytuł", "Details": "Szczegóły", - "Options": "Options", + "Options": "Opcje", "RequestPanel": { - "Delete": "Delete Request", - "Approve": "Approve Request", - "ChangeAvailability": "Mark Available", - "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Delete": "Usuń zgłoszenie", + "Approve": "Zatwierdź zgłoszenie", + "Deny": "Deny Request", + "Approve4K": "Zatwierdź prośbę o 4K", + "Deny4K": "Deny 4K Request", + "ChangeAvailability": "Ozn. jako dostępne", + "Deleted": "Pomyślnie usunięto wybrane elementy", + "Approved": "Pomyślnie zatwierdzono wybrane elementy", + "Denied": "Successfully denied selected items" }, - "SuccessfullyApproved": "Successfully Approved", - "SuccessfullyDeleted": "Request successfully deleted", + "SuccessfullyApproved": "Zatwierdzono pomyślnie", + "SuccessfullyDeleted": "Prośba pomyślnie usunięta", "NowAvailable": "Request is now available", "NowUnavailable": "Request is now unavailable", "SuccessfullyReprocessed": "Successfully Re-processed the request", "DeniedRequest": "Denied Request", - "RequestCollection": "Request Collection", + "RequestCollection": "Poproś o kolekcję", "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", - "NeedToSelectEpisodes": "You need to select some episodes!", - "RequestAddedSuccessfully": "Request for {{title}} has been added successfully", + "NeedToSelectEpisodes": "Musisz wybrać jakieś odcinki!", + "RequestAddedSuccessfully": "Zgłoszenie dla {{title}} zostało pomyślnie dodane", "ErrorCodes": { "AlreadyRequested": "This has already been requested", "EpisodesAlreadyRequested": "We already have episodes requested from this series", "NoPermissionsOnBehalf": "You do not have the correct permissions to request on behalf of users!", "NoPermissions": "You do not have the correct permissions!", - "RequestDoesNotExist": "Request does not exist", + "RequestDoesNotExist": "Żądanie nie istnieje", "ChildRequestDoesNotExist": "Child Request does not exist", "NoPermissionsRequestMovie": "You do not have permissions to Request a Movie", "NoPermissionsRequestTV": "You do not have permissions to Request a TV Show", "NoPermissionsRequestAlbum": "You do not have permissions to Request an Album", "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", - "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", - "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" + "TvRequestQuotaExceeded": "Przekroczyłeś limit próśb odcinków!", + "AlbumRequestQuotaExceeded": "Przekroczyłeś limit próśb Albumów!" }, - "Notify": "Notify", - "RemoveNotification": "Remove Notifications", - "SuccessfulNotify": "You will now be notified for title {{title}}", + "Notify": "Powiadomienie", + "RemoveNotification": "Usuń powiadomienia", + "SuccessfulNotify": "Teraz otrzymasz powiadomienie o tytule {{title}}", "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", "CouldntNotify": "Couldn't notify title {{title}}" }, "Issues": { "Title": "Problemy", - "IssuesForTitle": "Issues for {{title}}", + "IssuesForTitle": "Zgłoszenie dla {{title}}", "PendingTitle": "Oczekujące problemy", "InProgressTitle": "Problemy w trakcie", "ResolvedTitle": "Problemy rozwiązane", @@ -254,22 +266,22 @@ "WriteMessagePlaceholder": "Tutaj wpisz swoją wiadomość…", "ReportedBy": "Zgłoszone przez", "IssueDialog": { - "Title": "Report an issue", - "DescriptionPlaceholder": "Please describe the issue", - "TitlePlaceholder": "Short title of your issue", - "SelectCategory": "Select Category", - "IssueCreated": "Issue has been created" + "Title": "Zgłoś problem", + "DescriptionPlaceholder": "Proszę opisać problem", + "TitlePlaceholder": "Krótki tytuł Twojego problemu", + "SelectCategory": "Wybierz kategorię", + "IssueCreated": "Problem został zgłoszony" }, - "Outstanding": "There are outstanding issues", - "ResolvedDate": "Resolved date", - "CreatedDate": "Raised on", - "MarkedAsResolved": "This issue has now been marked as resolved!", - "MarkedAsInProgress": "This issue has now been marked as in progress!", - "Delete": "Delete issue", - "DeletedIssue": "Issue has been deleted", - "Chat": "Chat", - "EnterYourMessage": "Enter Your Message", - "Requested": "Requested", + "Outstanding": "Występują zaległe problemy", + "ResolvedDate": "Data rozwiązania", + "CreatedDate": "Zgłoszony", + "MarkedAsResolved": "Ten problem został oznaczony jako rozwiązany!", + "MarkedAsInProgress": "Ten problem został oznaczony jako rozwiązywany!", + "Delete": "Usuń zgłoszenie", + "DeletedIssue": "Problem został usunięty", + "Chat": "Czat", + "EnterYourMessage": "Wpisz swoją wiadomość", + "Requested": "Zgłoszone", "UserOnDate": "{{user}} on {{date}}" }, "Filter": { @@ -279,7 +291,7 @@ "Approved": "Zatwierdzone", "PendingApproval": "Oczekujące na zatwierdzenie", "WatchProviders": "Watch Providers", - "Keywords": "Keywords" + "Keywords": "Słowa kluczowe" }, "UserManagment": { "TvRemaining": "Seriale: pozostało {{remaining}}/{{total}}", @@ -295,54 +307,55 @@ }, "MediaDetails": { "Denied": "Odrzucone", - "Trailers": "Trailers", + "Denied4K": "Denied 4K", + "Trailers": "Zwiastuny", "RecommendationsTitle": "Rekomendacje", "SimilarTitle": "Podobne", "VideosTitle": "Wideo", - "AlbumsTitle": "Albums", - "RequestAllAlbums": "Request All Albums", - "ClearSelection": "Clear Selection", - "RequestSelectedAlbums": "Request Selected Albums", - "ViewCollection": "View Collection", - "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", - "AdvancedOptions": "Advanced Options", + "AlbumsTitle": "Albumy", + "RequestAllAlbums": "Zgłoś wszystkie albumy", + "ClearSelection": "Wyczyść zaznaczenie", + "RequestSelectedAlbums": "Zgłoś zaznaczone albumy", + "ViewCollection": "Pokaż kolekcję", + "NotEnoughInfo": "Niestety nie ma jeszcze wystarczających informacji na temat tego serialu!", + "AdvancedOptions": "Opcje zaawansowane", "AutoApproveOptions": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! Please note, this is optional, just press Request to skip!", "AutoApproveOptionsTv": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", "AutoApproveOptionsTvShort": "You can configure the request here, once requested it will be sent to your DVR application! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", - "QualityProfilesSelect": "Select A Quality Profile", - "RootFolderSelect": "Select A Root Folder", + "QualityProfilesSelect": "Wybierz profil jakości", + "RootFolderSelect": "Wybierz katalog główny", "LanguageProfileSelect": "Select A Language Profile", - "Status": "Status:", + "Status": "Stan:", "StatusValues": { "Rumored": "Rumored", - "Planned": "Planned", + "Planned": "Planowany", "In Production": "In Production", "Post Production": "Post Production", - "Released": "Released", + "Released": "Wydany", "Running": "Running", "Returning Series": "Returning Series", - "Ended": "Ended", - "Canceled": "Canceled" + "Ended": "Zakończono", + "Canceled": "Anulowano" }, - "Seasons": "Seasons:", - "Episodes": "Episodes:", - "Availability": "Availability:", + "Seasons": "Sezony:", + "Episodes": "Odcinków:", + "Availability": "Dostępność:", "RequestStatus": "Status zgłoszenia", - "Quality": "Quality:", - "RootFolderOverride": "Root Folder Override:", - "QualityOverride": "Quality Override:", - "Network": "Network:", - "GenresLabel": "Genres:", - "Genres": "Genres", - "FirstAired": "First Aired:", - "TheatricalRelease": "Release:", - "DigitalRelease": "Digital Release:", - "Votes": "Votes:", - "Runtime": "Runtime:", - "Minutes": "{{runtime}} Minutes", - "Revenue": "Revenue:", - "Budget": "Budget:", - "Keywords": "Keywords/Tags:", + "Quality": "Jakość:", + "RootFolderOverride": "Wymuszenie folderu głównego:", + "QualityOverride": "Wymuszenie jakości:", + "Network": "Stacja:", + "GenresLabel": "Gatunki:", + "Genres": "Gatunki", + "FirstAired": "Pierwsza emisja:", + "TheatricalRelease": "Premiera kinowa:", + "DigitalRelease": "Wydanie cyfrowe:", + "Votes": "Głosy:", + "Runtime": "Czas trwania:", + "Minutes": "{{runtime}} minut(y)", + "Revenue": "Przychód:", + "Budget": "Budżet:", + "Keywords": "Słowa kluczowe/tagi:", "Casts": { "CastTitle": "Obsada" }, @@ -351,34 +364,36 @@ "FirstSeasonTooltip": "Zgłoszenie obejmie pierwszy sezon tego serialu", "LatestSeasonTooltip": "Zgłoszenie obejmie najnowszy sezon tego serialu", "NoEpisodes": "There unfortunately is no episode data for this show yet!", - "SeasonNumber": "Season {{number}}" + "SeasonNumber": "Sezon {{number}}" }, - "SonarrConfiguration": "Sonarr Configuration", - "RadarrConfiguration": "Radarr Configuration", - "RequestOnBehalf": "Request on behalf of", - "PleaseSelectUser": "Please select a user", - "StreamingOn": "Streaming On:", - "RequestedBy": "Requested By:", + "SonarrConfiguration": "Konfiguracja Sonarr", + "RadarrConfiguration": "Konfiguracja Radarr", + "RequestOnBehalf": "Zgłoszenie w imieniu", + "PleaseSelectUser": "Proszę wybrać użytkownika", + "StreamingOn": "Strumieniowane w:", + "RequestedBy": "Zgłoszone przez:", "RequestedByOn": "Requested By {{user}} on {{date}}", - "RequestDate": "Request Date:", + "RequestDate": "Data zgłoszenia:", "DeniedReason": "Denied Reason:", "ReProcessRequest": "Re-Process Request", + "ReProcessRequest4K": "Re-Process 4K Request", "Music": { - "Type": "Type:", - "Country": "Country:", - "StartDate": "Start Date:", - "EndDate": "EndDate:" - } + "Type": "Typ:", + "Country": "Kraj:", + "StartDate": "Data rozpoczęcia:", + "EndDate": "Data zakończenia:" + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Popularne", "TrendingTab": "Zyskujące popularność", "UpcomingTab": "Nadchodzące", "SeasonalTab": "Seasonal", - "RecentlyRequestedTab": "Recently Requested", + "RecentlyRequestedTab": "Ostatnie prośby", "Movies": "Filmy", - "Combined": "Combined", - "Tv": "TV", + "Combined": "Połączone", + "Tv": "Seriale", "CardDetails": { "Availability": "Dostępność", "Studio": "Studio", @@ -391,45 +406,45 @@ "Writer": "Scenarzysta", "ExecProducer": "Producent wykonawczy" }, - "NoSearch": "Sorry, nothing matches your search!" + "NoSearch": "Przepraszamy, nic nie pasuje do Twojego wyszukiwania!" }, "UserPreferences": { "Welcome": "Witaj {{username}}!", - "OmbiLanguage": "Language", - "DarkMode": "Dark Mode", - "Updated": "Successfully Updated", - "StreamingCountry": "Streaming Country", + "OmbiLanguage": "Język", + "DarkMode": "Tryb ciemny", + "Updated": "Zaktualizowano pomyślnie", + "StreamingCountry": "Kraj strumieniowania", "StreamingCountryDescription": "This is the country code that we will display streaming information for. If you are in the US please select US and you will get US related streaming information.", - "LanguageDescription": "This is the language you would like the Ombi interface to be displayed in.", - "MobileQRCode": "Mobile QR Code", - "LegacyApp": "Launch Legacy App", + "LanguageDescription": "To jest język, w którym ma być wyświetlany interfejs Ombi.", + "MobileQRCode": "Kod QR z telefonu", + "LegacyApp": "Uruchom starszą aplikację", "NoQrCode": "Please contact your administrator to enable QR codes", - "UserType": "User Type:", + "UserType": "Typ Użytkownika:", "ChangeDetails": "Change Details", - "NeedCurrentPassword": "You need your current password to make any changes here", - "CurrentPassword": "Current Password", - "EmailAddress": "Email Address", - "NewPassword": "New Password", - "NewPasswordConfirm": "New Password Confirm", - "Security": "Security", - "Profile": "Profile", - "UpdatedYourInformation": "Updated your information", - "Unsubscribed": "Unsubscribed!" + "NeedCurrentPassword": "Potrzebujesz swojego aktualnego hasła, aby potwierdzić zmiany", + "CurrentPassword": "Obecne hasło", + "EmailAddress": "Adres e-mail", + "NewPassword": "Nowe Hasło", + "NewPasswordConfirm": "Potwierdź nowe hasło", + "Security": "Ochrona", + "Profile": "Profil", + "UpdatedYourInformation": "Zaktualizuj swoje informacje", + "Unsubscribed": "Subskrypcja anulowana!" }, "UserTypeLabel": { - "1": "Local User", - "2": "Plex User", - "3": "Emby User", + "1": "Użytkownik lokalny", + "2": "Użytkownik Plex", + "3": "Użytkownik Emby", "4": "Emby Connect User", - "5": "Jellyfin User" + "5": "Użytkownik Jellyfin" }, "Paginator": { - "itemsPerPageLabel": "Items per page:", - "nextPageLabel": "Next page", - "previousPageLabel": "Previous page", - "firstPageLabel": "First page", - "lastPageLabel": "Last page", - "rangePageLabel1": "0 of {{length}}", - "rangePageLabel2": "{{startIndex}} – {{endIndex}} of {{length}}" + "itemsPerPageLabel": "Wpisów na stronie:", + "nextPageLabel": "Następna strona", + "previousPageLabel": "Poprzednia strona", + "firstPageLabel": "Pierwsza strona", + "lastPageLabel": "Ostatnia Strona", + "rangePageLabel1": "0 z {{length}}", + "rangePageLabel2": "{{startIndex}} - {{endIndex}} z {{length}}" } } diff --git a/src/Ombi/wwwroot/translations/pt-BR.json b/src/Ombi/wwwroot/translations/pt-BR.json new file mode 100644 index 000000000..88623edd5 --- /dev/null +++ b/src/Ombi/wwwroot/translations/pt-BR.json @@ -0,0 +1,450 @@ +{ + "Login": { + "SignInButton": "Iniciar sessão", + "UsernamePlaceholder": "Nome de usuário", + "PasswordPlaceholder": "Senha", + "RememberMe": "Lembrar-me", + "SignInWith": "Entre com {{appName}}", + "SignInWithPlex": "Iniciar sessão com Plex", + "ForgottenPassword": "Esqueceu sua senha?", + "Errors": { + "IncorrectCredentials": "Nome de usuário ou senha incorretos" + } + }, + "Common": { + "ContinueButton": "Continuar", + "Available": "Disponível", + "Available4K": "Disponível", + "Approved": "Aprovado", + "Approve4K": "Aprovar", + "Pending": "Pendente", + "PartiallyAvailable": "Parcialmente Disponível", + "Monitored": "Monitorado", + "NotAvailable": "Não Disponível", + "ProcessingRequest": "Processando Solicitação", + "PendingApproval": "Aprovação Pendente", + "RequestDenied": "Solicitação Negada", + "NotRequested": "Não Solicitado", + "Requested": "Solicitado", + "Requested4K": "4K requisitado", + "Search": "Buscar", + "Request": "Solicitar", + "Request4K": "Requisitar 4K", + "Denied": "Negado", + "Approve": "Aprovar", + "PartlyAvailable": "Parcialmente Disponível", + "ViewDetails": "Ver detalhes", + "Errors": { + "Validation": "Por favor, verifique os dados inseridos" + }, + "Cancel": "Cancelar", + "Submit": "Submeter", + "Update": "Atualizar", + "tvShow": "Series", + "movie": "Filmes", + "album": "Álbum" + }, + "PasswordReset": { + "EmailAddressPlaceholder": "Endereço de e-mail", + "ResetPasswordButton": "Redefinir Senha" + }, + "LandingPage": { + "OnlineHeading": "Online no momento", + "OnlineParagraph": "O servidor de mídia está atualmente online", + "PartiallyOnlineHeading": "Parcialmente Online", + "PartiallyOnlineParagraph": "O servidor de mídia está parcialmente online.", + "MultipleServersUnavailable": "Existem {{serversUnavailable}} servidores offline de um total de {{totalServers}}.", + "SingleServerUnavailable": "Existe {{serversUnavailable}} servidor offline de um total de {{totalServers}}.", + "OfflineHeading": "Offline Agora", + "OfflineParagraph": "O servidor de mídia está atualmente offline.", + "CheckPageForUpdates": "Verifique esta página para acompanhar as atualizações do site." + }, + "ErrorPages": { + "NotFound": "Pagina não encontrada" + }, + "NavigationBar": { + "Discover": "Explorar", + "Search": "Pesquisar", + "Requests": "Solicitações", + "UserManagement": "User Management", + "Issues": "Problemas", + "Vote": "Votar", + "Donate": "Doações!", + "DonateLibraryMaintainer": "Doar para o Dono da Biblioteca", + "DonateTooltip": "É assim que convenço minha esposa a me deixar passar o meu tempo livre desenvolvendo o Ombi 😁", + "UpdateAvailableTooltip": "Atualização Disponível!", + "Settings": "Configurações", + "Welcome": "Bem-vindo(a), {{username}}", + "UpdateDetails": "Detalhes da Atualização", + "Logout": "Desconectar", + "OpenMobileApp": "Abrir Aplicativo do Celular", + "RecentlyAdded": "Recentemente Adicionado", + "ChangeTheme": "Trocar Tema", + "Calendar": "Calendário", + "UserPreferences": "Preferências", + "FeatureSuggestion": "Feature Suggestion", + "FeatureSuggestionTooltip": "Teve uma ótima idéia? Sugira aqui!", + "Filter": { + "Movies": "Filmes", + "TvShows": "Séries", + "Music": "Músicas", + "People": "Pessoas" + }, + "MorningWelcome": "Bom dia!", + "AfternoonWelcome": "Boa tarde!", + "EveningWelcome": "Boa noite!" + }, + "Search": { + "Title": "Pesquisar", + "Paragraph": "Quer assistir a algo que não está disponível? Sem problemas, basta pesquisar abaixo e solicitar!", + "MoviesTab": "Filmes", + "TvTab": "Séries", + "MusicTab": "Músicas", + "AdvancedSearch": "Você pode preencher qualquer um dos abaixo para descobrir novas mídias. Todos os resultados são classificados por popularidade", + "AdvancedSearchHeader": "Pesquisa avançada", + "Suggestions": "Sugestões", + "NoResults": "Desculpe, não encontramos nenhum resultado!", + "DigitalDate": "Lançamento Digital: {{date}}", + "TheatricalRelease": "Lançamento nos Cinemas: {{date}}", + "ViewOnPlex": "View On Plex", + "ViewOnEmby": "View On Emby", + "ViewOnJellyfin": "Assistir no Jellyfin", + "RequestAdded": "O pedido de {{title}} foi adicionado com sucesso", + "Similar": "Semelhantes", + "Refine": "Corrigir", + "SearchBarPlaceholder": "Digite Aqui para Pesquisar", + "Movies": { + "PopularMovies": "Filmes Populares", + "UpcomingMovies": "Filmes Em Breve", + "TopRatedMovies": "Filmes Mais Votados", + "NowPlayingMovies": "Filmes em Cartaz", + "HomePage": "Página Inicial", + "Trailer": "Trailer" + }, + "TvShows": { + "Popular": "Popular", + "Trending": "Tendências", + "MostWatched": "Mais Assistidos", + "MostAnticipated": "Mais Aguardados", + "Results": "Resultados", + "AirDate": "Data de Exibição:", + "AllSeasons": "Todas as Temporadas", + "FirstSeason": "Primeira temporada", + "LatestSeason": "Última Temporada", + "Select": "Selecionar...", + "SubmitRequest": "Enviar solicitação", + "Season": "Temporada: {{seasonNumber}}", + "SelectAllInSeason": "Selecione Tudo na Temporada {{seasonNumber}}" + }, + "AdvancedSearchInstructions": "Por favor, escolha o tipo de mídia que você está procurando:", + "YearOfRelease": "Ano de lançamento", + "SearchGenre": "Pesquisa por gênero", + "SearchKeyword": "Pesquisar palavras-chave", + "SearchProvider": "Provedores de pesquisa", + "KeywordSearchingDisclaimer": "Por favor, note que a busca por palavra-chave é muito acertada e perdida devido aos dados inconsistentes no TheMovieDb" + }, + "Requests": { + "Title": "Solicitações", + "Paragraph": "Abaixo, você pode ver o seu e todos os outros pedidos, bem como o seu download e status de aprovação.", + "MoviesTab": "Filmes", + "ArtistName": "Artistas", + "AlbumName": "Nome do álbum", + "TvTab": "Séries", + "MusicTab": "Músicas", + "RequestedBy": "Solicitado por", + "Status": "Status", + "RequestStatus": "Status da solicitação", + "Denied": " Negados:", + "TheatricalRelease": "Lançamento nos Cinemas: {{date}}", + "ReleaseDate": "Lançado: {{date}}", + "TheatricalReleaseSort": "Lançamento nos Cinemas", + "DigitalRelease": "Lançamento Digital: {{date}}", + "RequestDate": "Data da Solicitação", + "QualityOverride": "Substituição de Qualidade:", + "RootFolderOverride": "Substituição da Pasta Raiz:", + "ChangeRootFolder": "Pasta Raiz", + "ChangeQualityProfile": "Perfil de Qualidade", + "MarkUnavailable": "Marcar como Indisponível", + "MarkUnavailable4K": "Marcar indisponível 4K", + "MarkAvailable": "Marcar como Disponível", + "MarkAvailable4K": "Marcar disponível 4K", + "Remove": "Remover", + "Deny": "Negar", + "Deny4K": "Recusar 4K", + "Has4KRequest": "Pedido 4K existente", + "DenyReason": "Razão da rejeição", + "DeniedReason": "Razão da rejeição", + "Season": "Temporada", + "GridTitle": "Título", + "AirDate": "AirDate", + "GridStatus": "Status", + "ReportIssue": "Relatar Problema", + "Filter": "Filtro", + "Sort": "Ordenar por", + "SeasonNumberHeading": "Temporada: {seasonNumber}", + "SortTitleAsc": "Título ▲", + "SortTitleDesc": "Título ▼", + "SortRequestDateAsc": "Data da Solicitação ▲", + "SortRequestDateDesc": "Data da Solicitação ▼", + "SortStatusAsc": "Status ▲", + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} solicitações restantes", + "NextDays": "Outra solicitação será adicionada em {{time}} dias", + "NextHours": "Outra solicitação será adicionada em {{time}} horas", + "NextMinutes": "Outra solicitação será adicionada em {{time}} minutos", + "NextMinute": "Outra solicitação será adicionada em {{time}} minuto" + }, + "AllRequests": "Todas solicitações", + "PendingRequests": "Solicitações pendentes", + "ProcessingRequests": "Solicitações em andamento", + "AvailableRequests": "Solicitação Disponíveis", + "DeniedRequests": "Solicitações Negadas", + "RequestsToDisplay": "Itens por página", + "RequestsTitle": "Título", + "Details": "Detalhes", + "Options": "Opções", + "RequestPanel": { + "Delete": "Apagar Solicitação", + "Approve": "Aprovar Solicitação", + "Deny": "Recusar pedido", + "Approve4K": "Aprovar pedido 4K", + "Deny4K": "Recusar pedido de 4K", + "ChangeAvailability": "Marcar Como Disponível", + "Deleted": "Successfully deleted selected items", + "Approved": "Successfully approved selected items", + "Denied": "Itens selecionados negados com sucesso" + }, + "SuccessfullyApproved": "Successfully Approved", + "SuccessfullyDeleted": "Request successfully deleted", + "NowAvailable": "Request is now available", + "NowUnavailable": "Request is now unavailable", + "SuccessfullyReprocessed": "Successfully Re-processed the request", + "DeniedRequest": "Denied Request", + "RequestCollection": "Request Collection", + "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", + "NeedToSelectEpisodes": "You need to select some episodes!", + "RequestAddedSuccessfully": "Solicitação de {{title}} foi adicionada com sucesso", + "ErrorCodes": { + "AlreadyRequested": "This has already been requested", + "EpisodesAlreadyRequested": "We already have episodes requested from this series", + "NoPermissionsOnBehalf": "You do not have the correct permissions to request on behalf of users!", + "NoPermissions": "You do not have the correct permissions!", + "RequestDoesNotExist": "Request does not exist", + "ChildRequestDoesNotExist": "Child Request does not exist", + "NoPermissionsRequestMovie": "You do not have permissions to Request a Movie", + "NoPermissionsRequestTV": "You do not have permissions to Request a TV Show", + "NoPermissionsRequestAlbum": "You do not have permissions to Request an Album", + "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", + "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", + "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" + }, + "Notify": "Notify", + "RemoveNotification": "Remove Notifications", + "SuccessfulNotify": "You will now be notified for title {{title}}", + "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", + "CouldntNotify": "Couldn't notify title {{title}}" + }, + "Issues": { + "Title": "Problemas", + "IssuesForTitle": "Issues for {{title}}", + "PendingTitle": "Problemas pendentes", + "InProgressTitle": "Problemas em resolução", + "ResolvedTitle": "Problemas Resolvidos", + "ColumnTitle": "Título", + "Count": "Count", + "Category": "Categoria", + "Status": "Status", + "Details": "Detalhes", + "Description": "Descrição", + "NoComments": "Sem Comentários!", + "MarkInProgress": "Marcar como em andamento", + "MarkResolved": "Marcar como resolvido", + "SendMessageButton": "Enviar", + "Subject": "Assunto", + "Comments": "Comentários", + "WriteMessagePlaceholder": "Escreva sua mensagem aqui...", + "ReportedBy": "Reportado por", + "IssueDialog": { + "Title": "Reportar um problema", + "DescriptionPlaceholder": "Por favor, descreva o problema", + "TitlePlaceholder": "Título curto para o problema", + "SelectCategory": "Selecione Uma Categoria", + "IssueCreated": "Um registro de problema foi criado" + }, + "Outstanding": "Existem problemas pendentes", + "ResolvedDate": "Data da resolução", + "CreatedDate": "Notificado em", + "MarkedAsResolved": "Esse problema foi marcado como resolvido!", + "MarkedAsInProgress": "Esse problema foi marcado como resolvendo!", + "Delete": "Deletar problema", + "DeletedIssue": "O problema foi excluído", + "Chat": "Chat", + "EnterYourMessage": "Enter Your Message", + "Requested": "Solicitado", + "UserOnDate": "{{user}} on {{date}}" + }, + "Filter": { + "ClearFilter": "Limpar Filtro", + "FilterHeaderAvailability": "Disponibilidade", + "FilterHeaderRequestStatus": "Status", + "Approved": "Aprovado", + "PendingApproval": "Aprovação Pendente", + "WatchProviders": "Watch Providers", + "Keywords": "Keywords" + }, + "UserManagment": { + "TvRemaining": "Séries: {{remaining}}/{{total}} restantes", + "MovieRemaining": "Filmes: {{remaining}}/{{total}} restantes", + "MusicRemaining": "Músicas: {{remaining}}/{{total}} restantes", + "TvDue": "Série: {{date}}", + "MovieDue": "Filme: {{date}}", + "MusicDue": "Música: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Votado", + "VotesTab": "Votos necessários" + }, + "MediaDetails": { + "Denied": "Rejeitado", + "Denied4K": "4K recusado", + "Trailers": "Trailers", + "RecommendationsTitle": "Recomendações", + "SimilarTitle": "Semelhante", + "VideosTitle": "Vídeos", + "AlbumsTitle": "Álbuns", + "RequestAllAlbums": "Solicitar Todos Álbuns", + "ClearSelection": "Limpar Seleção", + "RequestSelectedAlbums": "Solicitar Álbuns Selecionados", + "ViewCollection": "Ver Coleção", + "NotEnoughInfo": "Infelizmente ainda não há informação sobre essa série!", + "AdvancedOptions": "Opções Avançadas", + "AutoApproveOptions": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! Please note, this is optional, just press Request to skip!", + "AutoApproveOptionsTv": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", + "AutoApproveOptionsTvShort": "You can configure the request here, once requested it will be sent to your DVR application! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", + "QualityProfilesSelect": "Selecione um perfil de qualidade", + "RootFolderSelect": "Selecione o diretório raiz", + "LanguageProfileSelect": "Select A Language Profile", + "Status": "Status:", + "StatusValues": { + "Rumored": "Rumored", + "Planned": "Planned", + "In Production": "In Production", + "Post Production": "Post Production", + "Released": "Released", + "Running": "Running", + "Returning Series": "Returning Series", + "Ended": "Ended", + "Canceled": "Canceled" + }, + "Seasons": "Seasons:", + "Episodes": "Episodes:", + "Availability": "Disponibilidade:", + "RequestStatus": "Estado da solicitação", + "Quality": "Qualidade:", + "RootFolderOverride": "Substituição da Pasta Raiz:", + "QualityOverride": "Substituição de Qualidade:", + "Network": "Rede:", + "GenresLabel": "Gêneros:", + "Genres": "Gêneros", + "FirstAired": "Primeira Exibição:", + "TheatricalRelease": "Theatrical Release:", + "DigitalRelease": "Lançamento Digital:", + "Votes": "Votos:", + "Runtime": "Tempo de execução:", + "Minutes": "{{runtime}} Minutos", + "Revenue": "Receita:", + "Budget": "Orçamento:", + "Keywords": "Palavras-Chave/Tags:", + "Casts": { + "CastTitle": "Elenco" + }, + "EpisodeSelector": { + "AllSeasonsTooltip": "Isto irá pedir todas as temporadas da série", + "FirstSeasonTooltip": "Isto somente irá pedir a 1ª temporada da série", + "LatestSeasonTooltip": "Isto somente irá pedir a última temporada da série", + "NoEpisodes": "There unfortunately is no episode data for this show yet!", + "SeasonNumber": "Temporada: {{number}}" + }, + "SonarrConfiguration": "Configuração do Sonarr", + "RadarrConfiguration": "Configuração do Radarr", + "RequestOnBehalf": "Pedido em nome de", + "PleaseSelectUser": "Por favor, selecione um usuário", + "StreamingOn": "Streaming On:", + "RequestedBy": "Solicitado por:", + "RequestedByOn": "Requested By {{user}} on {{date}}", + "RequestDate": "Data da Solicitação:", + "DeniedReason": "Razão da rejeição:", + "ReProcessRequest": "Re-Process Request", + "ReProcessRequest4K": "Reprocessar pedido 4K", + "Music": { + "Type": "Type:", + "Country": "Country:", + "StartDate": "Start Date:", + "EndDate": "EndDate:" + }, + "RequestSource": "Source:" + }, + "Discovery": { + "PopularTab": "Popular", + "TrendingTab": "Tendências", + "UpcomingTab": "Próximo", + "SeasonalTab": "Seasonal", + "RecentlyRequestedTab": "Recently Requested", + "Movies": "Filmes", + "Combined": "Combinados", + "Tv": "Serie", + "CardDetails": { + "Availability": "Disponibilidade", + "Studio": "Estúdio", + "Network": "Rede", + "UnknownNetwork": "Desconhecido", + "RequestStatus": "Estado da solicitação", + "Director": "Diretor", + "InCinemas": "Nos Cinemas", + "FirstAired": "Primeira Exibição", + "Writer": "Escritor", + "ExecProducer": "Produtor Executivo" + }, + "NoSearch": "Desculpe, nada corresponde à sua pesquisa!" + }, + "UserPreferences": { + "Welcome": "Bem-vindo, {{username}}!", + "OmbiLanguage": "Idioma", + "DarkMode": "Modo Escuro", + "Updated": "Atualizado com Sucesso", + "StreamingCountry": "País de Streaming", + "StreamingCountryDescription": "This is the country code that we will display streaming information for. If you are in the US please select US and you will get US related streaming information.", + "LanguageDescription": "Este é o idioma que você gostaria de exibir na interface do Ombi.", + "MobileQRCode": "QR Code para Celular", + "LegacyApp": "Iniciar Legacy App", + "NoQrCode": "Please contact your administrator to enable QR codes", + "UserType": "User Type:", + "ChangeDetails": "Change Details", + "NeedCurrentPassword": "You need your current password to make any changes here", + "CurrentPassword": "Current Password", + "EmailAddress": "Endereço de e-mail", + "NewPassword": "New Password", + "NewPasswordConfirm": "New Password Confirm", + "Security": "Security", + "Profile": "Profile", + "UpdatedYourInformation": "Updated your information", + "Unsubscribed": "Unsubscribed!" + }, + "UserTypeLabel": { + "1": "Local User", + "2": "Plex User", + "3": "Emby User", + "4": "Emby Connect User", + "5": "Jellyfin User" + }, + "Paginator": { + "itemsPerPageLabel": "Items per page:", + "nextPageLabel": "Next page", + "previousPageLabel": "Previous page", + "firstPageLabel": "First page", + "lastPageLabel": "Last page", + "rangePageLabel1": "0 of {{length}}", + "rangePageLabel2": "{{startIndex}} – {{endIndex}} of {{length}}" + } +} diff --git a/src/Ombi/wwwroot/translations/pt.json b/src/Ombi/wwwroot/translations/pt.json index ea1967e78..ed1aa5434 100644 --- a/src/Ombi/wwwroot/translations/pt.json +++ b/src/Ombi/wwwroot/translations/pt.json @@ -1,207 +1,219 @@ { "Login": { "SignInButton": "Iniciar sessão", - "UsernamePlaceholder": "Nome de usuário", - "PasswordPlaceholder": "Senha", - "RememberMe": "Lembrar-me", + "UsernamePlaceholder": "Nome de Usuário", + "PasswordPlaceholder": "Palavra-passe", + "RememberMe": "Recorde-me", "SignInWith": "Entre com {{appName}}", "SignInWithPlex": "Iniciar sessão com Plex", "ForgottenPassword": "Esqueceu sua senha?", "Errors": { - "IncorrectCredentials": "Nome de usuário ou senha incorretos" + "IncorrectCredentials": "Usuário ou senha incorretos" } }, "Common": { "ContinueButton": "Continuar", "Available": "Disponível", + "Available4K": "Disponível 4K", "Approved": "Aprovado", - "Pending": "Pendente", + "Approve4K": "Approve 4K", + "Pending": "Pending", "PartiallyAvailable": "Parcialmente Disponível", - "Monitored": "Monitorado", - "NotAvailable": "Não Disponível", - "ProcessingRequest": "Processando Solicitação", + "Monitored": "Monitored", + "NotAvailable": "Não disponível", + "ProcessingRequest": "Processando o pedido", "PendingApproval": "Aprovação Pendente", - "RequestDenied": "Solicitação Negada", + "RequestDenied": "Pedido Negado", "NotRequested": "Não Solicitado", - "Requested": "Solicitado", - "Search": "Buscar", + "Requested": "Pedido", + "Requested4K": "Requested 4K", + "Search": "Search", "Request": "Solicitar", - "Denied": "Negado", + "Request4K": "Request 4K", + "Denied": "Recusado", "Approve": "Aprovar", "PartlyAvailable": "Parcialmente Disponível", "ViewDetails": "Ver detalhes", "Errors": { - "Validation": "Por favor, verifique os dados inseridos" + "Validation": "Por favor, verifique os valores inseridos" }, "Cancel": "Cancelar", "Submit": "Submeter", - "Update": "Atualizar", - "tvShow": "Series", - "movie": "Filmes", - "album": "Álbum" + "Update": "Update", + "tvShow": "TV Show", + "movie": "Movie", + "album": "Album" }, "PasswordReset": { - "EmailAddressPlaceholder": "Endereço de e-mail", - "ResetPasswordButton": "Redefinir Senha" + "EmailAddressPlaceholder": "Email Address", + "ResetPasswordButton": "Nova senha" }, "LandingPage": { "OnlineHeading": "Online no momento", - "OnlineParagraph": "O servidor de mídia está atualmente online", - "PartiallyOnlineHeading": "Parcialmente Online", - "PartiallyOnlineParagraph": "O servidor de mídia está parcialmente online.", - "MultipleServersUnavailable": "Existem {{serversUnavailable}} servidores offline de um total de {{totalServers}}.", - "SingleServerUnavailable": "Existe {{serversUnavailable}} servidor offline de um total de {{totalServers}}.", - "OfflineHeading": "Offline Agora", - "OfflineParagraph": "O servidor de mídia está atualmente offline.", - "CheckPageForUpdates": "Verifique esta página para acompanhar as atualizações do site." + "OnlineParagraph": "The media server is currently online", + "PartiallyOnlineHeading": "Partially Online", + "PartiallyOnlineParagraph": "The media server is partially online.", + "MultipleServersUnavailable": "There are {{serversUnavailable}} servers offline out of {{totalServers}}.", + "SingleServerUnavailable": "There is {{serversUnavailable}} server offline out of {{totalServers}}.", + "OfflineHeading": "Currently Offline", + "OfflineParagraph": "The media server is currently offline.", + "CheckPageForUpdates": "Check this page for continuous site updates." }, "ErrorPages": { - "NotFound": "Pagina não encontrada" + "NotFound": "Page not found" }, "NavigationBar": { - "Discover": "Explorar", - "Search": "Pesquisar", - "Requests": "Solicitações", - "UserManagement": "User Management", - "Issues": "Problemas", - "Vote": "Votar", - "Donate": "Doações!", - "DonateLibraryMaintainer": "Doar para o Dono da Biblioteca", - "DonateTooltip": "É assim que convenço minha esposa a me deixar passar o meu tempo livre desenvolvendo o Ombi 😁", - "UpdateAvailableTooltip": "Atualização Disponível!", - "Settings": "Configurações", - "Welcome": "Bem-vindo(a), {{username}}", - "UpdateDetails": "Detalhes da Atualização", - "Logout": "Desconectar", - "OpenMobileApp": "Abrir Aplicativo do Celular", - "RecentlyAdded": "Recentemente Adicionado", - "ChangeTheme": "Trocar Tema", - "Calendar": "Calendário", - "UserPreferences": "Preferências", - "FeatureSuggestion": "Feature Suggestion", - "FeatureSuggestionTooltip": "Teve uma ótima idéia? Sugira aqui!", + "Discover": "Discover", + "Search": "Search", + "Requests": "Requests", + "UserManagement": "Users", + "Issues": "Issues", + "Vote": "Vote", + "Donate": "Donate!", + "DonateLibraryMaintainer": "Donate to Library Maintainer", + "DonateTooltip": "This is how I convince my wife to let me spend my spare time developing Ombi 😁", + "UpdateAvailableTooltip": "Update Available!", + "Settings": "Settings", + "Welcome": "Welcome {{username}}", + "UpdateDetails": "Update Details", + "Logout": "Logout", + "OpenMobileApp": "Open Mobile App", + "RecentlyAdded": "Recently Added", + "ChangeTheme": "Change Theme", + "Calendar": "Calendar", + "UserPreferences": "Preferences", + "FeatureSuggestion": "Features", + "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", "Filter": { - "Movies": "Filmes", - "TvShows": "Séries", - "Music": "Músicas", - "People": "Pessoas" + "Movies": "Movies", + "TvShows": "TV Shows", + "Music": "Music", + "People": "People" }, - "MorningWelcome": "Bom dia!", - "AfternoonWelcome": "Boa tarde!", - "EveningWelcome": "Boa noite!" + "MorningWelcome": "Good morning!", + "AfternoonWelcome": "Good afternoon!", + "EveningWelcome": "Good evening!" }, "Search": { - "Title": "Pesquisar", - "Paragraph": "Quer assistir a algo que não está disponível? Sem problemas, basta pesquisar abaixo e solicitar!", - "MoviesTab": "Filmes", - "TvTab": "Séries", - "MusicTab": "Músicas", - "AdvancedSearch": "Você pode preencher qualquer um dos abaixo para descobrir novas mídias. Todos os resultados são classificados por popularidade", - "AdvancedSearchHeader": "Pesquisa avançada", - "Suggestions": "Sugestões", - "NoResults": "Desculpe, não encontramos nenhum resultado!", - "DigitalDate": "Lançamento Digital: {{date}}", - "TheatricalRelease": "Lançamento nos Cinemas: {{date}}", - "ViewOnPlex": "View On Plex", - "ViewOnEmby": "View On Emby", - "ViewOnJellyfin": "Assistir no Jellyfin", - "RequestAdded": "O pedido de {{title}} foi adicionado com sucesso", - "Similar": "Semelhantes", - "Refine": "Corrigir", - "SearchBarPlaceholder": "Digite Aqui para Pesquisar", + "Title": "Search", + "Paragraph": "Want to watch something that is not currently available? No problem, just search for it below and request it!", + "MoviesTab": "Movies", + "TvTab": "TV Shows", + "MusicTab": "Music", + "AdvancedSearch": "You can fill in any of the below to discover new media. All of the results are sorted by popularity", + "AdvancedSearchHeader": "Advanced Search", + "Suggestions": "Suggestions", + "NoResults": "Sorry, we didn't find any results!", + "DigitalDate": "Digital Release: {{date}}", + "TheatricalRelease": "Theatrical Release: {{date}}", + "ViewOnPlex": "Play On Plex", + "ViewOnEmby": "Play On Emby", + "ViewOnJellyfin": "Play On Jellyfin", + "RequestAdded": "Request for {{title}} has been added successfully", + "Similar": "Similar", + "Refine": "Refine", + "SearchBarPlaceholder": "Type Here to Search", "Movies": { - "PopularMovies": "Filmes Populares", - "UpcomingMovies": "Filmes Em Breve", - "TopRatedMovies": "Filmes Mais Votados", - "NowPlayingMovies": "Filmes em Cartaz", - "HomePage": "Página Inicial", + "PopularMovies": "Popular Movies", + "UpcomingMovies": "Upcoming Movies", + "TopRatedMovies": "Top Rated Movies", + "NowPlayingMovies": "Now Playing Movies", + "HomePage": "Home Page", "Trailer": "Trailer" }, "TvShows": { "Popular": "Popular", - "Trending": "Tendências", - "MostWatched": "Mais Assistidos", - "MostAnticipated": "Mais Aguardados", - "Results": "Resultados", - "AirDate": "Data de Exibição:", - "AllSeasons": "Todas as Temporadas", - "FirstSeason": "Primeira temporada", - "LatestSeason": "Última Temporada", - "Select": "Selecionar...", - "SubmitRequest": "Enviar solicitação", - "Season": "Temporada: {{seasonNumber}}", - "SelectAllInSeason": "Selecione Tudo na Temporada {{seasonNumber}}" + "Trending": "Trending", + "MostWatched": "Most Watched", + "MostAnticipated": "Most Anticipated", + "Results": "Results", + "AirDate": "Air Date:", + "AllSeasons": "All Seasons", + "FirstSeason": "First Season", + "LatestSeason": "Latest Season", + "Select": "Select ...", + "SubmitRequest": "Submit Request", + "Season": "Season {{seasonNumber}}", + "SelectAllInSeason": "Select All in Season {{seasonNumber}}" }, - "AdvancedSearchInstructions": "Por favor, escolha o tipo de mídia que você está procurando:", - "YearOfRelease": "Ano de lançamento", - "SearchGenre": "Pesquisa por gênero", - "SearchKeyword": "Pesquisar palavras-chave", - "SearchProvider": "Provedores de pesquisa", - "KeywordSearchingDisclaimer": "Por favor, note que a busca por palavra-chave é muito acertada e perdida devido aos dados inconsistentes no TheMovieDb" + "AdvancedSearchInstructions": "Please choose what type of media you are searching for:", + "YearOfRelease": "Year of Release", + "SearchGenre": "Search Genre", + "SearchKeyword": "Search Keyword", + "SearchProvider": "Search Provider", + "KeywordSearchingDisclaimer": "Please note that Keyword Searching is very hit and miss due to the inconsistent data in TheMovieDb" }, "Requests": { - "Title": "Solicitações", - "Paragraph": "Abaixo, você pode ver o seu e todos os outros pedidos, bem como o seu download e status de aprovação.", - "MoviesTab": "Filmes", - "ArtistName": "Artistas", - "AlbumName": "Nome do álbum", - "TvTab": "Séries", - "MusicTab": "Músicas", - "RequestedBy": "Solicitado por", + "Title": "Requests", + "Paragraph": "Below you can see yours and all other requests, as well as their download and approval status.", + "MoviesTab": "Movies", + "ArtistName": "Artist", + "AlbumName": "Album Name", + "TvTab": "TV Shows", + "MusicTab": "Music", + "RequestedBy": "Requested By", "Status": "Status", - "RequestStatus": "Status da solicitação", - "Denied": " Negados:", - "TheatricalRelease": "Lançamento nos Cinemas: {{date}}", - "ReleaseDate": "Lançado: {{date}}", - "TheatricalReleaseSort": "Lançamento nos Cinemas", - "DigitalRelease": "Lançamento Digital: {{date}}", - "RequestDate": "Data da Solicitação", - "QualityOverride": "Substituição de Qualidade:", - "RootFolderOverride": "Substituição da Pasta Raiz:", - "ChangeRootFolder": "Pasta Raiz", - "ChangeQualityProfile": "Perfil de Qualidade", - "MarkUnavailable": "Marcar como Indisponível", - "MarkAvailable": "Marcar como Disponível", - "Remove": "Remover", - "Deny": "Negar", - "DenyReason": "Razão da rejeição", - "DeniedReason": "Razão da rejeição", - "Season": "Temporada", - "GridTitle": "Título", - "AirDate": "AirDate", + "RequestStatus": "Request status", + "Denied": " Denied:", + "TheatricalRelease": "Theatrical Release: {{date}}", + "ReleaseDate": "Released: {{date}}", + "TheatricalReleaseSort": "Theatrical Release", + "DigitalRelease": "Digital Release: {{date}}", + "RequestDate": "Request Date", + "QualityOverride": "Quality Override:", + "RootFolderOverride": "Root Folder Override:", + "ChangeRootFolder": "Root Folder", + "ChangeQualityProfile": "Quality Profile", + "MarkUnavailable": "Mark Unavailable", + "MarkUnavailable4K": "Mark Unavailable 4K", + "MarkAvailable": "Mark Available", + "MarkAvailable4K": "Mark Available 4K", + "Remove": "Remove", + "Deny": "Deny", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", + "DenyReason": "Deny Reason", + "DeniedReason": "Denied Reason", + "Season": "Season", + "GridTitle": "Title", + "AirDate": "Air Date", "GridStatus": "Status", - "ReportIssue": "Relatar Problema", - "Filter": "Filtro", - "Sort": "Ordenar por", - "SeasonNumberHeading": "Temporada: {seasonNumber}", - "SortTitleAsc": "Título ▲", - "SortTitleDesc": "Título ▼", - "SortRequestDateAsc": "Data da Solicitação ▲", - "SortRequestDateDesc": "Data da Solicitação ▼", + "ReportIssue": "Report Issue", + "Filter": "Filter", + "Sort": "Sort", + "SeasonNumberHeading": "Season: {seasonNumber}", + "SortTitleAsc": "Title ▲", + "SortTitleDesc": "Title ▼", + "SortRequestDateAsc": "Request Date ▲", + "SortRequestDateDesc": "Request Date ▼", "SortStatusAsc": "Status ▲", "SortStatusDesc": "Status ▼", "Remaining": { - "Quota": "{{remaining}}/{{total}} solicitações restantes", - "NextDays": "Outra solicitação será adicionada em {{time}} dias", - "NextHours": "Outra solicitação será adicionada em {{time}} horas", - "NextMinutes": "Outra solicitação será adicionada em {{time}} minutos", - "NextMinute": "Outra solicitação será adicionada em {{time}} minuto" + "Quota": "{{remaining}}/{{total}} requests remaining", + "NextDays": "Another request will be added in {{time}} days", + "NextHours": "Another request will be added in {{time}} hours", + "NextMinutes": "Another request will be added in {{time}} minutes", + "NextMinute": "Another request will be added in {{time}} minute" }, - "AllRequests": "Todas solicitações", - "PendingRequests": "Solicitações pendentes", - "ProcessingRequests": "Solicitações em andamento", - "AvailableRequests": "Solicitação Disponíveis", - "DeniedRequests": "Solicitações Negadas", - "RequestsToDisplay": "Itens por página", - "RequestsTitle": "Título", - "Details": "Detalhes", - "Options": "Opções", + "AllRequests": "All Requests", + "PendingRequests": "Pending Requests", + "ProcessingRequests": "Processing Requests", + "AvailableRequests": "Available Requests", + "DeniedRequests": "Denied Requests", + "RequestsToDisplay": "Requests to display", + "RequestsTitle": "Title", + "Details": "Details", + "Options": "Options", "RequestPanel": { - "Delete": "Apagar Solicitação", + "Delete": "Delete Request", "Approve": "Approve Request", + "Deny": "Deny Request", + "Approve4K": "Approve 4K Request", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Mark Available", "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Approved": "Successfully approved selected items", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Successfully Approved", "SuccessfullyDeleted": "Request successfully deleted", @@ -234,25 +246,25 @@ "CouldntNotify": "Couldn't notify title {{title}}" }, "Issues": { - "Title": "Problemas", + "Title": "Issues", "IssuesForTitle": "Issues for {{title}}", - "PendingTitle": "Problemas pendentes", - "InProgressTitle": "Problemas em resolução", - "ResolvedTitle": "Problemas Resolvidos", - "ColumnTitle": "Título", + "PendingTitle": "Pending Issues", + "InProgressTitle": "In Progress Issues", + "ResolvedTitle": "Resolved Issues", + "ColumnTitle": "Title", "Count": "Count", - "Category": "Categoria", + "Category": "Category", "Status": "Status", - "Details": "Detalhes", - "Description": "Descrição", - "NoComments": "Sem Comentários!", - "MarkInProgress": "Marcar como em andamento", - "MarkResolved": "Marcar como resolvido", - "SendMessageButton": "Enviar", - "Subject": "Assunto", - "Comments": "Comentários", - "WriteMessagePlaceholder": "Escreva sua mensagem aqui...", - "ReportedBy": "Reportado por", + "Details": "Details", + "Description": "Description", + "NoComments": "No Comments!", + "MarkInProgress": "Mark In Progress", + "MarkResolved": "Mark Resolved", + "SendMessageButton": "Send", + "Subject": "Subject", + "Comments": "Comments", + "WriteMessagePlaceholder": "Write your message here...", + "ReportedBy": "Reported By", "IssueDialog": { "Title": "Report an issue", "DescriptionPlaceholder": "Please describe the issue", @@ -269,39 +281,40 @@ "DeletedIssue": "Issue has been deleted", "Chat": "Chat", "EnterYourMessage": "Enter Your Message", - "Requested": "Requested", + "Requested": "Pedido", "UserOnDate": "{{user}} on {{date}}" }, "Filter": { - "ClearFilter": "Limpar Filtro", - "FilterHeaderAvailability": "Disponibilidade", + "ClearFilter": "Clear Filter", + "FilterHeaderAvailability": "Availability", "FilterHeaderRequestStatus": "Status", - "Approved": "Aprovado", + "Approved": "Approved", "PendingApproval": "Aprovação Pendente", "WatchProviders": "Watch Providers", "Keywords": "Keywords" }, "UserManagment": { - "TvRemaining": "Séries: {{remaining}}/{{total}} restantes", - "MovieRemaining": "Filmes: {{remaining}}/{{total}} restantes", - "MusicRemaining": "Músicas: {{remaining}}/{{total}} restantes", - "TvDue": "Série: {{date}}", - "MovieDue": "Filme: {{date}}", - "MusicDue": "Música: {{date}}" + "TvRemaining": "TV: {{remaining}}/{{total}} remaining", + "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", + "TvDue": "TV: {{date}}", + "MovieDue": "Movie: {{date}}", + "MusicDue": "Music: {{date}}" }, "Votes": { - "CompletedVotesTab": "Votado", - "VotesTab": "Votos necessários" + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" }, "MediaDetails": { - "Denied": "Denied", + "Denied": "Recusado", + "Denied4K": "Denied 4K", "Trailers": "Trailers", "RecommendationsTitle": "Recommendations", "SimilarTitle": "Similar", - "VideosTitle": "Vídeos", - "AlbumsTitle": "Álbuns", - "RequestAllAlbums": "Solicitar Todos Álbuns", - "ClearSelection": "Limpar Seleção", + "VideosTitle": "Videos", + "AlbumsTitle": "Albums", + "RequestAllAlbums": "Request All Albums", + "ClearSelection": "Clear Selection", "RequestSelectedAlbums": "Request Selected Albums", "ViewCollection": "View Collection", "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", @@ -363,12 +376,14 @@ "RequestDate": "Request Date:", "DeniedReason": "Denied Reason:", "ReProcessRequest": "Re-Process Request", + "ReProcessRequest4K": "Re-Process 4K Request", "Music": { "Type": "Type:", "Country": "Country:", "StartDate": "Start Date:", "EndDate": "EndDate:" - } + }, + "RequestSource": "Origem:" }, "Discovery": { "PopularTab": "Popular", diff --git a/src/Ombi/wwwroot/translations/ru.json b/src/Ombi/wwwroot/translations/ru.json index 0f57f9c31..b60adcaaa 100644 --- a/src/Ombi/wwwroot/translations/ru.json +++ b/src/Ombi/wwwroot/translations/ru.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Продолжить", "Available": "Доступно", - "Approved": "Approved", + "Available4K": "Available 4K", + "Approved": "Одобрено", + "Approve4K": "Approve 4K", "Pending": "Pending", "PartiallyAvailable": "Частично доступно", "Monitored": "Мониторинг", @@ -24,8 +26,10 @@ "RequestDenied": "Запрос отклонен", "NotRequested": "Не запрошено", "Requested": "Запрошено", - "Search": "Search", + "Requested4K": "Requested 4K", + "Search": "Поиск", "Request": "Запросить", + "Request4K": "Request 4K", "Denied": "Отказано", "Approve": "Одобрить", "PartlyAvailable": "Частично доступно", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Корневая папка", "ChangeQualityProfile": "Профиль качества", "MarkUnavailable": "Отметить недоступным", + "MarkUnavailable4K": "Mark Unavailable 4K", "MarkAvailable": "Отметить доступным", + "MarkAvailable4K": "Mark Available 4K", "Remove": "Удалить", "Deny": "Отклонить", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", "DenyReason": "Deny Reason", "DeniedReason": "Denied Reason", "Season": "Сезон", @@ -199,9 +207,13 @@ "RequestPanel": { "Delete": "Delete Request", "Approve": "Approve Request", - "ChangeAvailability": "Mark Available", + "Deny": "Deny Request", + "Approve4K": "Approve 4K Request", + "Deny4K": "Deny 4K Request", + "ChangeAvailability": "Отметить доступным", "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Approved": "Successfully approved selected items", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Successfully Approved", "SuccessfullyDeleted": "Request successfully deleted", @@ -212,7 +224,7 @@ "RequestCollection": "Request Collection", "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", "NeedToSelectEpisodes": "You need to select some episodes!", - "RequestAddedSuccessfully": "Request for {{title}} has been added successfully", + "RequestAddedSuccessfully": "Запрос на {{title}} успешно добавлен", "ErrorCodes": { "AlreadyRequested": "This has already been requested", "EpisodesAlreadyRequested": "We already have episodes requested from this series", @@ -269,7 +281,7 @@ "DeletedIssue": "Issue has been deleted", "Chat": "Chat", "EnterYourMessage": "Enter Your Message", - "Requested": "Requested", + "Requested": "Запрошено", "UserOnDate": "{{user}} on {{date}}" }, "Filter": { @@ -295,6 +307,7 @@ }, "MediaDetails": { "Denied": "Отказано", + "Denied4K": "Denied 4K", "Trailers": "Trailers", "RecommendationsTitle": "Recommendations", "SimilarTitle": "Похожие", @@ -312,7 +325,7 @@ "QualityProfilesSelect": "Select A Quality Profile", "RootFolderSelect": "Select A Root Folder", "LanguageProfileSelect": "Select A Language Profile", - "Status": "Status:", + "Status": "Статус:", "StatusValues": { "Rumored": "Rumored", "Planned": "Planned", @@ -326,16 +339,16 @@ }, "Seasons": "Seasons:", "Episodes": "Episodes:", - "Availability": "Availability:", + "Availability": "Доступность:", "RequestStatus": "Request Status", "Quality": "Quality:", - "RootFolderOverride": "Root Folder Override:", - "QualityOverride": "Quality Override:", + "RootFolderOverride": "Переопределение корневой папки:", + "QualityOverride": "Переопределение качества:", "Network": "Network:", "GenresLabel": "Genres:", "Genres": "Genres", "FirstAired": "First Aired:", - "TheatricalRelease": "Release:", + "TheatricalRelease": "Релиз в кинотеатрах:", "DigitalRelease": "Digital Release:", "Votes": "Votes:", "Runtime": "Runtime:", @@ -351,24 +364,26 @@ "FirstSeasonTooltip": "This will only request the First Season for this show", "LatestSeasonTooltip": "This will only request the Latest Season for this show", "NoEpisodes": "There unfortunately is no episode data for this show yet!", - "SeasonNumber": "Season {{number}}" + "SeasonNumber": "Сезон {{number}}" }, "SonarrConfiguration": "Sonarr Configuration", "RadarrConfiguration": "Radarr Configuration", "RequestOnBehalf": "Request on behalf of", "PleaseSelectUser": "Please select a user", "StreamingOn": "Streaming On:", - "RequestedBy": "Requested By:", + "RequestedBy": "Автор запроса:", "RequestedByOn": "Requested By {{user}} on {{date}}", - "RequestDate": "Request Date:", + "RequestDate": "Дата запроса:", "DeniedReason": "Denied Reason:", "ReProcessRequest": "Re-Process Request", + "ReProcessRequest4K": "Re-Process 4K Request", "Music": { "Type": "Type:", "Country": "Country:", "StartDate": "Start Date:", "EndDate": "EndDate:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Популярное", @@ -408,7 +423,7 @@ "ChangeDetails": "Change Details", "NeedCurrentPassword": "You need your current password to make any changes here", "CurrentPassword": "Current Password", - "EmailAddress": "Email Address", + "EmailAddress": "Адрес эл. почты", "NewPassword": "New Password", "NewPasswordConfirm": "New Password Confirm", "Security": "Security", diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json index 1e0ae25cf..b13ddd8ff 100644 --- a/src/Ombi/wwwroot/translations/sk.json +++ b/src/Ombi/wwwroot/translations/sk.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Pokračovať", "Available": "Dostupné", + "Available4K": "Available 4K", "Approved": "Schválené", + "Approve4K": "Approve 4K", "Pending": "Čakajúce", "PartiallyAvailable": "Čiastočne dostupné", "Monitored": "Sledované", @@ -24,8 +26,10 @@ "RequestDenied": "Požiadavka zamietnutá", "NotRequested": "Nepožiadané", "Requested": "Požiadané", + "Requested4K": "Requested 4K", "Search": "Hľadať", "Request": "Požiadať", + "Request4K": "Request 4K", "Denied": "Zamietnuté", "Approve": "Schválené", "PartlyAvailable": "Čiastočne dostupné", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Koreňový priečinok", "ChangeQualityProfile": "Profil kvality", "MarkUnavailable": "Označiť nedostupné", + "MarkUnavailable4K": "Mark Unavailable 4K", "MarkAvailable": "Označiť dostupné", + "MarkAvailable4K": "Mark Available 4K", "Remove": "Odstrániť", "Deny": "Odmietnuť", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", "DenyReason": "Odmietnuť dôvod", "DeniedReason": "Odmietnuť dôvod", "Season": "Séria", @@ -199,9 +207,13 @@ "RequestPanel": { "Delete": "Odstrániž požiadavku", "Approve": "Schváliť žiadosť", + "Deny": "Deny Request", + "Approve4K": "Approve 4K Request", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Označiť k dispozícií", "Deleted": "Úspešne odstránené vybrané položky", - "Approved": "Úspešne schválené vybrané položky" + "Approved": "Úspešne schválené vybrané položky", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Úspešne schválené", "SuccessfullyDeleted": "Žiadosť bola úspešne vymazaná", @@ -295,6 +307,7 @@ }, "MediaDetails": { "Denied": "Zamietnuté", + "Denied4K": "Denied 4K", "Trailers": "Upútavka", "RecommendationsTitle": "Odporúčania", "SimilarTitle": "Podobné", @@ -363,12 +376,14 @@ "RequestDate": "Dátum požiadavky:", "DeniedReason": "Dôvod zamietnutia:", "ReProcessRequest": "Žiadosť o opätovné spracovanie", + "ReProcessRequest4K": "Re-Process 4K Request", "Music": { "Type": "Typ:", "Country": "Krajina:", "StartDate": "Dátum začatia:", "EndDate": "Dátum ukončenia:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Populárne", diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 8532930be..7b4ba0439 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Fortsätt", "Available": "Tillgänglig", - "Approved": "Approved", + "Available4K": "Tillgänglig 4K", + "Approved": "Godkänd", + "Approve4K": "Godkänn 4K", "Pending": "Pending", "PartiallyAvailable": "Delvis tillgänglig", "Monitored": "Övervakad", @@ -24,8 +26,10 @@ "RequestDenied": "Efterfrågan nekas", "NotRequested": "Inte begärd", "Requested": "Begärd", - "Search": "Search", + "Requested4K": "Begärd 4K", + "Search": "Sök", "Request": "Begär", + "Request4K": "Begär 4K", "Denied": "Nekad", "Approve": "Godkänn", "PartlyAvailable": "Delvis tillgänglig", @@ -104,7 +108,7 @@ "TheatricalRelease": "Biopremiär: {{date}}", "ViewOnPlex": "Visa på Plex", "ViewOnEmby": "Visa på Emby", - "ViewOnJellyfin": "Play On Jellyfin", + "ViewOnJellyfin": "Spela på Jellyfin", "RequestAdded": "Begäran av {{title}} har lagts till", "Similar": "Liknande", "Refine": "Förfina", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Byt rotmapp", "ChangeQualityProfile": "Byt kvalitétsprofil", "MarkUnavailable": "Markera Otillgänglig", + "MarkUnavailable4K": "Markera som ej tillgänglig 4K", "MarkAvailable": "Markera Tillgänglig", + "MarkAvailable4K": "Markera som tillgänglig 4K", "Remove": "Ta bort", "Deny": "Neka", + "Deny4K": "Neka 4K", + "Has4KRequest": "Har 4K-förfrågan", "DenyReason": "Anledning för nekande", "DeniedReason": "Denied Reason", "Season": "Säsong", @@ -199,9 +207,13 @@ "RequestPanel": { "Delete": "Ta bort förfrågan", "Approve": "Godkänn begäran", + "Deny": "Deny Request", + "Approve4K": "Godkänn 4K-begäran", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Markera Tillgänglig", "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Approved": "Successfully approved selected items", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Successfully Approved", "SuccessfullyDeleted": "Request successfully deleted", @@ -212,7 +224,7 @@ "RequestCollection": "Request Collection", "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", "NeedToSelectEpisodes": "You need to select some episodes!", - "RequestAddedSuccessfully": "Request for {{title}} has been added successfully", + "RequestAddedSuccessfully": "Begäran av {{title}} har lagts till", "ErrorCodes": { "AlreadyRequested": "This has already been requested", "EpisodesAlreadyRequested": "We already have episodes requested from this series", @@ -269,7 +281,7 @@ "DeletedIssue": "Problemet har tagits bort", "Chat": "Chat", "EnterYourMessage": "Enter Your Message", - "Requested": "Requested", + "Requested": "Begärd", "UserOnDate": "{{user}} on {{date}}" }, "Filter": { @@ -295,6 +307,7 @@ }, "MediaDetails": { "Denied": "Nekad", + "Denied4K": "Nekad 4K", "Trailers": "Trailers", "RecommendationsTitle": "Rekommendationer", "SimilarTitle": "Liknande", @@ -326,23 +339,23 @@ }, "Seasons": "Seasons:", "Episodes": "Episodes:", - "Availability": "Availability:", + "Availability": "Tillgänglighet:", "RequestStatus": "Status för begäran", - "Quality": "Quality:", - "RootFolderOverride": "Root Folder Override:", - "QualityOverride": "Quality Override:", - "Network": "Network:", - "GenresLabel": "Genres:", - "Genres": "Genres", - "FirstAired": "First Aired:", - "TheatricalRelease": "Release:", - "DigitalRelease": "Digital Release:", - "Votes": "Votes:", - "Runtime": "Runtime:", + "Quality": "Kvalitet:", + "RootFolderOverride": "Rotmappsöverskridande:", + "QualityOverride": "Kvalitétsöverskridande:", + "Network": "Tv-nätverk:", + "GenresLabel": "Genrer:", + "Genres": "Genrer", + "FirstAired": "Sändes första gången:", + "TheatricalRelease": "Biopremiär:", + "DigitalRelease": "Digital release:", + "Votes": "Röster:", + "Runtime": "Speltid:", "Minutes": "{{runtime}} minuter", - "Revenue": "Revenue:", + "Revenue": "Intäkter:", "Budget": "Budget:", - "Keywords": "Keywords/Tags:", + "Keywords": "Nyckelord/Taggar:", "Casts": { "CastTitle": "Rollista" }, @@ -351,24 +364,26 @@ "FirstSeasonTooltip": "Detta kommer endast att begära den första säsongen för denna serie", "LatestSeasonTooltip": "Detta kommer endast att begära den senaste säsongen för denna serie", "NoEpisodes": "There unfortunately is no episode data for this show yet!", - "SeasonNumber": "Season {{number}}" + "SeasonNumber": "Säsong {{number}}" }, - "SonarrConfiguration": "Sonarr Configuration", - "RadarrConfiguration": "Radarr Configuration", - "RequestOnBehalf": "Request on behalf of", - "PleaseSelectUser": "Please select a user", - "StreamingOn": "Streaming On:", - "RequestedBy": "Requested By:", + "SonarrConfiguration": "Sonarr Konfiguration", + "RadarrConfiguration": "Radarr Konfiguration", + "RequestOnBehalf": "På begäran av", + "PleaseSelectUser": "Vänligen välj en användare", + "StreamingOn": "Strömmar på:", + "RequestedBy": "Efterfrågats av:", "RequestedByOn": "Requested By {{user}} on {{date}}", - "RequestDate": "Request Date:", + "RequestDate": "Datum för begäran:", "DeniedReason": "Denied Reason:", "ReProcessRequest": "Re-Process Request", + "ReProcessRequest4K": "Omarbeta 4K-förfrågan", "Music": { "Type": "Type:", "Country": "Country:", "StartDate": "Start Date:", "EndDate": "EndDate:" - } + }, + "RequestSource": "Källa:" }, "Discovery": { "PopularTab": "Populära", @@ -391,13 +406,13 @@ "Writer": "Författare", "ExecProducer": "Exekutiv producent" }, - "NoSearch": "Sorry, nothing matches your search!" + "NoSearch": "Tyvärr, inget matchar din sökning!" }, "UserPreferences": { "Welcome": "Välkommen {{username}}!", "OmbiLanguage": "Språk", "DarkMode": "Mörkt läge", - "Updated": "Successfully Updated", + "Updated": "Uppdatering lyckades", "StreamingCountry": "Streaming Country", "StreamingCountryDescription": "This is the country code that we will display streaming information for. If you are in the US please select US and you will get US related streaming information.", "LanguageDescription": "This is the language you would like the Ombi interface to be displayed in.", @@ -408,7 +423,7 @@ "ChangeDetails": "Change Details", "NeedCurrentPassword": "You need your current password to make any changes here", "CurrentPassword": "Current Password", - "EmailAddress": "Email Address", + "EmailAddress": "E-postadress", "NewPassword": "New Password", "NewPasswordConfirm": "New Password Confirm", "Security": "Security", diff --git a/src/Ombi/wwwroot/translations/zh-TW.json b/src/Ombi/wwwroot/translations/zh-TW.json new file mode 100644 index 000000000..16d8d9adf --- /dev/null +++ b/src/Ombi/wwwroot/translations/zh-TW.json @@ -0,0 +1,450 @@ +{ + "Login": { + "SignInButton": "登录", + "UsernamePlaceholder": "用户名", + "PasswordPlaceholder": "密码", + "RememberMe": "记住我", + "SignInWith": "使用 {{appName}} 登录", + "SignInWithPlex": "使用 Plex 登录", + "ForgottenPassword": "忘记密码?", + "Errors": { + "IncorrectCredentials": "用户名或密码错误" + } + }, + "Common": { + "ContinueButton": "继续", + "Available": "可播放", + "Available4K": "Available 4K", + "Approved": "已批准", + "Approve4K": "Approve 4K", + "Pending": "待审核", + "PartiallyAvailable": "部分可播放", + "Monitored": "监控中", + "NotAvailable": "不可播放", + "ProcessingRequest": "处理中请求", + "PendingApproval": "等待批准", + "RequestDenied": "请求被拒绝", + "NotRequested": "未请求", + "Requested": "已请求", + "Requested4K": "Requested 4K", + "Search": "搜索", + "Request": "请求", + "Request4K": "Request 4K", + "Denied": "已拒绝", + "Approve": "批准", + "PartlyAvailable": "部分可播放", + "ViewDetails": "查看详情", + "Errors": { + "Validation": "请检查您输入的值" + }, + "Cancel": "取消", + "Submit": "提交", + "Update": "更新", + "tvShow": "电视节目", + "movie": "电影", + "album": "专辑" + }, + "PasswordReset": { + "EmailAddressPlaceholder": "邮箱", + "ResetPasswordButton": "重置密码" + }, + "LandingPage": { + "OnlineHeading": "当前在线", + "OnlineParagraph": "媒体服务器当前在线", + "PartiallyOnlineHeading": "部分在线", + "PartiallyOnlineParagraph": "媒体服务器部分在线", + "MultipleServersUnavailable": "{{totalServers}} 个服务器中有{{serversUnavailable}} 个已离线", + "SingleServerUnavailable": "{{totalServers}} 个服务器中有{{serversUnavailable}} 个已离线", + "OfflineHeading": "当前离线", + "OfflineParagraph": "媒体服务器当前离线", + "CheckPageForUpdates": "检查此页面以获取站点连续更新。" + }, + "ErrorPages": { + "NotFound": "找不到页面" + }, + "NavigationBar": { + "Discover": "发现", + "Search": "搜索", + "Requests": "请求", + "UserManagement": "用户", + "Issues": "问题", + "Vote": "投票", + "Donate": "捐助", + "DonateLibraryMaintainer": "捐赠给维护者", + "DonateTooltip": "这是我说服我妻子让我继续利用业余时间开发Ombi的途径 😁", + "UpdateAvailableTooltip": "有可用更新!", + "Settings": "设置", + "Welcome": "{{username}},欢迎您", + "UpdateDetails": "更新详请", + "Logout": "登出", + "OpenMobileApp": "打开移动应用", + "RecentlyAdded": "最近添加", + "ChangeTheme": "更改主题", + "Calendar": "日历", + "UserPreferences": "偏好设置", + "FeatureSuggestion": "功能", + "FeatureSuggestionTooltip": "有一个很棒的新想法吗?在这里建议!", + "Filter": { + "Movies": "电影", + "TvShows": "电视节目", + "Music": "音乐", + "People": "人员" + }, + "MorningWelcome": "早上好!", + "AfternoonWelcome": "下午好!", + "EveningWelcome": "晚上好!" + }, + "Search": { + "Title": "搜索", + "Paragraph": "想要观看当前无法观看的内容吗?没问题,只需在下方搜索并请求!", + "MoviesTab": "电影", + "TvTab": "电视节目", + "MusicTab": "音乐", + "AdvancedSearch": "您可以填写以下任何一项来发现新媒体,所有结果都按受欢迎程度排序。", + "AdvancedSearchHeader": "高级搜索", + "Suggestions": "建议", + "NoResults": "对不起,我们没有找到任何结果。", + "DigitalDate": "数字版发行:{{date}}", + "TheatricalRelease": "剧场版发行:{{date}}", + "ViewOnPlex": "在Plex上播放", + "ViewOnEmby": "在 Emby上播放", + "ViewOnJellyfin": "在 Jellyfin上播放", + "RequestAdded": "{{title}} 的请求已成功添加", + "Similar": "相似", + "Refine": "精选", + "SearchBarPlaceholder": "在这里输入搜索内容", + "Movies": { + "PopularMovies": "热门电影", + "UpcomingMovies": "即将上映的电影", + "TopRatedMovies": "高评分的电影", + "NowPlayingMovies": "正在播放的电影", + "HomePage": "主页", + "Trailer": "预告片" + }, + "TvShows": { + "Popular": "热门", + "Trending": "趋势", + "MostWatched": "观看次数最多", + "MostAnticipated": "最期待", + "Results": "结果", + "AirDate": "播出日期:", + "AllSeasons": "所有季", + "FirstSeason": "第一季", + "LatestSeason": "最新季", + "Select": "请选择...", + "SubmitRequest": "提交请求", + "Season": "第{{seasonNumber}} 季", + "SelectAllInSeason": "在所有季中选择第{{seasonNumber}} 季" + }, + "AdvancedSearchInstructions": "请选择您需要搜索的媒体类型:", + "YearOfRelease": "发行年份", + "SearchGenre": "按类型搜索", + "SearchKeyword": "按关键字搜索", + "SearchProvider": "按提供者搜索", + "KeywordSearchingDisclaimer": "请注意,由于TheMovieDb中的数据不一致,关键字搜索方式非常容易出错" + }, + "Requests": { + "Title": "请求", + "Paragraph": "您可以在下方看到您的和所有其他人的请求,以及他们的下载和批准状态", + "MoviesTab": "电影", + "ArtistName": "艺术家", + "AlbumName": "专辑名称", + "TvTab": "电视节目", + "MusicTab": "音乐", + "RequestedBy": "请求者", + "Status": "发行状态", + "RequestStatus": "申请状态", + "Denied": "已拒绝:", + "TheatricalRelease": "剧场版发行:{{date}}", + "ReleaseDate": "已发行: {{date}}", + "TheatricalReleaseSort": "剧场版发行", + "DigitalRelease": "数字版发行:{{date}}", + "RequestDate": "请求日期", + "QualityOverride": "质量覆盖:", + "RootFolderOverride": "根目录覆盖:", + "ChangeRootFolder": "根目录", + "ChangeQualityProfile": "画质配置文件", + "MarkUnavailable": "标记为不可用", + "MarkUnavailable4K": "Mark Unavailable 4K", + "MarkAvailable": "标记为可用", + "MarkAvailable4K": "Mark Available 4K", + "Remove": "删除", + "Deny": "拒绝", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", + "DenyReason": "拒绝原因", + "DeniedReason": "被拒绝原因", + "Season": "季", + "GridTitle": "标题", + "AirDate": "播出日期:", + "GridStatus": "状态", + "ReportIssue": "反馈问题", + "Filter": "筛选", + "Sort": "排序", + "SeasonNumberHeading": "第{seasonNumber} 季", + "SortTitleAsc": "标题 ▲", + "SortTitleDesc": "标题 ▼", + "SortRequestDateAsc": "请求日期 ▲", + "SortRequestDateDesc": "请求日期 ▼", + "SortStatusAsc": "状态 ▲", + "SortStatusDesc": "状态 ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} 个请求剩余", + "NextDays": "将在{{time}} 天内添加另一个请求", + "NextHours": "将在{{time}} 小时后添加另一个请求", + "NextMinutes": "将在{{time}} 分钟内添加另一个请求", + "NextMinute": "将在{{time}} 分钟内添加另一个请求" + }, + "AllRequests": "所有请求", + "PendingRequests": "待处理请求", + "ProcessingRequests": "处理中请求", + "AvailableRequests": "可用请求", + "DeniedRequests": "已拒绝请求", + "RequestsToDisplay": "显示请求", + "RequestsTitle": "标题", + "Details": "详情", + "Options": "选项", + "RequestPanel": { + "Delete": "删除请求", + "Approve": "批准请求", + "Deny": "Deny Request", + "Approve4K": "Approve 4K Request", + "Deny4K": "Deny 4K Request", + "ChangeAvailability": "标记为可用", + "Deleted": "所选项目已删除", + "Approved": "所选项目已批准", + "Denied": "Successfully denied selected items" + }, + "SuccessfullyApproved": "批准成功", + "SuccessfullyDeleted": "删除请求成功", + "NowAvailable": "请求现在可观看", + "NowUnavailable": "请求现在不可观看", + "SuccessfullyReprocessed": "重新处理请求成功", + "DeniedRequest": "已拒绝请求", + "RequestCollection": "请求合集", + "CollectionSuccesfullyAdded": "合集 {{name}} 已成功添加!", + "NeedToSelectEpisodes": "您需要选择集数!", + "RequestAddedSuccessfully": "{{title}} 的请求已成功添加", + "ErrorCodes": { + "AlreadyRequested": "请求已经存在", + "EpisodesAlreadyRequested": "已存在这个系列的剧集请求", + "NoPermissionsOnBehalf": "您没有代表用户请求的正确权限!", + "NoPermissions": "您没有正确的权限!", + "RequestDoesNotExist": "请求不存在", + "ChildRequestDoesNotExist": "子请求不存在", + "NoPermissionsRequestMovie": "您没有请求电影的权限", + "NoPermissionsRequestTV": "您没有请求电视节目的权限", + "NoPermissionsRequestAlbum": "您没有请求专辑的权限", + "MovieRequestQuotaExceeded": "您的电影请求已超出配额!", + "TvRequestQuotaExceeded": "您的剧集请求已超出配额!", + "AlbumRequestQuotaExceeded": "您的专辑请求已超出配额!" + }, + "Notify": "通知", + "RemoveNotification": "删除通知", + "SuccessfulNotify": "您将收到标题为 {{title}} 的通知", + "SuccessfulUnNotify": "您将不再收到标题为 {{title}} 的通知", + "CouldntNotify": "无法通知标题 {{title}}" + }, + "Issues": { + "Title": "问题", + "IssuesForTitle": "{{title}} 的问题", + "PendingTitle": "待处理的问题", + "InProgressTitle": "正在处理的问题", + "ResolvedTitle": "已解决的问题", + "ColumnTitle": "标题", + "Count": "总计", + "Category": "类别", + "Status": "状态", + "Details": "详情", + "Description": "描述", + "NoComments": "暂无评论", + "MarkInProgress": "标记为进行中", + "MarkResolved": "标记为已解决", + "SendMessageButton": "发送", + "Subject": "主题", + "Comments": "评论", + "WriteMessagePlaceholder": "在这里写下您的留言", + "ReportedBy": "报告人", + "IssueDialog": { + "Title": "反馈问题", + "DescriptionPlaceholder": "请描述您的问题", + "TitlePlaceholder": "简短标题", + "SelectCategory": "选择分类", + "IssueCreated": "问题已创建" + }, + "Outstanding": "未解决的问题", + "ResolvedDate": "解决日期", + "CreatedDate": "提出日期", + "MarkedAsResolved": "此问题已被标记为已解决!", + "MarkedAsInProgress": "此问题已被标记为正在处理中!", + "Delete": "删除问题", + "DeletedIssue": "问题已被删除", + "Chat": "聊天", + "EnterYourMessage": "输入您的消息", + "Requested": "已请求", + "UserOnDate": "{{user}} 在 {{date}}" + }, + "Filter": { + "ClearFilter": "清除筛选", + "FilterHeaderAvailability": "可用性", + "FilterHeaderRequestStatus": "状态", + "Approved": "已批准", + "PendingApproval": "待批准", + "WatchProviders": "观看提供商", + "Keywords": "关键字" + }, + "UserManagment": { + "TvRemaining": "电视节目:{{remaining}}/{{total}} 剩余", + "MovieRemaining": "电影: {{remaining}}/{{total}} 剩余", + "MusicRemaining": "音乐: {{remaining}}/{{total}} 剩余", + "TvDue": "电视节目:{{date}}", + "MovieDue": "电影: {{date}}", + "MusicDue": "音乐: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "已投票", + "VotesTab": "需要投票" + }, + "MediaDetails": { + "Denied": "已拒绝", + "Denied4K": "Denied 4K", + "Trailers": "预告片", + "RecommendationsTitle": "推荐", + "SimilarTitle": "相似", + "VideosTitle": "视频", + "AlbumsTitle": "专辑", + "RequestAllAlbums": "请求所有专辑", + "ClearSelection": "清除已选择", + "RequestSelectedAlbums": "请求选中的专辑", + "ViewCollection": "查看合集", + "NotEnoughInfo": "很遗憾,这个节目还没有足够的信息!", + "AdvancedOptions": "高级选项", + "AutoApproveOptions": "您可以在这里配置请求,一旦请求它将被发送到您的DVR应用程序并将被自动批准! 请注意,这是可选的,只需按请求跳过!", + "AutoApproveOptionsTv": "您可以在这里配置请求,一旦请求它将被发送到您的DVR应用程序并将被自动批准! 如果请求已经在 Sonarr 中并且您设置了它,我们将不会更改根目录或画质配置文件! 请注意,这是可选的,只需按请求跳过!", + "AutoApproveOptionsTvShort": "您可以在这里配置请求,一旦请求它将被发送到您的DVR应用程序! 如果请求已经在 Sonarr 中并且您设置了它,我们将不会更改根目录或画质配置文件! 请注意,这是可选的,只需按请求跳过!", + "QualityProfilesSelect": "请选择画质配置文件", + "RootFolderSelect": "请选择根目录", + "LanguageProfileSelect": "请选择语言配置文件", + "Status": "状态:", + "StatusValues": { + "Rumored": "有想法", + "Planned": "计划中", + "In Production": "制作中", + "Post Production": "后期处理", + "Released": "已发布", + "Running": "运行中", + "Returning Series": "回归系列", + "Ended": "已结束", + "Canceled": "已取消" + }, + "Seasons": "季:", + "Episodes": "集:", + "Availability": "可用性:", + "RequestStatus": "请求状态", + "Quality": "画质:", + "RootFolderOverride": "根目录覆盖:", + "QualityOverride": "质量覆盖:", + "Network": "网络:", + "GenresLabel": "流派", + "Genres": "流派", + "FirstAired": "首播", + "TheatricalRelease": "发行日:", + "DigitalRelease": "数字版发行:", + "Votes": "投票:", + "Runtime": "运行时间:", + "Minutes": "{{runtime}} 分钟", + "Revenue": "收入:", + "Budget": "预算:", + "Keywords": "关键词/标签:", + "Casts": { + "CastTitle": "演员" + }, + "EpisodeSelector": { + "AllSeasonsTooltip": "请求这个节目的每一季", + "FirstSeasonTooltip": "请求这个节目的第一季", + "LatestSeasonTooltip": "只请求这个节目的最新季", + "NoEpisodes": "很遗憾,目前还没有该节目的剧集数据!", + "SeasonNumber": "第{{number}} 季" + }, + "SonarrConfiguration": "Sonarr 配置", + "RadarrConfiguration": "Radarr 配置", + "RequestOnBehalf": "代表请求", + "PleaseSelectUser": "请选择用户", + "StreamingOn": "流媒体:", + "RequestedBy": "请求者:", + "RequestedByOn": "由 {{user}} 在 {{date}} 时请求", + "RequestDate": "请求日期:", + "DeniedReason": "被拒绝原因:", + "ReProcessRequest": "重新处理请求", + "ReProcessRequest4K": "Re-Process 4K Request", + "Music": { + "Type": "类型:", + "Country": "国家:", + "StartDate": "开始日期:", + "EndDate": "结束日期:" + }, + "RequestSource": "Source:" + }, + "Discovery": { + "PopularTab": "热门", + "TrendingTab": "趋势", + "UpcomingTab": "即将上映", + "SeasonalTab": "按季的", + "RecentlyRequestedTab": "最近请求", + "Movies": "电影", + "Combined": "混合", + "Tv": "电视节目", + "CardDetails": { + "Availability": "可用性", + "Studio": "工作室", + "Network": "网络", + "UnknownNetwork": "未知", + "RequestStatus": "请求状态", + "Director": "导演", + "InCinemas": "影院放映", + "FirstAired": "首播", + "Writer": "编剧", + "ExecProducer": "制作发行商" + }, + "NoSearch": "抱歉,没有符合您搜索条件的内容!" + }, + "UserPreferences": { + "Welcome": "{{username}},欢迎您!", + "OmbiLanguage": "语言", + "DarkMode": "深色模式", + "Updated": "更新成功", + "StreamingCountry": "流媒体国家", + "StreamingCountryDescription": "这是我们将显示流媒体信息的国家代码。 如果您在美国,请选择美国并获取美国相关的流媒体信息。", + "LanguageDescription": "您希望Ombi界面显示的语言", + "MobileQRCode": "手机二维码", + "LegacyApp": "启动旧版应用程序", + "NoQrCode": "请联系管理员以启用二维码", + "UserType": "用户类型:", + "ChangeDetails": "变更详情", + "NeedCurrentPassword": "您需要输入当前密码才能进行更改", + "CurrentPassword": "当前密码", + "EmailAddress": "邮箱地址", + "NewPassword": "新密码", + "NewPasswordConfirm": "确认新密码", + "Security": "安全选项", + "Profile": "用户信息", + "UpdatedYourInformation": "您的用户信息已更新", + "Unsubscribed": "取消订阅!" + }, + "UserTypeLabel": { + "1": "本地用户", + "2": "Plex用户", + "3": "Emby用户", + "4": "Emby Connect用户", + "5": "Jellyfin用户" + }, + "Paginator": { + "itemsPerPageLabel": "每页显示项目数:", + "nextPageLabel": "下一页", + "previousPageLabel": "上一页", + "firstPageLabel": "转到第一页", + "lastPageLabel": "转到最后一页", + "rangePageLabel1": "{{length}} 中的第0项", + "rangePageLabel2": "{{length}} 中的第{{startIndex}} 到{{endIndex}} 项" + } +} diff --git a/src/Ombi/wwwroot/translations/zh.json b/src/Ombi/wwwroot/translations/zh.json index 453ef7418..edbdf6e94 100644 --- a/src/Ombi/wwwroot/translations/zh.json +++ b/src/Ombi/wwwroot/translations/zh.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "继续", "Available": "可播放", + "Available4K": "4K可播放", "Approved": "已批准", + "Approve4K": "批准4K", "Pending": "待审核", "PartiallyAvailable": "部分可播放", "Monitored": "监控中", @@ -24,8 +26,10 @@ "RequestDenied": "请求被拒绝", "NotRequested": "未请求", "Requested": "已请求", + "Requested4K": "请求4K", "Search": "搜索", "Request": "请求", + "Request4K": "请求4K", "Denied": "已拒绝", "Approve": "批准", "PartlyAvailable": "部分可播放", @@ -161,9 +165,13 @@ "ChangeRootFolder": "根目录", "ChangeQualityProfile": "画质配置文件", "MarkUnavailable": "标记为不可用", + "MarkUnavailable4K": "标记为不可播放4K", "MarkAvailable": "标记为可用", + "MarkAvailable4K": "标记为可播放4K", "Remove": "删除", "Deny": "拒绝", + "Deny4K": "拒绝4K", + "Has4KRequest": "已有4K请求", "DenyReason": "拒绝原因", "DeniedReason": "被拒绝原因", "Season": "季", @@ -199,9 +207,13 @@ "RequestPanel": { "Delete": "删除请求", "Approve": "批准请求", + "Deny": "Deny Request", + "Approve4K": "批准4K请求", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "标记为可用", "Deleted": "所选项目已删除", - "Approved": "所选项目已批准" + "Approved": "所选项目已批准", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "批准成功", "SuccessfullyDeleted": "删除请求成功", @@ -295,6 +307,7 @@ }, "MediaDetails": { "Denied": "已拒绝", + "Denied4K": "拒绝4K", "Trailers": "预告片", "RecommendationsTitle": "推荐", "SimilarTitle": "相似", @@ -363,12 +376,14 @@ "RequestDate": "请求日期:", "DeniedReason": "被拒绝原因:", "ReProcessRequest": "重新处理请求", + "ReProcessRequest4K": "重新处理4K请求", "Music": { "Type": "类型:", "Country": "国家:", "StartDate": "开始日期:", "EndDate": "结束日期:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "热门", diff --git a/tests/cypress/tests/requests/requests.spec.ts b/tests/cypress/tests/requests/requests.spec.ts index fc1a7489c..c161d0645 100644 --- a/tests/cypress/tests/requests/requests.spec.ts +++ b/tests/cypress/tests/requests/requests.spec.ts @@ -9,22 +9,27 @@ describe("Requests Tests", () => { cy.intercept("token").as("login"); cy.login(); - cy.requestAllTv(60735); // The Flash + const dbID = 60735; // The Flash + cy.requestAllTv(dbID); Page.visit(); Page.tvTab.click(); - const row = Page.tv.getGridRow(60735); + cy.waitUntil(() => { + const row = Page.tv.getGridRow(dbID); + return row.detailsButton.should("be.visible"); + }); + const row = Page.tv.getGridRow(dbID); row.detailsButton.click(); - cy.location("pathname").should("contains", "/details/tv/60735"); + cy.location("pathname").should("contains", "/details/tv/" + dbID); TvPage.title.contains("The Flash"); }); it("Deleting TV requests, removes from grid", () => { cy.intercept("POST", "request/tv").as("tvRequest"); cy.intercept("token").as("login"); - cy.intercept('DELETE', 'Request/tv/child/60735').as('deleteRequest'); + cy.intercept('DELETE','api/v1/Request/tv/child/60735').as('deleteRequest'); cy.login(); // cy.wait('@login'); diff --git a/version.json b/version.json index ed926cdfb..674e605d4 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.10.2" + "version": "4.16.10" } \ No newline at end of file
"); sb.Append(""); sb.Append(""); - await ProcessAlbums(albums, sb); + await ProcessAlbums(albums); sb.Append(""); sb.Append("
"); sb.Append("
{{ 'Requests.RequestDate' | translate}} {{element.requestedDate | amLocal | amUserLocale | amDateFormat: 'LL'}} {{getRequestDate(element) | amLocal | amUserLocale | amDateFormat: 'LL'}} {{element.status |translateStatus }} {{ 'Requests.Has4KRequest' | translate}} + + + {{ 'Requests.RequestStatus' | translate}}