diff --git a/.github/workflows/chromatic.yml b/.github/workflows/chromatic.yml
new file mode 100644
index 000000000..07f8a1a2b
--- /dev/null
+++ b/.github/workflows/chromatic.yml
@@ -0,0 +1,47 @@
+name: 'Chromatic'
+
+# Event for the workflow
+on:
+ push:
+ workflow_dispatch:
+
+# List of jobs
+jobs:
+ storybook-build:
+ # Operating System
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+
+ - name: NodeModules Cache
+ uses: actions/cache@v2
+ with:
+ path: '**/node_modules'
+ key: node_modules-${{ hashFiles('**/yarn.lock') }}
+
+ - name: Install dependencies
+ working-directory: ./src/Ombi/ClientApp
+ run: yarn
+
+ - name: Publish to Chromatic
+ if: github.ref != 'refs/heads/master'
+ uses: chromaui/action@v1
+ with:
+ projectToken: 7c47e1a1a4bd
+ exitZeroOnChanges: true
+ workingDir: ./src/Ombi/ClientApp
+ buildScriptName: storybookbuild
+ exitOnceUploaded: true
+
+ - name: Publish to Chromatic and auto accept changes
+ if: github.ref == 'refs/heads/develop'
+ uses: chromaui/action@v1
+ with:
+ projectToken: 7c47e1a1a4bd
+ autoAcceptChanges: true # 👈 Option to accept all changes
+ workingDir: ./src/Ombi/ClientApp
+ buildScriptName: storybookbuild
+ exitOnceUploaded: true
diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml
index 2e382eee3..2dc51179e 100644
--- a/.github/workflows/cypress.yml
+++ b/.github/workflows/cypress.yml
@@ -34,15 +34,29 @@ jobs:
- name: Install Frontend Deps
run: yarn --cwd ./src/Ombi/ClientApp install
- - name: Install Automation Deps
- run: yarn --cwd ./tests install
-
- - name: Start Backend
- run: |
- nohup dotnet run --project ./src/Ombi -- --host http://*:3577 &
- - name: Start Frontend
- run: |
- nohup yarn --cwd ./src/Ombi/ClientApp start &
+ - name: Build Frontend
+ run: yarn --cwd ./src/Ombi/ClientApp build
+
+ - name: Build Docker Image
+ run: docker build -t ombi src/
+
+ - name: Run Docker Image
+ run: nohup docker run --rm -p 5000:5000 ombi &
+
+ - name: Sleep for server to start
+ run: sleep 20
+
+ # - name: Start Frontend
+ # run: |
+ # nohup yarn --cwd ./src/Ombi/ClientApp start &
+
+ # - name: Install Automation Deps
+ # run: yarn --cwd ./tests install
+
+ # - name: Start Backend
+ # run: |
+ # nohup dotnet run --project ./src/Ombi -- --host http://*:3577 &
+
- name: Cypress Tests
uses: cypress-io/github-action@v2.8.2
with:
@@ -50,9 +64,9 @@ jobs:
browser: chrome
headless: true
working-directory: tests
- wait-on: http://localhost:3577/
- # 7 minutes
- wait-on-timeout: 420
+ wait-on: http://localhost:5000/
+ # 10 minutes
+ wait-on-timeout: 600
env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml
index 7c724a62a..402c5ffd0 100644
--- a/.github/workflows/label.yml
+++ b/.github/workflows/label.yml
@@ -8,6 +8,8 @@
name: Labeler
on: [pull_request]
+permissions: write-all
+
jobs:
label:
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index 961871f8a..7465635cc 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -5,6 +5,11 @@ on:
types: [opened, synchronize, reopened]
workflow_dispatch:
+permissions:
+ pull-requests: write
+ issues: write
+ repository-projects: write
+
jobs:
build-ui:
runs-on: ubuntu-latest
@@ -28,6 +33,7 @@ jobs:
unit-test:
runs-on: ubuntu-latest
+
steps:
- uses: actions/checkout@v2
- uses: actions/setup-dotnet@v1
@@ -45,7 +51,7 @@ jobs:
- name: Run Unit Tests
run: |
cd src
- dotnet test --logger trx --results-directory "TestResults"
+ dotnet test --configuration "Release" --logger "trx;LogFileName=test-results.trx"
analysis:
runs-on: ubuntu-latest
diff --git a/.gitignore b/.gitignore
index 845eda385..cae15017a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -251,3 +251,4 @@ _Pvt_Extensions
/src/Ombi/databases.json
/src/Ombi/healthchecksdb
/src/Ombi/ClientApp/package-lock.json
+/src/Ombi.Core/Properties/launchSettings.json
diff --git a/.mergify.yml b/.mergify.yml
new file mode 100644
index 000000000..fac2166e3
--- /dev/null
+++ b/.mergify.yml
@@ -0,0 +1,7 @@
+pull_request_rules:
+ - name: Automatic merge on approval
+ conditions:
+ - "#approved-reviews-by>=1"
+ actions:
+ merge:
+ method: merge
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2915d98bb..cce336ad8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,360 +1,363 @@
-## [4.16.12](https://github.com/Ombi-app/Ombi/compare/v4.16.11...v4.16.12) (2022-04-19)
-
-
-
-## [4.16.11](https://github.com/Ombi-app/Ombi/compare/v4.16.10...v4.16.11) (2022-04-14)
+## [4.22.4](https://github.com/Ombi-app/Ombi/compare/v4.22.3...v4.22.4) (2022-08-04)
### Bug Fixes
-* Set the default job for the watchlist import to hourly instead of daily ([75906af](https://github.com/Ombi-app/Ombi/commit/75906af0adee3e3c68d825c3aaa8f7b918461b1f))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([0e8a64b](https://github.com/Ombi-app/Ombi/commit/0e8a64b8ca00d210fbe843ac2c3f6af218d80cbc))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([7b0ad61](https://github.com/Ombi-app/Ombi/commit/7b0ad61bfcff3986b33180dc64022cba7ea8eefb))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([4fc2c1f](https://github.com/Ombi-app/Ombi/commit/4fc2c1f24534085a783a3d5791f5533b68272153))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([76ab733](https://github.com/Ombi-app/Ombi/commit/76ab733b91791e4d93d184f3c7d0779c6a388695))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([06e4cef](https://github.com/Ombi-app/Ombi/commit/06e4cefa7b4e55b860da9a64f461f6ec8fa17367))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([c12d89d](https://github.com/Ombi-app/Ombi/commit/c12d89d6781a337520977ad285f8d08c93f434dd))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([bc0c2f6](https://github.com/Ombi-app/Ombi/commit/bc0c2f622e34fb5a2711039d9ed7aad34f982b15))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([e4b00e6](https://github.com/Ombi-app/Ombi/commit/e4b00e6b3468bd9389eeb02fc6ad7daf27abc3b3))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([d1998d3](https://github.com/Ombi-app/Ombi/commit/d1998d326f999a38586d0a351a20c5448df95842))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([bee4ccb](https://github.com/Ombi-app/Ombi/commit/bee4ccb804594e7385b1fbdc9fe2ef5c42e0d21f))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([80233ed](https://github.com/Ombi-app/Ombi/commit/80233ed560cc976e83570d0655c3472f20171fb3))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([8a78adc](https://github.com/Ombi-app/Ombi/commit/8a78adc9bb62f277f2b213dcb3847ed6d0089fcb))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([d04c60a](https://github.com/Ombi-app/Ombi/commit/d04c60aa5909b47ba6bffa6f66b03079cbd43521))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([92a785e](https://github.com/Ombi-app/Ombi/commit/92a785e736fa4b72a45270da2d0f4661df433078))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([634982d](https://github.com/Ombi-app/Ombi/commit/634982df2661cefab5ea9f5163fe04a005cc0171))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([b404baa](https://github.com/Ombi-app/Ombi/commit/b404baad6d0aeaa1561701e0db8db4e78613a364))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([d14f11e](https://github.com/Ombi-app/Ombi/commit/d14f11e0eb20ab0a68e765ee77968b3b3e54e995))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([7cf64f9](https://github.com/Ombi-app/Ombi/commit/7cf64f909d78908edaabeffb8a39a7d02e73fe7e))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([0c9e1ec](https://github.com/Ombi-app/Ombi/commit/0c9e1ec090827080cc8f7393e5e91456ff37d691))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([3b0b730](https://github.com/Ombi-app/Ombi/commit/3b0b730cb02efe24f6d4026e5fdb20d37e495119))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([6ed1a03](https://github.com/Ombi-app/Ombi/commit/6ed1a03b7ff4077f09ea9e13394b18b0d138f4c3))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([2941acd](https://github.com/Ombi-app/Ombi/commit/2941acd3b2ec74a5e6aeea275ab5a39d2653f37f))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([c075a1a](https://github.com/Ombi-app/Ombi/commit/c075a1a66784d975eaf60f2dfbbcbe048f2f63d7))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([76bd81c](https://github.com/Ombi-app/Ombi/commit/76bd81c3ca55a98c6ec944a838dc01294a6193a6))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([0d38275](https://github.com/Ombi-app/Ombi/commit/0d3827507e002bcf58f673e97ffcc3bd25dcf337))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([5c99601](https://github.com/Ombi-app/Ombi/commit/5c99601b07aec1a65d0186a4c4327440811e64c6))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([01546a0](https://github.com/Ombi-app/Ombi/commit/01546a0f7f86379528b486463246ef9bdfb9033e))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([d7fea78](https://github.com/Ombi-app/Ombi/commit/d7fea7843aaaab7ddff8dc31ca6d2a9117471dcc))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([1a6b95d](https://github.com/Ombi-app/Ombi/commit/1a6b95d45c220310213b8d811272a63f0f6ff42b))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([fa10174](https://github.com/Ombi-app/Ombi/commit/fa1017422c4efd4b0897871bd3c671151774d7c3))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([0c31e62](https://github.com/Ombi-app/Ombi/commit/0c31e628df376aac6d56ae67c7c705a9a4a7c080))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([6399643](https://github.com/Ombi-app/Ombi/commit/63996437a02fe10ffae6822ffa15369bec0a6b36))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([5826e2d](https://github.com/Ombi-app/Ombi/commit/5826e2d9a1c3f1210a87fa270dc0c81bac32944a))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([d434514](https://github.com/Ombi-app/Ombi/commit/d43451405be489254d7cdc7755d5f516a1e495a5))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([0b9596d](https://github.com/Ombi-app/Ombi/commit/0b9596d807178f5e071113ec0347868ec7f0960b))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([8c4c0b2](https://github.com/Ombi-app/Ombi/commit/8c4c0b262978c1303767af360d802c4b4c2b4d24))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([289ab77](https://github.com/Ombi-app/Ombi/commit/289ab77b0e04aae235b6f6cebc86e0a8d1f0cf2b))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([30e3417](https://github.com/Ombi-app/Ombi/commit/30e3417285a4eed18d429d7776f0e74096e834c0))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([6c0a5da](https://github.com/Ombi-app/Ombi/commit/6c0a5dadd4b8f37760252eb0fe7f88908f55506d))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([d5bf969](https://github.com/Ombi-app/Ombi/commit/d5bf9692ce1fc0ccfe7beca6dd200c78be177bdc))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([8a9e7ea](https://github.com/Ombi-app/Ombi/commit/8a9e7ea588aefbcd73ed82625887e3614e1703ea))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([01047a3](https://github.com/Ombi-app/Ombi/commit/01047a3fd67153f3ff16f860d2c7b50213e8d9b2))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([698a23f](https://github.com/Ombi-app/Ombi/commit/698a23fb83f323cdd1dd57cb49803079d44214a7))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([24eb842](https://github.com/Ombi-app/Ombi/commit/24eb842fc4424f7bcc3ec2949d7f5472492e96f6))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([ac8b16a](https://github.com/Ombi-app/Ombi/commit/ac8b16a3051ad71dbd54a8973c7dd847b564a515))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([f428ce6](https://github.com/Ombi-app/Ombi/commit/f428ce6a700c081437703839bc84d2f2b1138bcc))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([94b16df](https://github.com/Ombi-app/Ombi/commit/94b16dfe09bf1d2cd6286777d74eb5d4496abbbb))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([4881775](https://github.com/Ombi-app/Ombi/commit/4881775eda69a8f136ce0d8fbbf970e3d0406dc9))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([8297db9](https://github.com/Ombi-app/Ombi/commit/8297db91e85da308bde6fb09ad78347dee063630))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([d1152ab](https://github.com/Ombi-app/Ombi/commit/d1152ab7674243daa528c524c0cdc87d81ad49c9))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([eb2788b](https://github.com/Ombi-app/Ombi/commit/eb2788b761b55c487a59a049427ca08f6c10e836))
-* **translations:** 🌐 New translations from Crowdin [skip ci] ([21a794c](https://github.com/Ombi-app/Ombi/commit/21a794cbc0a5fa735ca0347c8f7f1ac04a487fbc))
+* :bug: Fixed missing externals ([#4712](https://github.com/Ombi-app/Ombi/issues/4712)) ([fcc1eaa](https://github.com/Ombi-app/Ombi/commit/fcc1eaaa377683dcdc81d62a2a688fb0c4490c7b))
+* fixed trakt image not loading when base url present ([#4711](https://github.com/Ombi-app/Ombi/issues/4711)) ([f102dcf](https://github.com/Ombi-app/Ombi/commit/f102dcf751c2eb62ebfe30f9f8e4b2ad863c3b0d))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([#4713](https://github.com/Ombi-app/Ombi/issues/4713)) ([ff142b0](https://github.com/Ombi-app/Ombi/commit/ff142b09abbb2f9540387284222552e6e12639fe))
-## [4.10.2](https://github.com/Ombi-app/Ombi/compare/v4.10.1...v4.10.2) (2022-01-22)
+## [4.22.3](https://github.com/Ombi-app/Ombi/compare/v4.22.2...v4.22.3) (2022-07-28)
+### Bug Fixes
-## [4.16.10](https://github.com/Ombi-app/Ombi/compare/v4.16.9...v4.16.10) (2022-04-13)
+* Override Sonarr V3 Profiles endpoint ([#4678](https://github.com/Ombi-app/Ombi/issues/4678)) ([875da95](https://github.com/Ombi-app/Ombi/commit/875da959f353119b05138d68ee6d32a49e14b91e))
-## [4.16.9](https://github.com/Ombi-app/Ombi/compare/v4.16.8...v4.16.9) (2022-04-13)
+## [4.22.2](https://github.com/Ombi-app/Ombi/compare/v4.22.1...v4.22.2) (2022-07-25)
### Bug Fixes
-* **plex-watchlist:** Only request the latest season when importing from the watchlist ([77a47ff](https://github.com/Ombi-app/Ombi/commit/77a47ff157c6c5feafe3f2a29a3fcba8df4fdfef))
+* fixed an issue where I broke images for some users ([81ddc85](https://github.com/Ombi-app/Ombi/commit/81ddc8553b9094c3f6843b036daebb2eb9262e00))
-## [4.16.8](https://github.com/Ombi-app/Ombi/compare/v4.16.7...v4.16.8) (2022-04-13)
+## [4.22.1](https://github.com/Ombi-app/Ombi/compare/v4.22.0...v4.22.1) (2022-07-25)
### 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))
+* **discover:** :bug: Created new Image component to handle 429's from TMDB ([#4698](https://github.com/Ombi-app/Ombi/issues/4698)) and fixed [#4635](https://github.com/Ombi-app/Ombi/issues/4635) ([#4699](https://github.com/Ombi-app/Ombi/issues/4699)) ([f22d3da](https://github.com/Ombi-app/Ombi/commit/f22d3da765799365455b919027f7563e52b347c3))
-## [4.16.7](https://github.com/Ombi-app/Ombi/compare/v4.16.6...v4.16.7) (2022-04-12)
+# [4.22.0](https://github.com/Ombi-app/Ombi/compare/v4.21.2...v4.22.0) (2022-07-22)
+### Features
-## [4.16.6](https://github.com/Ombi-app/Ombi/compare/v4.16.5...v4.16.6) (2022-04-11)
+* **discover:** ✨ Added infinite scroll on advanced search results ([898bc89](https://github.com/Ombi-app/Ombi/commit/898bc89fa78245c1f3de9481f6c724f087a16e39))
-## [4.16.5](https://github.com/Ombi-app/Ombi/compare/v4.16.4...v4.16.5) (2022-04-08)
+## [4.21.2](https://github.com/Ombi-app/Ombi/compare/v4.21.1...v4.21.2) (2022-07-22)
### Bug Fixes
-* **watchlist:** actually fixed it this time... ([d962a32](https://github.com/Ombi-app/Ombi/commit/d962a3211eca29520662ddce962676e3aea17ec5))
+* Landing and Login page improvements ([#4690](https://github.com/Ombi-app/Ombi/issues/4690)) ([6d423b5](https://github.com/Ombi-app/Ombi/commit/6d423b5447c52c5e59d8d2bd92a23b47468eb736))
-## [4.16.4](https://github.com/Ombi-app/Ombi/compare/v4.16.3...v4.16.4) (2022-04-08)
+## [4.21.1](https://github.com/Ombi-app/Ombi/compare/v4.21.0...v4.21.1) (2022-07-11)
+### Bug Fixes
-## [4.16.3](https://github.com/Ombi-app/Ombi/compare/v4.16.2...v4.16.3) (2022-04-08)
+* **images:** Retry images with a backoff when we get a Too Many requests from TheMovieDb [#4685](https://github.com/Ombi-app/Ombi/issues/4685) ([3f1f35d](https://github.com/Ombi-app/Ombi/commit/3f1f35df3164db6739691cdda8f925c296239791))
-### 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.21.0](https://github.com/Ombi-app/Ombi/compare/v4.20.4...v4.21.0) (2022-06-22)
+### Features
-## [4.16.2](https://github.com/Ombi-app/Ombi/compare/v4.16.1...v4.16.2) (2022-04-07)
+* Upgrade to Angular14 ([#4668](https://github.com/Ombi-app/Ombi/issues/4668)) ([b9d55a4](https://github.com/Ombi-app/Ombi/commit/b9d55a469b412558cbf67c1e25db7fdda5964cd8))
-### Bug Fixes
+### Performance Improvements
-* **wizard:** Fixed an issue when using Plex OAuth it could fail setting up ([b743cf4](https://github.com/Ombi-app/Ombi/commit/b743cf4fafa7341ad1b163276f006d7ab0e9dcff))
+* stop populating obsolete subscribe fields ([#4625](https://github.com/Ombi-app/Ombi/issues/4625)) ([9a73463](https://github.com/Ombi-app/Ombi/commit/9a734637665f671b17c2bb440d93b35a891c142b))
-## [4.16.1](https://github.com/Ombi-app/Ombi/compare/v4.16.0...v4.16.1) (2022-04-07)
+## [4.20.4](https://github.com/Ombi-app/Ombi/compare/v4.20.3...v4.20.4) (2022-06-15)
+### Bug Fixes
-# [4.16.0](https://github.com/Ombi-app/Ombi/compare/v4.15.6...v4.16.0) (2022-04-07)
+* fixed build ([f877921](https://github.com/Ombi-app/Ombi/commit/f8779219146051ea74f8b6408658ff7975afb88b))
-## [4.15.6](https://github.com/Ombi-app/Ombi/compare/v4.15.5...v4.15.6) (2022-04-07)
+## [4.20.3](https://github.com/Ombi-app/Ombi/compare/v4.20.2...v4.20.3) (2022-06-05)
### 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))
+* **plex:** 🐛 Fixed an issue with the Plex Sync ([ab1a11a](https://github.com/Ombi-app/Ombi/commit/ab1a11af78efbe9d37bd55aa80a640796c138a98))
-## [4.15.5](https://github.com/Ombi-app/Ombi/compare/v4.15.4...v4.15.5) (2022-04-06)
+## [4.20.2](https://github.com/Ombi-app/Ombi/compare/v4.20.1...v4.20.2) (2022-06-03)
+### Bug Fixes
-## [4.15.4](https://github.com/Ombi-app/Ombi/compare/v4.15.3...v4.15.4) (2022-03-29)
+* :bug: Fixed the Request on Behalf of having blanks ([#4667](https://github.com/Ombi-app/Ombi/issues/4667)) ([7dd9b1c](https://github.com/Ombi-app/Ombi/commit/7dd9b1cac07f571dd35b362544e4fe0226c4b817))
-## [4.15.3](https://github.com/Ombi-app/Ombi/compare/v4.15.2...v4.15.3) (2022-03-24)
+## [4.20.1](https://github.com/Ombi-app/Ombi/compare/v4.20.0...v4.20.1) (2022-05-27)
+### Bug Fixes
-## [4.15.2](https://github.com/Ombi-app/Ombi/compare/v4.15.1...v4.15.2) (2022-03-23)
+* added media type tag to media type text ([#4638](https://github.com/Ombi-app/Ombi/issues/4638)) ([fe501d3](https://github.com/Ombi-app/Ombi/commit/fe501d34a0c36ac9f000b107eca49dbc6694d006))
+* **API:** Fix pagination in some edge cases ([#4649](https://github.com/Ombi-app/Ombi/issues/4649)) ([a70bf8f](https://github.com/Ombi-app/Ombi/commit/a70bf8f46c76d74c9dfdf908c53bd9955ca0a35d))
+* **discover:** Carousel touch not working when scrolling page and recommendations and similar movie navigation ([#4633](https://github.com/Ombi-app/Ombi/issues/4633)) ([d5ef1d5](https://github.com/Ombi-app/Ombi/commit/d5ef1d53e5f77d19dba8b8059c80b538a3e14f2a))
+* Improve Swagger documentation ([#4652](https://github.com/Ombi-app/Ombi/issues/4652)) ([181892b](https://github.com/Ombi-app/Ombi/commit/181892bcfe88e6d76febf49ef57745d04552d08e))
+* Missing Poster broken link fix ([#4637](https://github.com/Ombi-app/Ombi/issues/4637)) ([4070f0d](https://github.com/Ombi-app/Ombi/commit/4070f0d093b1c92487a1c80cabad8283a9650f51))
+* **sickrage:** Fixed issue with incorrect handling of SiCKRAGE episode results returned during episode status changes, now expects array of objects from data path if present ([#4648](https://github.com/Ombi-app/Ombi/issues/4648)) ([6d16442](https://github.com/Ombi-app/Ombi/commit/6d16442d4d714920367df065a3ced42b729f4233))
+* **sync:** Emby+Jellyfin - sync multi-episode files of 3+ episodes ([bd8fd89](https://github.com/Ombi-app/Ombi/commit/bd8fd890554c9d85d6da4d2cee813e82ce698e52))
-### 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.20.0](https://github.com/Ombi-app/Ombi/compare/v4.19.1...v4.20.0) (2022-04-28)
+### Features
-## [4.15.1](https://github.com/Ombi-app/Ombi/compare/v4.15.0...v4.15.1) (2022-03-18)
+* **discover:** Show more relevant shows in upcoming TV ([8357819](https://github.com/Ombi-app/Ombi/commit/8357819b53b8c675c0b246d7006b5a778bdba33f))
-### 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.19.1](https://github.com/Ombi-app/Ombi/compare/v4.19.0...v4.19.1) (2022-04-27)
-# [4.15.0](https://github.com/Ombi-app/Ombi/compare/v4.14.4...v4.15.0) (2022-03-17)
+# [4.19.0](https://github.com/Ombi-app/Ombi/compare/v4.18.0...v4.19.0) (2022-04-27)
-### Bug Fixes
+### Features
-* **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)
+* **sync:** Detect reidentified movies in Emby and Jellyfin ([5938077](https://github.com/Ombi-app/Ombi/commit/5938077d82a5357f79c07b218b3986557a5816e8))
+* **sync:** Detect reidentified series in Emby and Jellyfin ([9096e91](https://github.com/Ombi-app/Ombi/commit/9096e91d55d268819bce22831f8a8b27f2a1776b))
-## [4.14.4](https://github.com/Ombi-app/Ombi/compare/v4.14.3...v4.14.4) (2022-03-10)
+# [4.18.0](https://github.com/Ombi-app/Ombi/compare/v4.17.0...v4.18.0) (2022-04-26)
### 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))
+* **discover:** Fix cache mix up ([03d9422](https://github.com/Ombi-app/Ombi/commit/03d94220c7eaafb50c6c80a6ed1150794b873ac3))
+* **discover:** Fix new trending feature detection ([6794b88](https://github.com/Ombi-app/Ombi/commit/6794b887f6544fb41528bdd9728b7824b65e47ee))
+* **settings:** Allow toggling features when there are more than one ([a373359](https://github.com/Ombi-app/Ombi/commit/a373359ae8e6bad42b558a6e01a8ff2840d3bbaa))
+### Features
-## [4.14.3](https://github.com/Ombi-app/Ombi/compare/v4.14.2...v4.14.3) (2022-03-06)
+* **discover:** Add new trending source experimental feature ([1a0823c](https://github.com/Ombi-app/Ombi/commit/1a0823ca80559417c67323aaeaa1ef5243e98031))
+* **discover:** Default trending source to new logic ([4f12939](https://github.com/Ombi-app/Ombi/commit/4f12939e22020a67a5ee75e2907923faea136e8d))
-### 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.17.0](https://github.com/Ombi-app/Ombi/compare/v4.16.17...v4.17.0) (2022-04-25)
+### Features
-## [4.14.2](https://github.com/Ombi-app/Ombi/compare/v4.14.1...v4.14.2) (2022-03-05)
+* **discover:** Add original language filter ([ef7ec86](https://github.com/Ombi-app/Ombi/commit/ef7ec861d8aede2a4817752c990617f583805391))
-### 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.16.17](https://github.com/Ombi-app/Ombi/compare/v4.16.16...v4.16.17) (2022-04-25)
-## [4.14.1](https://github.com/Ombi-app/Ombi/compare/v4.14.0...v4.14.1) (2022-03-03)
+## [4.16.16](https://github.com/Ombi-app/Ombi/compare/v4.16.15...v4.16.16) (2022-04-25)
+### Bug Fixes
-# [4.14.0](https://github.com/Ombi-app/Ombi/compare/v4.13.2...v4.14.0) (2022-03-02)
+* **4616:** :bug: fixed mandatory fields ([d8f2260](https://github.com/Ombi-app/Ombi/commit/d8f2260c7ae3ed48386743b7adbd06e284487034))
-## [4.13.2](https://github.com/Ombi-app/Ombi/compare/v4.13.1...v4.13.2) (2022-03-01)
+## [4.16.15](https://github.com/Ombi-app/Ombi/compare/v4.16.14...v4.16.15) (2022-04-24)
-### 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.16.14](https://github.com/Ombi-app/Ombi/compare/v4.16.13...v4.16.14) (2022-04-19)
-## [4.13.1](https://github.com/Ombi-app/Ombi/compare/v4.13.0...v4.13.1) (2022-03-01)
+## [4.16.13](https://github.com/Ombi-app/Ombi/compare/v4.16.12...v4.16.13) (2022-04-19)
-### 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.16.12](https://github.com/Ombi-app/Ombi/compare/v4.16.11...v4.16.12) (2022-04-19)
-# [4.13.0](https://github.com/Ombi-app/Ombi/compare/v4.12.7...v4.13.0) (2022-02-25)
+## [4.16.11](https://github.com/Ombi-app/Ombi/compare/v4.16.10...v4.16.11) (2022-04-14)
### 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))
+* Set the default job for the watchlist import to hourly instead of daily ([75906af](https://github.com/Ombi-app/Ombi/commit/75906af0adee3e3c68d825c3aaa8f7b918461b1f))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([0e8a64b](https://github.com/Ombi-app/Ombi/commit/0e8a64b8ca00d210fbe843ac2c3f6af218d80cbc))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([7b0ad61](https://github.com/Ombi-app/Ombi/commit/7b0ad61bfcff3986b33180dc64022cba7ea8eefb))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([4fc2c1f](https://github.com/Ombi-app/Ombi/commit/4fc2c1f24534085a783a3d5791f5533b68272153))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([76ab733](https://github.com/Ombi-app/Ombi/commit/76ab733b91791e4d93d184f3c7d0779c6a388695))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([06e4cef](https://github.com/Ombi-app/Ombi/commit/06e4cefa7b4e55b860da9a64f461f6ec8fa17367))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([c12d89d](https://github.com/Ombi-app/Ombi/commit/c12d89d6781a337520977ad285f8d08c93f434dd))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([bc0c2f6](https://github.com/Ombi-app/Ombi/commit/bc0c2f622e34fb5a2711039d9ed7aad34f982b15))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([e4b00e6](https://github.com/Ombi-app/Ombi/commit/e4b00e6b3468bd9389eeb02fc6ad7daf27abc3b3))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([d1998d3](https://github.com/Ombi-app/Ombi/commit/d1998d326f999a38586d0a351a20c5448df95842))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([bee4ccb](https://github.com/Ombi-app/Ombi/commit/bee4ccb804594e7385b1fbdc9fe2ef5c42e0d21f))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([80233ed](https://github.com/Ombi-app/Ombi/commit/80233ed560cc976e83570d0655c3472f20171fb3))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([8a78adc](https://github.com/Ombi-app/Ombi/commit/8a78adc9bb62f277f2b213dcb3847ed6d0089fcb))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([d04c60a](https://github.com/Ombi-app/Ombi/commit/d04c60aa5909b47ba6bffa6f66b03079cbd43521))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([92a785e](https://github.com/Ombi-app/Ombi/commit/92a785e736fa4b72a45270da2d0f4661df433078))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([634982d](https://github.com/Ombi-app/Ombi/commit/634982df2661cefab5ea9f5163fe04a005cc0171))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([b404baa](https://github.com/Ombi-app/Ombi/commit/b404baad6d0aeaa1561701e0db8db4e78613a364))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([d14f11e](https://github.com/Ombi-app/Ombi/commit/d14f11e0eb20ab0a68e765ee77968b3b3e54e995))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([7cf64f9](https://github.com/Ombi-app/Ombi/commit/7cf64f909d78908edaabeffb8a39a7d02e73fe7e))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([0c9e1ec](https://github.com/Ombi-app/Ombi/commit/0c9e1ec090827080cc8f7393e5e91456ff37d691))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([3b0b730](https://github.com/Ombi-app/Ombi/commit/3b0b730cb02efe24f6d4026e5fdb20d37e495119))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([6ed1a03](https://github.com/Ombi-app/Ombi/commit/6ed1a03b7ff4077f09ea9e13394b18b0d138f4c3))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([2941acd](https://github.com/Ombi-app/Ombi/commit/2941acd3b2ec74a5e6aeea275ab5a39d2653f37f))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([c075a1a](https://github.com/Ombi-app/Ombi/commit/c075a1a66784d975eaf60f2dfbbcbe048f2f63d7))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([76bd81c](https://github.com/Ombi-app/Ombi/commit/76bd81c3ca55a98c6ec944a838dc01294a6193a6))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([0d38275](https://github.com/Ombi-app/Ombi/commit/0d3827507e002bcf58f673e97ffcc3bd25dcf337))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([5c99601](https://github.com/Ombi-app/Ombi/commit/5c99601b07aec1a65d0186a4c4327440811e64c6))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([01546a0](https://github.com/Ombi-app/Ombi/commit/01546a0f7f86379528b486463246ef9bdfb9033e))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([d7fea78](https://github.com/Ombi-app/Ombi/commit/d7fea7843aaaab7ddff8dc31ca6d2a9117471dcc))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([1a6b95d](https://github.com/Ombi-app/Ombi/commit/1a6b95d45c220310213b8d811272a63f0f6ff42b))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([fa10174](https://github.com/Ombi-app/Ombi/commit/fa1017422c4efd4b0897871bd3c671151774d7c3))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([0c31e62](https://github.com/Ombi-app/Ombi/commit/0c31e628df376aac6d56ae67c7c705a9a4a7c080))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([6399643](https://github.com/Ombi-app/Ombi/commit/63996437a02fe10ffae6822ffa15369bec0a6b36))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([5826e2d](https://github.com/Ombi-app/Ombi/commit/5826e2d9a1c3f1210a87fa270dc0c81bac32944a))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([d434514](https://github.com/Ombi-app/Ombi/commit/d43451405be489254d7cdc7755d5f516a1e495a5))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([0b9596d](https://github.com/Ombi-app/Ombi/commit/0b9596d807178f5e071113ec0347868ec7f0960b))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([8c4c0b2](https://github.com/Ombi-app/Ombi/commit/8c4c0b262978c1303767af360d802c4b4c2b4d24))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([289ab77](https://github.com/Ombi-app/Ombi/commit/289ab77b0e04aae235b6f6cebc86e0a8d1f0cf2b))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([30e3417](https://github.com/Ombi-app/Ombi/commit/30e3417285a4eed18d429d7776f0e74096e834c0))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([6c0a5da](https://github.com/Ombi-app/Ombi/commit/6c0a5dadd4b8f37760252eb0fe7f88908f55506d))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([d5bf969](https://github.com/Ombi-app/Ombi/commit/d5bf9692ce1fc0ccfe7beca6dd200c78be177bdc))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([8a9e7ea](https://github.com/Ombi-app/Ombi/commit/8a9e7ea588aefbcd73ed82625887e3614e1703ea))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([01047a3](https://github.com/Ombi-app/Ombi/commit/01047a3fd67153f3ff16f860d2c7b50213e8d9b2))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([698a23f](https://github.com/Ombi-app/Ombi/commit/698a23fb83f323cdd1dd57cb49803079d44214a7))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([24eb842](https://github.com/Ombi-app/Ombi/commit/24eb842fc4424f7bcc3ec2949d7f5472492e96f6))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([ac8b16a](https://github.com/Ombi-app/Ombi/commit/ac8b16a3051ad71dbd54a8973c7dd847b564a515))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([f428ce6](https://github.com/Ombi-app/Ombi/commit/f428ce6a700c081437703839bc84d2f2b1138bcc))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([94b16df](https://github.com/Ombi-app/Ombi/commit/94b16dfe09bf1d2cd6286777d74eb5d4496abbbb))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([4881775](https://github.com/Ombi-app/Ombi/commit/4881775eda69a8f136ce0d8fbbf970e3d0406dc9))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([8297db9](https://github.com/Ombi-app/Ombi/commit/8297db91e85da308bde6fb09ad78347dee063630))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([d1152ab](https://github.com/Ombi-app/Ombi/commit/d1152ab7674243daa528c524c0cdc87d81ad49c9))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([eb2788b](https://github.com/Ombi-app/Ombi/commit/eb2788b761b55c487a59a049427ca08f6c10e836))
+* **translations:** 🌐 New translations from Crowdin [skip ci] ([21a794c](https://github.com/Ombi-app/Ombi/commit/21a794cbc0a5fa735ca0347c8f7f1ac04a487fbc))
-### Features
-* **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.10.2](https://github.com/Ombi-app/Ombi/compare/v4.10.1...v4.10.2) (2022-01-22)
-## [4.12.7](https://github.com/Ombi-app/Ombi/compare/v4.12.6...v4.12.7) (2022-02-23)
+## [4.16.10](https://github.com/Ombi-app/Ombi/compare/v4.16.9...v4.16.10) (2022-04-13)
-## [4.12.6](https://github.com/Ombi-app/Ombi/compare/v4.12.5...v4.12.6) (2022-02-22)
+## [4.16.9](https://github.com/Ombi-app/Ombi/compare/v4.16.8...v4.16.9) (2022-04-13)
### Bug Fixes
-* **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))
+* **plex-watchlist:** Only request the latest season when importing from the watchlist ([77a47ff](https://github.com/Ombi-app/Ombi/commit/77a47ff157c6c5feafe3f2a29a3fcba8df4fdfef))
-## [4.12.5](https://github.com/Ombi-app/Ombi/compare/v4.12.4...v4.12.5) (2022-02-21)
+## [4.16.8](https://github.com/Ombi-app/Ombi/compare/v4.16.7...v4.16.8) (2022-04-13)
### Bug Fixes
-* **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))
+* **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.12.4](https://github.com/Ombi-app/Ombi/compare/v4.12.3...v4.12.4) (2022-02-17)
+## [4.16.7](https://github.com/Ombi-app/Ombi/compare/v4.16.6...v4.16.7) (2022-04-12)
-## [4.12.3](https://github.com/Ombi-app/Ombi/compare/v4.12.2...v4.12.3) (2022-02-16)
+## [4.16.6](https://github.com/Ombi-app/Ombi/compare/v4.16.5...v4.16.6) (2022-04-11)
-## [4.12.2](https://github.com/Ombi-app/Ombi/compare/v4.12.1...v4.12.2) (2022-02-16)
+## [4.16.5](https://github.com/Ombi-app/Ombi/compare/v4.16.4...v4.16.5) (2022-04-08)
### 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))
+* **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.12.1](https://github.com/Ombi-app/Ombi/compare/v4.12.0...v4.12.1) (2022-02-16)
+## [4.16.3](https://github.com/Ombi-app/Ombi/compare/v4.16.2...v4.16.3) (2022-04-08)
### 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)
+* **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.12.0](https://github.com/Ombi-app/Ombi/compare/v4.11.8...v4.12.0) (2022-02-14)
+## [4.16.2](https://github.com/Ombi-app/Ombi/compare/v4.16.1...v4.16.2) (2022-04-07)
-### Features
+### Bug Fixes
-* **radarr:** 4K Requests and Radarr 4K support ([ba88848](https://github.com/Ombi-app/Ombi/commit/ba88848866b0a9dedb1e79b55c4d81a0fd453843))
+* **wizard:** Fixed an issue when using Plex OAuth it could fail setting up ([b743cf4](https://github.com/Ombi-app/Ombi/commit/b743cf4fafa7341ad1b163276f006d7ab0e9dcff))
-## [4.11.8](https://github.com/Ombi-app/Ombi/compare/v4.11.7...v4.11.8) (2022-02-13)
+## [4.16.1](https://github.com/Ombi-app/Ombi/compare/v4.16.0...v4.16.1) (2022-04-07)
-### Bug Fixes
-* **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.16.0](https://github.com/Ombi-app/Ombi/compare/v4.15.6...v4.16.0) (2022-04-07)
-## [4.11.7](https://github.com/Ombi-app/Ombi/compare/v4.11.6...v4.11.7) (2022-02-12)
+## [4.15.6](https://github.com/Ombi-app/Ombi/compare/v4.15.5...v4.15.6) (2022-04-07)
### Bug Fixes
-* **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))
+* **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.11.6](https://github.com/Ombi-app/Ombi/compare/v4.11.5...v4.11.6) (2022-02-10)
-### Bug Fixes
+## [4.15.4](https://github.com/Ombi-app/Ombi/compare/v4.15.3...v4.15.4) (2022-03-29)
+
+
-* **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.15.3](https://github.com/Ombi-app/Ombi/compare/v4.15.2...v4.15.3) (2022-03-24)
-## [4.11.5](https://github.com/Ombi-app/Ombi/compare/v4.11.4...v4.11.5) (2022-02-05)
+## [4.15.2](https://github.com/Ombi-app/Ombi/compare/v4.15.1...v4.15.2) (2022-03-23)
### Bug Fixes
-* **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))
+* **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))
diff --git a/README.md b/README.md
index 32552817e..c8fde6e73 100644
--- a/README.md
+++ b/README.md
@@ -100,17 +100,17 @@ Here are some of the features Ombi has:
-
-
+
+
- Anojh Thayaparan
+ Sephrat
|
-
-
+
+
- Sephrat
+ Anojh Thayaparan
|
@@ -222,10 +222,10 @@ Here are some of the features Ombi has:
-
-
+
+
- Steffokeffo
+ Stefan
|
@@ -286,6 +286,13 @@ Here are some of the features Ombi has:
|
+
+
+
+
+ Dr3amer
+
+ |
@@ -320,15 +327,15 @@ Here are some of the features Ombi has:
Austin Jackson
- |
+
+
D34DC3N73R
- |
-
+
@@ -363,15 +370,15 @@ Here are some of the features Ombi has:
Jeffrey Peters
- |
+
+
Marius Schiffer
- |
-
+
@@ -406,15 +413,15 @@ Here are some of the features Ombi has:
Abe Kline
- |
+
+
Alexander Standke
- |
-
+
@@ -449,15 +456,15 @@ Here are some of the features Ombi has:
Chris Lees
- |
+
+
Christopher Demicoli
- |
-
+
@@ -492,15 +499,15 @@ Here are some of the features Ombi has:
Devin Buhl
- |
+
+
Eli
- |
-
+
@@ -515,6 +522,13 @@ Here are some of the features Ombi has:
Haries Ramdhani
|
+
+
+
+
+ Igor Borges
+
+ |
@@ -528,7 +542,8 @@ Here are some of the features Ombi has:
Jacob Pyke
- |
+
+
@@ -542,8 +557,7 @@ Here are some of the features Ombi has:
Joe Groocock
- |
-
+
@@ -571,7 +585,8 @@ Here are some of the features Ombi has:
Kris Klosterman
- |
+
+
@@ -585,8 +600,14 @@ Here are some of the features Ombi has:
Lightkeeper
- |
-
+
+
+
+
+
+ Lucane
+
+ |
@@ -594,13 +615,21 @@ Here are some of the features Ombi has:
Madeleine Schönemann
|
+
+
+
+
+ Marley
+
+ |
Matt
- |
+
+
@@ -628,8 +657,7 @@ Here are some of the features Ombi has:
Qiming Chen
- |
-
+
@@ -643,7 +671,8 @@ Here are some of the features Ombi has:
Rob Gökemeijer
- |
+
+
@@ -665,21 +694,28 @@ Here are some of the features Ombi has:
Shoghi
|
+
+
+
+
+ Teifun2
+
+ |
Thomas Van Tilburg
- |
-
+
Tim Trott
- |
+
+
@@ -714,15 +750,15 @@ Here are some of the features Ombi has:
Tim OBrien
- |
-
+
Blake Drumm
- |
+
+
@@ -744,6 +780,13 @@ Here are some of the features Ombi has:
Dorian ALKOUM
|
+
+
+
+
+ Echel0n
+
+ |
@@ -766,6 +809,13 @@ Here are some of the features Ombi has:
Patrick Weber
|
+
+
+
+
+ Mkgeeky
+
+ |
diff --git a/src/.dockerignore b/src/.dockerignore
new file mode 100644
index 000000000..252736d92
--- /dev/null
+++ b/src/.dockerignore
@@ -0,0 +1,285 @@
+**/bin/
+**/obj/
+**/.angular/
+**/node_modules/
+.gitignore
+.git/
+
+
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+project.fragment.lock.json
+artifacts/
+Properties/launchSettings.json
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+# NuGet v3's project.json files produces more ignoreable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush
+.cr/
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/
+tools/Cake.CoreCLR
+.vscode
+tools
+.dotnet
+Dockerfile
+
+# .env file contains default environment variables for docker
+.env
+.git/
\ No newline at end of file
diff --git a/src/Ombi.Api.Emby/EmbyApi.cs b/src/Ombi.Api.Emby/EmbyApi.cs
index a1791494d..e9e5f0fca 100644
--- a/src/Ombi.Api.Emby/EmbyApi.cs
+++ b/src/Ombi.Api.Emby/EmbyApi.cs
@@ -106,7 +106,7 @@ public async Task> GetCollection(string mediaId, st
request.AddQueryString("Fields", "ProviderIds,Overview");
- request.AddQueryString("IsVirtualItem", "False");
+ request.AddQueryString("IsMissing", "False");
return await Api.Request>(request);
}
@@ -180,7 +180,7 @@ private async Task> RecentlyAdded(string type, string ap
request.AddQueryString("ParentId", parentIdFilder);
}
- request.AddQueryString("IsVirtualItem", "False");
+ request.AddQueryString("IsMissing", "False");
AddHeaders(request, apiKey);
@@ -207,7 +207,7 @@ private async Task> GetAll(string type, string apiKey, s
request.AddQueryString("IncludeItemTypes", type);
request.AddQueryString("Fields", includeOverview ? "ProviderIds,Overview" : "ProviderIds");
- request.AddQueryString("IsVirtualItem", "False");
+ request.AddQueryString("IsMissing", "False");
AddHeaders(request, apiKey);
@@ -229,7 +229,7 @@ private async Task> GetAll(string type, string apiKey, s
request.AddQueryString("ParentId", parentIdFilder);
}
- request.AddQueryString("IsVirtualItem", "False");
+ request.AddQueryString("isMissing", "False");
AddHeaders(request, apiKey);
diff --git a/src/Ombi.Api.Jellyfin/JellyfinApi.cs b/src/Ombi.Api.Jellyfin/JellyfinApi.cs
index f6afb7912..0604cb984 100644
--- a/src/Ombi.Api.Jellyfin/JellyfinApi.cs
+++ b/src/Ombi.Api.Jellyfin/JellyfinApi.cs
@@ -82,7 +82,7 @@ public async Task> GetCollection(string med
request.AddQueryString("Fields", "ProviderIds,Overview");
- request.AddQueryString("IsVirtualItem", "False");
+ request.AddQueryString("isMissing", "False");
return await Api.Request>(request);
}
@@ -143,7 +143,7 @@ private async Task> GetAll(string type, string apiKe
request.AddQueryString("IncludeItemTypes", type);
request.AddQueryString("Fields", includeOverview ? "ProviderIds,Overview" : "ProviderIds");
- request.AddQueryString("IsVirtualItem", "False");
+ request.AddQueryString("isMissing", "False");
AddHeaders(request, apiKey);
@@ -165,7 +165,7 @@ private async Task> GetAll(string type, string apiKe
request.AddQueryString("ParentId", parentIdFilder);
}
- request.AddQueryString("IsVirtualItem", "False");
+ request.AddQueryString("isMissing", "False");
AddHeaders(request, apiKey);
diff --git a/src/Ombi.Api.Plex/Models/Metadata.cs b/src/Ombi.Api.Plex/Models/Metadata.cs
index 3481e9b57..97cab391b 100644
--- a/src/Ombi.Api.Plex/Models/Metadata.cs
+++ b/src/Ombi.Api.Plex/Models/Metadata.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using Newtonsoft.Json;
namespace Ombi.Api.Plex.Models
{
diff --git a/src/Ombi.Api.SickRage/Models/SickRageEpisodeStatus.cs b/src/Ombi.Api.SickRage/Models/SickRageEpisodeStatus.cs
index 4f131d5e3..9142e2b42 100644
--- a/src/Ombi.Api.SickRage/Models/SickRageEpisodeStatus.cs
+++ b/src/Ombi.Api.SickRage/Models/SickRageEpisodeStatus.cs
@@ -9,7 +9,7 @@ public class SickRageEpisodeStatus
public class SickRageEpisodeSetStatus
{
- public Data data { get; set; }
+ public Data[] data { get; set; }
public string message { get; set; }
public string result { get; set; }
}
diff --git a/src/Ombi.Api.Sonarr/SonarrApi.cs b/src/Ombi.Api.Sonarr/SonarrApi.cs
index d2df50cd9..50e4f04ff 100644
--- a/src/Ombi.Api.Sonarr/SonarrApi.cs
+++ b/src/Ombi.Api.Sonarr/SonarrApi.cs
@@ -19,7 +19,7 @@ public SonarrApi(IApi api)
protected IApi Api { get; }
protected virtual string ApiBaseUrl => "/api/";
- public async Task> GetProfiles(string apiKey, string baseUrl)
+ public virtual async Task> GetProfiles(string apiKey, string baseUrl)
{
var request = new Request($"{ApiBaseUrl}profile", baseUrl, HttpMethod.Get);
request.AddHeader("X-Api-Key", apiKey);
diff --git a/src/Ombi.Api.Sonarr/SonarrV3Api.cs b/src/Ombi.Api.Sonarr/SonarrV3Api.cs
index 64377ee4a..71c230f35 100644
--- a/src/Ombi.Api.Sonarr/SonarrV3Api.cs
+++ b/src/Ombi.Api.Sonarr/SonarrV3Api.cs
@@ -1,6 +1,8 @@
using System.Net.Http;
using System.Collections.Generic;
using System.Threading.Tasks;
+
+using Ombi.Api.Sonarr.Models;
using Ombi.Api.Sonarr.Models.V3;
namespace Ombi.Api.Sonarr
@@ -21,5 +23,12 @@ public async Task> LanguageProfiles(string apiKey,
return await Api.Request>(request);
}
+
+ public override async Task> GetProfiles(string apiKey, string baseUrl)
+ {
+ var request = new Request($"{ApiBaseUrl}qualityprofile", baseUrl, HttpMethod.Get);
+ request.AddHeader("X-Api-Key", apiKey);
+ return await Api.Request>(request);
+ }
}
}
diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs
index cb4cb4ba6..e5114677b 100644
--- a/src/Ombi.Core/Engine/MovieRequestEngine.cs
+++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs
@@ -136,6 +136,7 @@ public async Task RequestMovie(MovieRequestViewModel model)
Status = movieInfo.Status,
RequestedDate = model.Is4kRequest ? DateTime.MinValue : DateTime.Now,
Approved = false,
+ Approved4K = false,
RequestedUserId = canRequestOnBehalf ? model.RequestOnBehalf : userDetails.Id,
Background = movieInfo.BackdropPath,
LangCode = model.LanguageCode,
@@ -151,7 +152,7 @@ public async Task RequestMovie(MovieRequestViewModel model)
var usDates = movieInfo.ReleaseDates?.Results?.FirstOrDefault(x => x.IsoCode == "US");
requestModel.DigitalReleaseDate = usDates?.ReleaseDate
?.FirstOrDefault(x => x.Type == ReleaseDateType.Digital)?.ReleaseDate;
-
+
var ruleResults = (await RunRequestRules(requestModel)).ToList();
var ruleResultInError = ruleResults.Find(x => !x.Success);
if (ruleResultInError != null)
@@ -163,7 +164,7 @@ public async Task RequestMovie(MovieRequestViewModel model)
};
}
- if (requestModel.Approved) // The rules have auto approved this
+ if (requestModel.Approved || requestModel.Approved4K) // The rules have auto approved this
{
var requestEngineResult = await AddMovieRequest(requestModel, fullMovieName, model.RequestOnBehalf, isExisting, is4kRequest);
if (requestEngineResult.Result)
@@ -333,7 +334,7 @@ public async Task> GetRequestsByStatus(int coun
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))
+ (x.Has4KRequest && x.Approved4K && !x.Available4K && (!x.Denied4K.HasValue || !x.Denied4K.Value))
);
break;
case RequestStatus.Available:
@@ -533,7 +534,10 @@ private async Task CheckForSubscription(string UserId, List movie
}
else
{
- x.ShowSubscribe = true;
+ if (!x.Available && !x.Available4K && (!x.Denied ?? true) && (!x.Denied4K ?? true))
+ {
+ x.ShowSubscribe = true;
+ }
var hasSub = sub.FirstOrDefault(r => r.RequestId == x.Id);
x.Subscribed = hasSub != null;
}
diff --git a/src/Ombi.Core/Engine/MovieSearchEngine.cs b/src/Ombi.Core/Engine/MovieSearchEngine.cs
index 682a999eb..ae24e275a 100644
--- a/src/Ombi.Core/Engine/MovieSearchEngine.cs
+++ b/src/Ombi.Core/Engine/MovieSearchEngine.cs
@@ -16,7 +16,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Security.Principal;
using System.Threading.Tasks;
namespace Ombi.Core.Engine
@@ -161,7 +160,7 @@ public async Task> UpcomingMovies()
var result = await Cache.GetOrAddAsync(CacheKeys.UpcomingMovies, async () =>
{
var langCode = await DefaultLanguageCode(null);
- return await MovieApi.Upcoming(langCode);
+ return await MovieApi.UpcomingMovies(langCode);
}, DateTimeOffset.Now.AddHours(12));
if (result != null)
{
@@ -216,34 +215,9 @@ protected async Task ProcessSingleMovie(SearchMovieViewMod
await RunSearchRules(viewMovie);
- // This requires the rules to be run first to populate the RequestId property
- await CheckForSubscription(viewMovie);
-
return viewMovie;
}
- private async Task CheckForSubscription(SearchMovieViewModel viewModel)
- {
- // Check if this user requested it
- var user = await GetUser();
- if (user == null)
- {
- return;
- }
- var request = await RequestService.MovieRequestService.GetAll()
- .AnyAsync(x => x.RequestedUserId.Equals(user.Id) && x.TheMovieDbId == viewModel.Id);
- if (request || viewModel.Available)
- {
- viewModel.ShowSubscribe = false;
- }
- else
- {
- viewModel.ShowSubscribe = true;
- var sub = await _subscriptionRepository.GetAll().FirstOrDefaultAsync(s => s.UserId == user.Id
- && s.RequestId == viewModel.RequestId && s.RequestType == RequestType.Movie);
- viewModel.Subscribed = sub != null;
- }
- }
private async Task ProcessSingleMovie(MovieDbSearchResult movie)
{
diff --git a/src/Ombi.Core/Engine/MusicRequestEngine.cs b/src/Ombi.Core/Engine/MusicRequestEngine.cs
index 640d2ade3..67caa81a2 100644
--- a/src/Ombi.Core/Engine/MusicRequestEngine.cs
+++ b/src/Ombi.Core/Engine/MusicRequestEngine.cs
@@ -270,7 +270,10 @@ private async Task CheckForSubscription(HideResult shouldHide, List r.RequestId == x.Id);
x.Subscribed = hasSub != null;
}
diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs
index 5664d276f..8ccc6d17e 100644
--- a/src/Ombi.Core/Engine/TvRequestEngine.cs
+++ b/src/Ombi.Core/Engine/TvRequestEngine.cs
@@ -886,7 +886,10 @@ private async Task CheckForSubscription(HideResult shouldHide, List s.RequestId == x.Id);
x.Subscribed = result != null;
}
diff --git a/src/Ombi.Core/Engine/TvSearchEngine.cs b/src/Ombi.Core/Engine/TvSearchEngine.cs
index 2747f262a..ac2ed9979 100644
--- a/src/Ombi.Core/Engine/TvSearchEngine.cs
+++ b/src/Ombi.Core/Engine/TvSearchEngine.cs
@@ -106,11 +106,17 @@ public async Task GetShowInformation(string tvdbid, Cance
SeasonNumber = e.season,
Episodes = new List()
};
+ var hasAirDate = e.airstamp.HasValue();
+ var airDate = DateTime.MinValue;
+ if (hasAirDate)
+ {
+ hasAirDate = DateTime.TryParse(e.airdate, out airDate);
+ }
newSeason.Episodes.Add(new EpisodeRequests
{
Url = e.url.ToHttpsUrl(),
Title = e.name,
- AirDate = e.airstamp.HasValue() ? DateTime.Parse(e.airstamp) : DateTime.MinValue,
+ AirDate = airDate,
EpisodeNumber = e.number,
});
@@ -118,12 +124,18 @@ public async Task GetShowInformation(string tvdbid, Cance
}
else
{
+ var hasAirDate = e.airstamp.HasValue();
+ var airDate = DateTime.MinValue;
+ if (hasAirDate)
+ {
+ hasAirDate = DateTime.TryParse(e.airdate, out airDate);
+ }
// We already have the season, so just add the episode
season.Episodes.Add(new EpisodeRequests
{
Url = e.url.ToHttpsUrl(),
Title = e.name,
- AirDate = e.airstamp.HasValue() ? DateTime.Parse(e.airstamp) : DateTime.MinValue,
+ AirDate = airDate,
EpisodeNumber = e.number,
});
}
diff --git a/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs b/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs
index 7ad8c509a..7666db6fe 100644
--- a/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs
+++ b/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs
@@ -3,6 +3,7 @@
using System.Threading.Tasks;
using Ombi.Api.TheMovieDb.Models;
using Ombi.Core.Models.Search.V2;
+using Ombi.TheMovieDbApi.Models;
// Due to conflicting Genre models in
// Ombi.TheMovieDbApi.Models and Ombi.Api.TheMovieDb.Models
@@ -14,5 +15,6 @@ public interface IMultiSearchEngine
{
Task> MultiSearch(string searchTerm, MultiSearchFilter filter, CancellationToken cancellationToken);
Task> GetGenres(string media, CancellationToken requestAborted);
+ Task> GetLanguages(CancellationToken requestAborted);
}
}
\ No newline at end of file
diff --git a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs
index 3acd7d1f0..044d79969 100644
--- a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs
+++ b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs
@@ -11,6 +11,7 @@
using Ombi.Core.Models.Search.V2;
using Ombi.Core.Models.UI;
using Ombi.Core.Rule.Interfaces;
+using Ombi.Core.Services;
using Ombi.Core.Settings;
using Ombi.Helpers;
using Ombi.Settings.Settings.Models;
@@ -31,7 +32,8 @@ public class MovieSearchEngineV2 : BaseMediaEngine, IMovieEngineV2
{
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)
+ ISettingsService customizationSettings, IMovieRequestEngine movieRequestEngine, IHttpClientFactory httpClientFactory,
+ IFeatureService feature)
: base(identity, service, r, um, mem, s, sub)
{
MovieApi = movApi;
@@ -40,6 +42,7 @@ public MovieSearchEngineV2(ICurrentUser identity, IRequestServiceMain service, I
_customizationSettings = customizationSettings;
_movieRequestEngine = movieRequestEngine;
_client = httpClientFactory.CreateClient();
+ _feature = feature;
}
private IMovieDbApi MovieApi { get; }
@@ -48,6 +51,7 @@ public MovieSearchEngineV2(ICurrentUser identity, IRequestServiceMain service, I
private readonly ISettingsService _customizationSettings;
private readonly IMovieRequestEngine _movieRequestEngine;
private readonly HttpClient _client;
+ private readonly IFeatureService _feature;
public async Task GetFullMovieInformation(int theMovieDbId, CancellationToken cancellationToken, string langCode = null)
{
@@ -148,15 +152,15 @@ public async Task> AdvancedSearch(DiscoverMode
{
var langCode = await DefaultLanguageCode(null);
- //var pages = PaginationHelper.GetNextPages(currentlyLoaded, toLoad, _theMovieDbMaxPageItems);
+ var pages = PaginationHelper.GetNextPages(currentlyLoaded, toLoad, _theMovieDbMaxPageItems);
var results = new List();
- //foreach (var pagesToLoad in pages)
- //{
- var apiResult = await MovieApi.AdvancedSearch(model, cancellationToken);
- //results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take));
- //}
- return await TransformMovieResultsToResponse(apiResult);
+ foreach (var pagesToLoad in pages)
+ {
+ var apiResult = await MovieApi.AdvancedSearch(model, pagesToLoad.Page, cancellationToken);
+ results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take));
+ }
+ return await TransformMovieResultsToResponse(results);
}
///
@@ -196,14 +200,19 @@ public async Task> TopRatedMovies(int currentP
public async Task> NowPlayingMovies(int currentPosition, int amountToLoad)
{
var langCode = await DefaultLanguageCode(null);
+ var isOldTrendingSourceEnabled = await _feature.FeatureEnabled(FeatureNames.OldTrendingSource);
var pages = PaginationHelper.GetNextPages(currentPosition, amountToLoad, _theMovieDbMaxPageItems);
var results = new List();
foreach (var pagesToLoad in pages)
{
+ var search = () => (isOldTrendingSourceEnabled) ?
+ MovieApi.NowPlaying(langCode, pagesToLoad.Page)
+ : MovieApi.TrendingMovies(langCode, pagesToLoad.Page);
+
var apiResult = await Cache.GetOrAddAsync(nameof(NowPlayingMovies) + pagesToLoad.Page + langCode,
- () => MovieApi.NowPlaying(langCode, pagesToLoad.Page), DateTimeOffset.Now.AddHours(12));
+ search, DateTimeOffset.Now.AddHours(12));
results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take));
}
return await TransformMovieResultsToResponse(results);
@@ -278,7 +287,7 @@ public async Task> UpcomingMovies()
var result = await Cache.GetOrAddAsync(CacheKeys.UpcomingMovies, async () =>
{
var langCode = await DefaultLanguageCode(null);
- return await MovieApi.Upcoming(langCode);
+ return await MovieApi.UpcomingMovies(langCode);
}, DateTimeOffset.Now.AddHours(12));
if (result != null)
{
@@ -298,7 +307,7 @@ public async Task> UpcomingMovies(int currentP
foreach (var pagesToLoad in pages)
{
var apiResult = await Cache.GetOrAddAsync(nameof(UpcomingMovies) + pagesToLoad.Page + langCode,
- () => MovieApi.Upcoming(langCode, pagesToLoad.Page), DateTimeOffset.Now.AddHours(12));
+ () => MovieApi.UpcomingMovies(langCode, pagesToLoad.Page), DateTimeOffset.Now.AddHours(12));
results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take));
}
return await TransformMovieResultsToResponse(results);
@@ -393,8 +402,6 @@ private async Task ProcessSingleMovie(FullMovieInfo movi
await RunSearchRules(viewMovie);
- // This requires the rules to be run first to populate the RequestId property
- await CheckForSubscription(viewMovie);
var mapped = Mapper.Map(movie);
mapped.Available = viewMovie.Available;
@@ -406,8 +413,6 @@ private async Task ProcessSingleMovie(FullMovieInfo movi
mapped.PlexUrl = viewMovie.PlexUrl;
mapped.EmbyUrl = viewMovie.EmbyUrl;
mapped.JellyfinUrl = viewMovie.JellyfinUrl;
- mapped.Subscribed = viewMovie.Subscribed;
- mapped.ShowSubscribe = viewMovie.ShowSubscribe;
mapped.DigitalReleaseDate = viewMovie.DigitalReleaseDate;
mapped.RequestedDate4k = viewMovie.RequestedDate4k;
mapped.Approved4K = viewMovie.Approved4K;
@@ -429,8 +434,6 @@ private async Task ProcessCollection(Collections coll
var mappedMovie = Mapper.Map(movie);
await RunSearchRules(mappedMovie);
- // This requires the rules to be run first to populate the RequestId property
- await CheckForSubscription(mappedMovie);
var mapped = Mapper.Map(movie);
mapped.Available = movie.Available;
@@ -440,8 +443,6 @@ private async Task ProcessCollection(Collections coll
mapped.PlexUrl = movie.PlexUrl;
mapped.EmbyUrl = movie.EmbyUrl;
mapped.JellyfinUrl = movie.JellyfinUrl;
- mapped.Subscribed = movie.Subscribed;
- mapped.ShowSubscribe = movie.ShowSubscribe;
mapped.ReleaseDate = movie.ReleaseDate;
}
return viewMovie;
@@ -470,34 +471,9 @@ private async Task ProcessSingleMovie(SearchMovieViewModel
await RunSearchRules(viewMovie);
- // This requires the rules to be run first to populate the RequestId property
- await CheckForSubscription(viewMovie);
-
return viewMovie;
}
- private async Task CheckForSubscription(SearchViewModel viewModel)
- {
- // Check if this user requested it
- var user = await GetUser();
- if (user == null)
- {
- return;
- }
- var request = await RequestService.MovieRequestService.GetAll()
- .AnyAsync(x => x.RequestedUserId.Equals(user.Id) && x.TheMovieDbId == viewModel.Id);
- if (request)
- {
- viewModel.ShowSubscribe = false;
- }
- else
- {
- viewModel.ShowSubscribe = true;
- var sub = await _subscriptionRepository.GetAll().FirstOrDefaultAsync(s => s.UserId == user.Id
- && s.RequestId == viewModel.RequestId && s.RequestType == RequestType.Movie);
- viewModel.Subscribed = sub != null;
- }
- }
public async Task GetMovieInfoByImdbId(string imdbId, CancellationToken cancellationToken)
{
diff --git a/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs b/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs
index 362a79e43..3f96f1598 100644
--- a/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs
+++ b/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs
@@ -17,6 +17,7 @@
using Ombi.Settings.Settings.Models.External;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
+using Ombi.TheMovieDbApi.Models;
// Due to conflicting Genre models in
// Ombi.TheMovieDbApi.Models and Ombi.Api.TheMovieDb.Models
@@ -124,5 +125,9 @@ public async Task> GetGenres(string media, CancellationToken
var lang = await DefaultLanguageCode(null);
return await _movieDbApi.GetGenres(media, cancellationToken, lang);
}
+ public async Task> GetLanguages(CancellationToken cancellationToken)
+ {
+ return await _movieDbApi.GetLanguages(cancellationToken);
+ }
}
}
diff --git a/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs
index 344ced813..ee21db8dd 100644
--- a/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs
+++ b/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs
@@ -26,6 +26,7 @@
using Ombi.Core.Engine.Interfaces;
using Ombi.Core.Models.UI;
using Ombi.Core.Helpers;
+using Ombi.Core.Services;
namespace Ombi.Core.Engine.V2
{
@@ -37,10 +38,12 @@ public class TvSearchEngineV2 : BaseMediaEngine, ITVSearchEngineV2
private readonly IMovieDbApi _movieApi;
private readonly ISettingsService _customization;
private readonly ITvRequestEngine _requestEngine;
+ private readonly IFeatureService _feature;
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)
+ IRepository sub, IMovieDbApi movieApi, ISettingsService customization, ITvRequestEngine requestEngine,
+ IFeatureService feature)
: base(identity, service, r, um, memCache, s, sub)
{
_tvMaze = tvMaze;
@@ -49,6 +52,7 @@ public TvSearchEngineV2(ICurrentUser identity, IRequestServiceMain service, ITvM
_movieApi = movieApi;
_customization = customization;
_requestEngine = requestEngine;
+ _feature = feature;
}
@@ -132,15 +136,19 @@ public async Task> Anticipated(int currentlyL
}
public async Task> Trending(int currentlyLoaded, int amountToLoad)
- {
+ {
var langCode = await DefaultLanguageCode(null);
+ var isOldTrendingSourceEnabled = await _feature.FeatureEnabled(FeatureNames.OldTrendingSource);
var pages = PaginationHelper.GetNextPages(currentlyLoaded, amountToLoad, ResultLimit);
var results = new List();
foreach (var pagesToLoad in pages)
{
+ var search = ( async () => (isOldTrendingSourceEnabled) ?
+ await _movieApi.TopRatedTv(langCode, pagesToLoad.Page)
+ : await _movieApi.TrendingTv(langCode, pagesToLoad.Page));
var apiResult = await Cache.GetOrAddAsync(nameof(Trending) + langCode + pagesToLoad.Page,
- async () => await _movieApi.TopRatedTv(langCode, pagesToLoad.Page), DateTimeOffset.Now.AddHours(12));
+ search, DateTimeOffset.Now.AddHours(12));
results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take));
}
@@ -264,11 +272,17 @@ private static void MapSeasons(List seasonRequests, Season tvSea
Overview = tvSeason.overview,
Episodes = new List()
};
+ var hasAirDate = episode.air_date.HasValue();
+ var airDate = DateTime.MinValue;
+ if (hasAirDate)
+ {
+ DateTime.TryParse(episode.air_date, out airDate);
+ }
newSeason.Episodes.Add(new EpisodeRequests
{
//Url = episode...ToHttpsUrl(),
Title = episode.name,
- AirDate = episode.air_date.HasValue() ? DateTime.Parse(episode.air_date) : DateTime.MinValue,
+ AirDate = airDate,
EpisodeNumber = episode.episode_number,
});
@@ -276,12 +290,18 @@ private static void MapSeasons(List seasonRequests, Season tvSea
}
else
{
+ var hasAirDate = episode.air_date.HasValue();
+ var airDate = DateTime.MinValue;
+ if (hasAirDate)
+ {
+ DateTime.TryParse(episode.air_date, out airDate);
+ }
// We already have the season, so just add the episode
season.Episodes.Add(new EpisodeRequests
{
//Url = e.url.ToHttpsUrl(),
Title = episode.name,
- AirDate = episode.air_date.HasValue() ? DateTime.Parse(episode.air_date) : DateTime.MinValue,
+ AirDate = airDate,
EpisodeNumber = episode.episode_number,
});
}
diff --git a/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs b/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs
index fc66d197d..5fe378465 100644
--- a/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs
+++ b/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs
@@ -261,9 +261,16 @@ public TvShowRequestBuilder CreateNewRequest(TvRequestViewModel tv)
return this;
}
- private DateTime FormatDate(string date)
+ private static DateTime FormatDate(string date)
{
- return string.IsNullOrEmpty(date) ? DateTime.MinValue : DateTime.Parse(date);
+ if (date.HasValue())
+ {
+ if (DateTime.TryParse(date, out var d))
+ {
+ return d;
+ }
+ }
+ return DateTime.MinValue;
}
}
}
\ No newline at end of file
diff --git a/src/Ombi.Core/Helpers/TvShowRequestBuilderV2.cs b/src/Ombi.Core/Helpers/TvShowRequestBuilderV2.cs
index 4053109da..5bb4e61fd 100644
--- a/src/Ombi.Core/Helpers/TvShowRequestBuilderV2.cs
+++ b/src/Ombi.Core/Helpers/TvShowRequestBuilderV2.cs
@@ -9,6 +9,7 @@
using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository.Requests;
using System.Threading;
+using Ombi.Helpers;
namespace Ombi.Core.Helpers
{
@@ -255,9 +256,16 @@ public TvShowRequestBuilderV2 CreateNewRequest(TvRequestViewModelV2 tv, int root
return this;
}
- private DateTime FormatDate(string date)
+ private static DateTime FormatDate(string date)
{
- return string.IsNullOrEmpty(date) ? DateTime.MinValue : DateTime.Parse(date);
+ if (date.HasValue())
+ {
+ if (DateTime.TryParse(date, out var d))
+ {
+ return d;
+ }
+ }
+ return DateTime.MinValue;
}
}
}
\ 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 e1a2f2850..4dda0444e 100644
--- a/src/Ombi.Core/Models/Search/SearchViewModel.cs
+++ b/src/Ombi.Core/Models/Search/SearchViewModel.cs
@@ -36,6 +36,7 @@ public abstract class SearchViewModel
[Obsolete("Use request service instead")]
public bool Subscribed { get; set; }
[NotMapped]
+ [Obsolete("Use request service instead")]
public bool ShowSubscribe { get; set; }
}
}
diff --git a/src/Ombi.Core/Senders/MusicSender.cs b/src/Ombi.Core/Senders/MusicSender.cs
index 6390578dd..260b008fe 100644
--- a/src/Ombi.Core/Senders/MusicSender.cs
+++ b/src/Ombi.Core/Senders/MusicSender.cs
@@ -70,7 +70,7 @@ await _requestQueueRepository.Add(new RequestQueue
}
- return new SenderResult { Success = false, Sent = false, Message = "Something went wrong!" };
+ return new SenderResult { Success = false, Sent = false };
}
private async Task SendToLidarr(AlbumRequest model, LidarrSettings settings)
diff --git a/src/Ombi.Core/Senders/TvSender.cs b/src/Ombi.Core/Senders/TvSender.cs
index 3676d05ee..22f6aadcd 100644
--- a/src/Ombi.Core/Senders/TvSender.cs
+++ b/src/Ombi.Core/Senders/TvSender.cs
@@ -133,8 +133,7 @@ await _requestQueueRepository.Add(new RequestQueue
return new SenderResult
{
- Success = false,
- Message = "Something went wrong!"
+ Success = false
};
}
@@ -343,8 +342,6 @@ private async Task SendToSonarr(ChildRequests model, SonarrSeries result, Sonarr
await Task.Delay(500);
}
- var seriesChanges = false;
-
foreach (var season in model.SeasonRequests)
{
foreach (var ep in season.Episodes)
@@ -359,72 +356,36 @@ private async Task SendToSonarr(ChildRequests model, SonarrSeries result, Sonarr
}
existingSeason = result.seasons.FirstOrDefault(x => x.seasonNumber == season.SeasonNumber);
- var sonarrEpisodeList = sonarrEpList.Where(x => x.seasonNumber == season.SeasonNumber).ToList();
- var sonarrEpCount = sonarrEpisodeList.Count;
- var ourRequestCount = season.Episodes.Count;
-
- var ourEpisodes = season.Episodes.Select(x => x.EpisodeNumber).ToList();
- var unairedEpisodes = sonarrEpisodeList.Where(x => x.airDateUtc > DateTime.UtcNow).Select(x => x.episodeNumber).ToList();
- //// Check if we have requested all the latest episodes, if we have then monitor
- //// NOTE, not sure if needed since ombi ui displays future episodes anyway...
- //ourEpisodes.AddRange(unairedEpisodes);
- //var distinctEpisodes = ourEpisodes.Distinct().ToList();
- //var missingEpisodes = Enumerable.Range(distinctEpisodes.Min(), distinctEpisodes.Count).Except(distinctEpisodes);
-
- if (sonarrEpCount == ourRequestCount /*|| !missingEpisodes.Any()*/)
+ // Make sure this season is set to monitored
+ if (!existingSeason.monitored)
{
- // We have the same amount of requests as all of the episodes in the season.
+ // We need to monitor it, problem being is all episodes will now be monitored
+ // So we need to monitor the series but unmonitor every episode
existingSeason.monitored = true;
- seriesChanges = true;
+ var sea = result.seasons.FirstOrDefault(x => x.seasonNumber == existingSeason.seasonNumber);
+ sea.monitored = true;
- // 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
- {
- // Make sure this season is set to monitored
- if (!existingSeason.monitored)
+ result = await SonarrApi.UpdateSeries(result, s.ApiKey, s.FullUri);
+ var epToUnmonitored = new List();
+ var newEpList = sonarrEpList.ConvertAll(ep => new Episode(ep)); // Clone it so we don't modify the original member
+ foreach (var ep in newEpList.Where(x => x.seasonNumber == existingSeason.seasonNumber).ToList())
{
- // We need to monitor it, problem being is all episodes will now be monitored
- // So we need to monitor the series but unmonitor every episode
- // Except the episodes that are already monitored before we update the series (we do not want to unmonitored episodes that are monitored beforehand)
- existingSeason.monitored = true;
- var sea = result.seasons.FirstOrDefault(x => x.seasonNumber == existingSeason.seasonNumber);
- sea.monitored = true;
- //var previouslyMonitoredEpisodes = sonarrEpList.Where(x =>
- // x.seasonNumber == existingSeason.seasonNumber && x.monitored).Select(x => x.episodeNumber).ToList(); // We probably don't actually care about this
- result = await SonarrApi.UpdateSeries(result, s.ApiKey, s.FullUri);
- var epToUnmonitored = new List();
- var newEpList = sonarrEpList.ConvertAll(ep => new Episode(ep)); // Clone it so we don't modify the original member
- foreach (var ep in newEpList.Where(x => x.seasonNumber == existingSeason.seasonNumber).ToList())
- {
- //if (previouslyMonitoredEpisodes.Contains(ep.episodeNumber))
- //{
- // // This was previously monitored.
- // continue;
- //}
- ep.monitored = false;
- epToUnmonitored.Add(ep);
- }
-
- foreach (var epToUpdate in epToUnmonitored)
- {
- await SonarrApi.UpdateEpisode(epToUpdate, s.ApiKey, s.FullUri);
- }
+ ep.monitored = false;
+ epToUnmonitored.Add(ep);
}
- // Now update the episodes that need updating
- foreach (var epToUpdate in episodesToUpdate.Where(x => x.seasonNumber == season.SeasonNumber))
+
+ foreach (var epToUpdate in epToUnmonitored)
{
await SonarrApi.UpdateEpisode(epToUpdate, s.ApiKey, s.FullUri);
}
}
- }
- if (seriesChanges)
- {
- await SonarrApi.SeasonPass(s.ApiKey, s.FullUri, result);
+ // 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);
+ }
}
if (!s.AddOnly)
diff --git a/src/Ombi.Helpers.Tests/PagnationHelperTests.cs b/src/Ombi.Helpers.Tests/PagnationHelperTests.cs
index 4b058c403..44bbfdd8e 100644
--- a/src/Ombi.Helpers.Tests/PagnationHelperTests.cs
+++ b/src/Ombi.Helpers.Tests/PagnationHelperTests.cs
@@ -83,6 +83,8 @@ public static IEnumerable CurrentPositionMultiplePagesTestData
.SetName("PaginationPosition_Load_SecondHalf_FirstPage_FirstHalf_SecondPage");
yield return new TestCaseData(0, 40, 20, new List { new MultiplePagesTestData(1, 20, 0), new MultiplePagesTestData(2, 20, 0) })
.SetName("PaginationPosition_Load_Full_First_And_SecondPage");
+ yield return new TestCaseData(40, 40, 20, new List { new MultiplePagesTestData(3, 20, 0), new MultiplePagesTestData(4, 20, 0) })
+ .SetName("PaginationPosition_Load_Full_Third_And_ForthPage");
yield return new TestCaseData(35, 15, 20, new List { new MultiplePagesTestData(2, 5, 15), new MultiplePagesTestData(3, 10, 0) })
.SetName("PaginationPosition_Load_EndSecondPage_Beginning_ThirdPage");
yield return new TestCaseData(18, 22, 20, new List { new MultiplePagesTestData(1, 2, 18), new MultiplePagesTestData(2, 20, 0) })
diff --git a/src/Ombi.Helpers/PaginationHelper.cs b/src/Ombi.Helpers/PaginationHelper.cs
index 520f56b19..2caafe186 100644
--- a/src/Ombi.Helpers/PaginationHelper.cs
+++ b/src/Ombi.Helpers/PaginationHelper.cs
@@ -17,7 +17,7 @@ public static List GetNextPages(int currentlyLoaded, int toTake, in
var lastPage = lastItemIndex / maxItemsPerPage + 1;
var stopPos = lastItemIndex % maxItemsPerPage + 1;
- while (currentlyLoaded > maxItemsPerPage)
+ while (currentlyLoaded >= maxItemsPerPage)
{
currentlyLoaded -= maxItemsPerPage;
}
diff --git a/src/Ombi.I18n/Resources/Texts.de.resx b/src/Ombi.I18n/Resources/Texts.de.resx
index a222d02b0..91a4aced4 100644
--- a/src/Ombi.I18n/Resources/Texts.de.resx
+++ b/src/Ombi.I18n/Resources/Texts.de.resx
@@ -139,7 +139,7 @@
Episoden:
- Powered by
+ Betrieben durch
Abbestellen
@@ -148,9 +148,9 @@
Album
- Movie
+ Film
- TV Show
+ TV-Serie
\ No newline at end of file
diff --git a/src/Ombi.I18n/Resources/Texts.pl.resx b/src/Ombi.I18n/Resources/Texts.pl.resx
index c8e5e5ee1..f7833ced6 100644
--- a/src/Ombi.I18n/Resources/Texts.pl.resx
+++ b/src/Ombi.I18n/Resources/Texts.pl.resx
@@ -118,13 +118,13 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- Nowy Album
+ Nowe Albumy
- Nowy film
+ Nowe filmy
- Nowy telewizor
+ Nowe seriale
Gatunki:
@@ -136,21 +136,21 @@
Sezon:
- Odcinków:
+ Odcinki:
Wspierane przez
- Wypisać się
+ Wypisz się
Album
- Movie
+ Film
- TV Show
+ Serial
\ No newline at end of file
diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs
index 9d88c5907..8e8b75e45 100644
--- a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs
+++ b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs
@@ -7,10 +7,12 @@
using Microsoft.Extensions.Logging;
using Ombi.Core;
using Ombi.Core.Notifications;
+using Ombi.Core.Services;
using Ombi.Helpers;
using Ombi.Hubs;
using Ombi.Notifications.Models;
using Ombi.Schedule.Jobs.Ombi;
+using Ombi.Settings.Settings.Models;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
using Ombi.Store.Repository.Requests;
@@ -21,7 +23,7 @@ namespace Ombi.Schedule.Jobs.Emby
public class EmbyAvaliabilityChecker : IEmbyAvaliabilityChecker
{
public EmbyAvaliabilityChecker(IEmbyContentRepository repo, ITvRequestRepository t, IMovieRequestRepository m,
- INotificationHelper n, ILogger log, IHubContext notification)
+ INotificationHelper n, ILogger log, IHubContext notification, IFeatureService featureService)
{
_repo = repo;
_tvRepo = t;
@@ -29,6 +31,7 @@ public EmbyAvaliabilityChecker(IEmbyContentRepository repo, ITvRequestRepository
_notificationService = n;
_log = log;
_notification = notification;
+ _featureService = featureService;
}
private readonly ITvRequestRepository _tvRepo;
@@ -37,6 +40,7 @@ public EmbyAvaliabilityChecker(IEmbyContentRepository repo, ITvRequestRepository
private readonly INotificationHelper _notificationService;
private readonly ILogger _log;
private readonly IHubContext _notification;
+ private readonly IFeatureService _featureService;
public async Task Execute(IJobExecutionContext job)
{
@@ -53,6 +57,7 @@ await _notification.Clients.Clients(NotificationHub.AdminConnectionIds)
private async Task ProcessMovies()
{
+ var feature4kEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests);
var movies = _movieRepo.GetAll().Include(x => x.RequestedUser).Where(x => !x.Available || (!x.Available4K && x.Has4KRequest));
foreach (var movie in movies)
@@ -85,8 +90,8 @@ private async Task ProcessMovies()
notify = true;
}
- // If we have a non-4k versison then mark as available
- if (embyContent.Quality != null && !movie.Available)
+ // If we have a non-4k version or we don't care about versions, then mark as available
+ if (!movie.Available && ( !feature4kEnabled || embyContent.Quality != null ))
{
movie.Available = true;
movie.MarkedAsAvailable = DateTime.Now;
diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs
index b4d61f93d..27cdf0f3a 100644
--- a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs
+++ b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs
@@ -157,9 +157,20 @@ private async Task ProcessTv(EmbyServers server, bool recentlyAdded, string pare
}
var existingTv = await _repo.GetByEmbyId(tvShow.Id);
+
+ if (existingTv != null &&
+ ( existingTv.ImdbId != tvShow.ProviderIds?.Imdb
+ || existingTv.TheMovieDbId != tvShow.ProviderIds?.Tmdb
+ || existingTv.TvDbId != tvShow.ProviderIds?.Tvdb))
+ {
+ _logger.LogDebug($"Series '{tvShow.Name}' has different IDs, probably a reidentification.");
+ await _repo.DeleteTv(existingTv);
+ existingTv = null;
+ }
+
if (existingTv == null)
{
- _logger.LogDebug("Adding new TV Show {0}", tvShow.Name);
+ _logger.LogDebug("Adding TV Show {0}", tvShow.Name);
mediaToAdd.Add(new EmbyContent
{
TvDbId = tvShow.ProviderIds?.Tvdb,
@@ -265,23 +276,21 @@ private async Task ProcessMovies(EmbyMovie movieInfo, ICollection c
return;
}
_logger.LogDebug($"Adding new movie {movieInfo.Name}");
-
- content.Add(new EmbyContent
- {
- ImdbId = movieInfo.ProviderIds.Imdb,
- TheMovieDbId = movieInfo.ProviderIds?.Tmdb,
- Title = movieInfo.Name,
- Type = MediaType.Movie,
- EmbyId = movieInfo.Id,
- Url = EmbyHelper.GetEmbyMediaUrl(movieInfo.Id, server?.ServerId, server.ServerHostname),
- AddedAt = DateTime.UtcNow,
- Quality = has4K ? null : quality,
- Has4K = has4K
- });
+ var newMovie = new EmbyContent();
+ newMovie.AddedAt = DateTime.UtcNow;
+ MapEmbyContent(newMovie, movieInfo, server, has4K, quality);
+ content.Add(newMovie);
}
else
{
- if (!quality.Equals(existingMovie?.Quality, StringComparison.InvariantCultureIgnoreCase))
+ var movieHasChanged = false;
+ if (existingMovie.ImdbId != movieInfo.ProviderIds.Imdb || existingMovie.TheMovieDbId != movieInfo.ProviderIds.Tmdb)
+ {
+ _logger.LogDebug($"Updating existing movie '{movieInfo.Name}'");
+ MapEmbyContent(existingMovie, movieInfo, server, has4K, quality);
+ movieHasChanged = true;
+ }
+ else 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;
@@ -290,6 +299,11 @@ private async Task ProcessMovies(EmbyMovie movieInfo, ICollection c
// 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
+ movieHasChanged = true;
+ }
+
+ if (movieHasChanged)
+ {
toUpdate.Add(existingMovie);
}
else
@@ -300,6 +314,17 @@ private async Task ProcessMovies(EmbyMovie movieInfo, ICollection c
}
}
+ private void MapEmbyContent(EmbyContent content, EmbyMovie movieInfo, EmbyServers server, bool has4K, string quality){
+ content.ImdbId = movieInfo.ProviderIds.Imdb;
+ content.TheMovieDbId = movieInfo.ProviderIds?.Tmdb;
+ content.Title = movieInfo.Name;
+ content.Type = MediaType.Movie;
+ content.EmbyId = movieInfo.Id;
+ content.Url = EmbyHelper.GetEmbyMediaUrl(movieInfo.Id, server?.ServerId, server.ServerHostname);
+ content.Quality = has4K ? null : quality;
+ content.Has4K = has4K;
+ }
+
private bool ValidateSettings(EmbyServers server)
{
if (server?.Ip == null || string.IsNullOrEmpty(server?.ApiKey))
diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs
index b3c1ffbab..5293d30b4 100644
--- a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs
+++ b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs
@@ -130,12 +130,6 @@ private async Task CacheEpisodes(EmbyServers server, bool recentlyAdded, string
{
processed++;
- if (ep.LocationType?.Equals("Virtual", StringComparison.InvariantCultureIgnoreCase) ?? false)
- {
- // For some reason Emby is not respecting the `IsVirtualItem` field.
- continue;
- }
-
// Let's make sure we have the parent request, stop those pesky forign key errors,
// Damn me having data integrity
var parent = await _repo.GetByEmbyId(ep.SeriesId);
@@ -176,18 +170,26 @@ private async Task CacheEpisodes(EmbyServers server, bool recentlyAdded, string
if (ep.IndexNumberEnd.HasValue && ep.IndexNumberEnd.Value != ep.IndexNumber)
{
- epToAdd.Add(new EmbyEpisode
+ int episodeNumber = ep.IndexNumber;
+ do
{
- EmbyId = ep.Id,
- EpisodeNumber = ep.IndexNumberEnd.Value,
- SeasonNumber = ep.ParentIndexNumber,
- ParentId = ep.SeriesId,
- TvDbId = ep.ProviderIds.Tvdb,
- TheMovieDbId = ep.ProviderIds.Tmdb,
- ImdbId = ep.ProviderIds.Imdb,
- Title = ep.Name,
- AddedAt = DateTime.UtcNow
- });
+ _logger.LogDebug($"Multiple-episode file detected. Adding episode ${episodeNumber}");
+ episodeNumber++;
+ epToAdd.Add(new EmbyEpisode
+ {
+ EmbyId = ep.Id,
+ EpisodeNumber = episodeNumber,
+ SeasonNumber = ep.ParentIndexNumber,
+ ParentId = ep.SeriesId,
+ TvDbId = ep.ProviderIds.Tvdb,
+ TheMovieDbId = ep.ProviderIds.Tmdb,
+ ImdbId = ep.ProviderIds.Imdb,
+ Title = ep.Name,
+ AddedAt = DateTime.UtcNow
+ });
+
+ } while (episodeNumber < ep.IndexNumberEnd.Value);
+
}
}
}
diff --git a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs
index b1dafa71f..79eb5d6a4 100644
--- a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs
+++ b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs
@@ -33,9 +33,11 @@
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.Settings.Settings.Models;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
using Ombi.Store.Repository.Requests;
@@ -46,7 +48,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin
public class JellyfinAvaliabilityChecker : IJellyfinAvaliabilityChecker
{
public JellyfinAvaliabilityChecker(IJellyfinContentRepository repo, ITvRequestRepository t, IMovieRequestRepository m,
- INotificationHelper n, ILogger log, IHubContext notification)
+ INotificationHelper n, ILogger log, IHubContext notification, IFeatureService featureService)
{
_repo = repo;
_tvRepo = t;
@@ -54,6 +56,7 @@ public JellyfinAvaliabilityChecker(IJellyfinContentRepository repo, ITvRequestRe
_notificationService = n;
_log = log;
_notification = notification;
+ _featureService = featureService;
}
private readonly ITvRequestRepository _tvRepo;
@@ -62,6 +65,7 @@ public JellyfinAvaliabilityChecker(IJellyfinContentRepository repo, ITvRequestRe
private readonly INotificationHelper _notificationService;
private readonly ILogger _log;
private readonly IHubContext _notification;
+ private readonly IFeatureService _featureService;
public async Task Execute(IJobExecutionContext job)
{
@@ -78,6 +82,7 @@ await _notification.Clients.Clients(NotificationHub.AdminConnectionIds)
private async Task ProcessMovies()
{
+ var feature4kEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests);
var movies = _movieRepo.GetAll().Include(x => x.RequestedUser).Where(x => !x.Available || (!x.Available4K && x.Has4KRequest));
foreach (var movie in movies)
@@ -110,8 +115,8 @@ private async Task ProcessMovies()
notify = true;
}
- // If we have a non-4k versison then mark as available
- if (jellyfinContent.Quality != null && !movie.Available)
+ // If we have a non-4k version or we don't care about versions, then mark as available
+ if (!movie.Available && ( !feature4kEnabled || jellyfinContent.Quality != null ))
{
movie.Available = true;
movie.MarkedAsAvailable = DateTime.Now;
diff --git a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs
index 060c974e7..5519b3413 100644
--- a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs
+++ b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs
@@ -132,9 +132,20 @@ private async Task ProcessTv(JellyfinServers server, string parentId = default)
}
var existingTv = await _repo.GetByJellyfinId(tvShow.Id);
+
+ if (existingTv != null &&
+ ( existingTv.ImdbId != tvShow.ProviderIds?.Imdb
+ || existingTv.TheMovieDbId != tvShow.ProviderIds?.Tmdb
+ || existingTv.TvDbId != tvShow.ProviderIds?.Tvdb))
+ {
+ _logger.LogDebug($"Series '{tvShow.Name}' has different IDs, probably a reidentification.");
+ await _repo.DeleteTv(existingTv);
+ existingTv = null;
+ }
+
if (existingTv == null)
{
- _logger.LogDebug("Adding new TV Show {0}", tvShow.Name);
+ _logger.LogDebug("Adding TV Show {0}", tvShow.Name);
mediaToAdd.Add(new JellyfinContent
{
TvDbId = tvShow.ProviderIds?.Tvdb,
@@ -230,22 +241,21 @@ private async Task ProcessMovies(JellyfinMovie movieInfo, ICollection FilterEpisodes(IEnumerable source, IEnumerable recentlyAdded)
{
var itemsToReturn = new HashSet();
- foreach (var ep in source.Where(x => x.Series.HasTvDb))
+ foreach (var ep in source.Where(x => x.Series.HasTvDb // needed for recentlyAddedLog
+ && x.Series.HasTheMovieDb // needed to fetch info to publish, this is just in case...
+ ))
{
var tvDbId = StringHelper.IntParseLinq(ep.Series.TvDbId);
if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber))
@@ -501,16 +503,11 @@ private async Task ProcessMovies(ICollection plexContentToS
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 = content.Url;
if (info == null)
{
- _log.LogWarning($"TMDB does not know movie {content.Title}, it won't be published.");
+ _log.LogError($"TMDB does not know movie {content.Title}. This shouldn't happen because our media server knows it as ID '{movieDbId}'.");
continue;
}
try
@@ -665,48 +662,18 @@ private async Task ProcessTv(IEnumerable episodes, string l
var orderedTv = series.OrderByDescending(x => x.AddedAt);
foreach (var t in orderedTv)
{
- if (!t.HasTvDb)
- {
- // We may need to use themoviedb for the imdbid or their own id to get info
- if (t.HasTheMovieDb)
- {
- int.TryParse(t.TheMovieDbId, out var movieId);
- 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();
- }
- // WE could check the below but we need to get the moviedb and then perform the above, let the metadata job figure this out.
- //else if(t.HasImdb)
- //{
- // // Check the imdbid
- // var externals = await _movieApi.Find(t.ImdbId, ExternalSource.imdb_id);
- // if (externals?.tv_results == null || externals.tv_results.Length <= 0)
- // {
- // continue;
- // }
- // t.TvDbId = externals.tv_results.FirstOrDefault()..ToString();
- //}
-
- }
-
try
{
var tvInfo = await _movieApi.GetTVInfo(t.TheMovieDbId, languageCode);
if (tvInfo == null)
{
- _log.LogWarning($"TMDB does not know series {t.Title}, it won't be published.");
+ _log.LogError($"TMDB does not know series {t.Title}. This shouldn't happen because our media server knows it as ID '{t.TheMovieDbId}'.");
continue;
}
if (tvInfo.backdrop_path.HasValue())
{
-
AddBackgroundInsideTable($"https://image.tmdb.org/t/p/w500{tvInfo.backdrop_path}");
}
else
@@ -732,7 +699,7 @@ private async Task ProcessTv(IEnumerable episodes, string l
}
catch (Exception e)
{
- _log.LogError(e, "Error when processing Plex TV {0}", t.Title);
+ _log.LogError(e, "Error when processing TV {0}", t.Title);
}
finally
{
diff --git a/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs b/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs
index c2df1b9b3..cbb0233a0 100644
--- a/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs
+++ b/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs
@@ -11,5 +11,7 @@ public sealed class TheMovieDbSettings : Ombi.Settings.Settings.Models.Settings
public List ExcludedMovieGenreIds { get; set; }
public List ExcludedTvGenreIds { get; set; }
+
+ public List OriginalLanguages { get; set; }
}
}
diff --git a/src/Ombi.Settings/Settings/Models/FeatureSettings.cs b/src/Ombi.Settings/Settings/Models/FeatureSettings.cs
index 6a285d422..9d0149e5d 100644
--- a/src/Ombi.Settings/Settings/Models/FeatureSettings.cs
+++ b/src/Ombi.Settings/Settings/Models/FeatureSettings.cs
@@ -20,5 +20,6 @@ public class FeatureEnablement
public static class FeatureNames
{
public const string Movie4KRequests = nameof(Movie4KRequests);
+ public const string OldTrendingSource = nameof(OldTrendingSource);
}
}
diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs
index 0681d9ca0..77298e719 100644
--- a/src/Ombi.Store/Context/OmbiContext.cs
+++ b/src/Ombi.Store/Context/OmbiContext.cs
@@ -212,7 +212,7 @@ public void Seed()
notificationToAdd = new NotificationTemplates
{
NotificationType = notificationType,
- Message = "Your TV request is now partially available! Season {PartiallyAvailableSeasonNumber} Episodes {PartiallyAvailableEpisodeNumbers}!",
+ Message = "Your TV request for {Title} is now partially available! Season {PartiallyAvailableSeasonNumber} Episodes {PartiallyAvailableEpisodeNumbers}!",
Subject = "{ApplicationName}: Partially Available Request!",
Agent = agent,
Enabled = true,
diff --git a/src/Ombi.Store/Repository/EmbyContentRepository.cs b/src/Ombi.Store/Repository/EmbyContentRepository.cs
index df88d8292..8f9904ebb 100644
--- a/src/Ombi.Store/Repository/EmbyContentRepository.cs
+++ b/src/Ombi.Store/Repository/EmbyContentRepository.cs
@@ -102,6 +102,13 @@ public override Task UpdateRange(IEnumerable existingConten
return InternalSaveChanges();
}
+ public override async Task DeleteTv(EmbyContent tv)
+ {
+ var episodesToDelete = GetAllEpisodes().Cast().Where(x => x.ParentId == tv.EmbyId).ToList();
+ Db.EmbyEpisode.RemoveRange(episodesToDelete);
+ await Delete(tv);
+ }
+
public override RecentlyAddedType RecentlyAddedType => RecentlyAddedType.Emby;
}
}
\ No newline at end of file
diff --git a/src/Ombi.Store/Repository/IMediaServerContentRepository.cs b/src/Ombi.Store/Repository/IMediaServerContentRepository.cs
index db4835a16..3f165b7e6 100644
--- a/src/Ombi.Store/Repository/IMediaServerContentRepository.cs
+++ b/src/Ombi.Store/Repository/IMediaServerContentRepository.cs
@@ -14,6 +14,7 @@ public interface IMediaServerContentRepository : IExternalRepository GetAllEpisodes();
Task Add(IMediaServerEpisode content);
Task AddRange(IEnumerable content);
+ Task DeleteTv(Content tv);
void UpdateWithoutSave(IMediaServerContent existingContent);
}
}
\ No newline at end of file
diff --git a/src/Ombi.Store/Repository/JellyfinContentRepository.cs b/src/Ombi.Store/Repository/JellyfinContentRepository.cs
index c3451da62..8dc729a6b 100644
--- a/src/Ombi.Store/Repository/JellyfinContentRepository.cs
+++ b/src/Ombi.Store/Repository/JellyfinContentRepository.cs
@@ -104,6 +104,13 @@ public override Task UpdateRange(IEnumerable existingConten
return InternalSaveChanges();
}
+ public override async Task DeleteTv(JellyfinContent tv)
+ {
+ var episodesToDelete = GetAllEpisodes().Cast().Where(x => x.ParentId == tv.JellyfinId).ToList();
+ Db.JellyfinEpisode.RemoveRange(episodesToDelete);
+ await Delete(tv);
+ }
+
public override RecentlyAddedType RecentlyAddedType => RecentlyAddedType.Jellyfin;
}
}
diff --git a/src/Ombi.Store/Repository/MediaServerRepository.cs b/src/Ombi.Store/Repository/MediaServerRepository.cs
index c1c7d4ec8..251fe3cea 100644
--- a/src/Ombi.Store/Repository/MediaServerRepository.cs
+++ b/src/Ombi.Store/Repository/MediaServerRepository.cs
@@ -22,5 +22,6 @@ public MediaServerContentRepository(ExternalContext db) : base(db)
public abstract Task AddRange(IEnumerable content);
public abstract void UpdateWithoutSave(IMediaServerContent existingContent);
public abstract Task UpdateRange(IEnumerable existingContent);
+ public abstract Task DeleteTv(T tv);
}
}
\ No newline at end of file
diff --git a/src/Ombi.Store/Repository/PlexContentRepository.cs b/src/Ombi.Store/Repository/PlexContentRepository.cs
index 96dfbe8e1..9f34af6a1 100644
--- a/src/Ombi.Store/Repository/PlexContentRepository.cs
+++ b/src/Ombi.Store/Repository/PlexContentRepository.cs
@@ -169,5 +169,12 @@ public override Task UpdateRange(IEnumerable existingConten
Db.PlexServerContent.UpdateRange((IEnumerable)existingContent);
return InternalSaveChanges();
}
+
+ public override Task DeleteTv(PlexServerContent tv)
+ {
+ // not used for now
+ // TODO: delete episodes, then delete series
+ throw new NotImplementedException();
+ }
}
}
\ No newline at end of file
diff --git a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs
index dc2e5525c..9b277c091 100644
--- a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs
+++ b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs
@@ -15,14 +15,16 @@ public interface IMovieDbApi
Task GetMovieInformation(int movieId);
Task GetMovieInformationWithExtraInfo(int movieId, string langCode = "en");
Task> NowPlaying(string languageCode, int? page = null);
+ Task> TrendingMovies(string languageCode, int? page = null);
Task> PopularMovies(string languageCode, int? page = null, CancellationToken cancellationToken = default(CancellationToken));
Task> PopularTv(string langCode, int? page = null, CancellationToken cancellationToken = default(CancellationToken));
Task> SearchMovie(string searchTerm, int? year, string languageCode);
Task> GetMoviesViaKeywords(string keywordId, string langCode, CancellationToken cancellationToken, int? page = null);
Task> SearchTv(string searchTerm, string year = default);
Task> TopRated(string languageCode, int? page = null);
- Task> Upcoming(string languageCode, int? page = null);
+ Task> UpcomingMovies(string languageCode, int? page = null);
Task> TopRatedTv(string languageCode, int? page = null);
+ Task> TrendingTv(string languageCode, int? page = null);
Task> UpcomingTv(string languageCode, int? page = null);
Task> SimilarMovies(int movieId, string langCode);
Task Find(string externalId, ExternalSource source);
@@ -41,7 +43,8 @@ public interface IMovieDbApi
Task GetMovieWatchProviders(int theMoviedbId, CancellationToken token);
Task GetTvWatchProviders(int theMoviedbId, CancellationToken token);
Task> GetGenres(string media, CancellationToken cancellationToken, string languageCode);
+ Task> GetLanguages(CancellationToken cancellationToken);
Task> SearchWatchProviders(string media, string searchTerm, CancellationToken cancellationToken);
- Task> AdvancedSearch(DiscoverModel model, CancellationToken cancellationToken);
+ Task> AdvancedSearch(DiscoverModel model, int page, CancellationToken cancellationToken);
}
}
diff --git a/src/Ombi.TheMovieDbApi/Models/Language.cs b/src/Ombi.TheMovieDbApi/Models/Language.cs
new file mode 100644
index 000000000..c6b14a654
--- /dev/null
+++ b/src/Ombi.TheMovieDbApi/Models/Language.cs
@@ -0,0 +1,14 @@
+using Newtonsoft.Json;
+
+namespace Ombi.TheMovieDbApi.Models
+{
+ public class Language
+ {
+ [JsonProperty("iso_639_1")]
+ public string Id { get; set; }
+ [JsonProperty("english_name")]
+ public string EnglishName { get; set; }
+ [JsonProperty("name")]
+ public string Name { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs
index 335ea7da3..055265701 100644
--- a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs
+++ b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs
@@ -70,11 +70,11 @@ public async Task> DiscoverMovies(string lan
- public async Task> AdvancedSearch(DiscoverModel model, CancellationToken cancellationToken)
+ public async Task> AdvancedSearch(DiscoverModel model, int page, CancellationToken cancellationToken)
{
var request = new Request($"discover/{model.Type}", BaseUri, HttpMethod.Get);
request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken);
- if(model.ReleaseYear.HasValue && model.ReleaseYear.Value > 1900)
+ if (model.ReleaseYear.HasValue && model.ReleaseYear.Value > 1900)
{
request.FullUri = request.FullUri.AddQueryParameter("year", model.ReleaseYear.Value.ToString());
}
@@ -92,6 +92,9 @@ public async Task> AdvancedSearch(DiscoverModel model,
}
//request.FullUri = request.FullUri.AddQueryParameter("sort_by", "popularity.desc");
+ request.AddQueryString("page", page.ToString());
+
+
var result = await Api.Request>(request, cancellationToken);
return Mapper.Map>(result.results);
}
@@ -139,7 +142,7 @@ public async Task GetActorMovieCredits(int actorId, string langCod
var result = await Api.Request(request);
return result;
}
-
+
public async Task GetActorTvCredits(int actorId, string langCode)
{
var request = new Request($"person/{actorId}/tv_credits", BaseUri, HttpMethod.Get);
@@ -282,21 +285,38 @@ private async Task> TopRated(string type, string langC
return Mapper.Map>(result.results);
}
- public Task> Upcoming(string langCode, int? page = null)
+ public Task> TrendingMovies(string langCode, int? page = null)
{
- return Upcoming("movie", langCode, page);
+ return Trending("movie", langCode, page);
}
- public Task> UpcomingTv(string langCode, int? page = null)
+
+ public Task> TrendingTv(string langCode, int? page = null)
{
- return Upcoming("tv", langCode, page);
+ return Trending("tv", langCode, page);
}
+ private async Task> Trending(string type, string langCode, int? page = null)
+ {
+ // https://developers.themoviedb.org/3/trending/get-trending
+ var timeWindow = "week"; // another option can be 'day'
+ var request = new Request($"trending/{type}/{timeWindow}", BaseUri, HttpMethod.Get);
+ request.AddQueryString("api_key", ApiToken);
+ request.AddQueryString("language", langCode);
+
+ if (page != null)
+ {
+ request.AddQueryString("page", page.ToString());
+ }
+ AddRetry(request);
+ var result = await Api.Request>(request);
+ return Mapper.Map>(result.results);
+ }
///
/// Maintains filter parity with /movie/upcoming.
///
- private async Task> Upcoming(string type, string langCode, int? page = null)
+ public async Task> UpcomingMovies(string langCode, int? page = null)
{
- var request = new Request($"discover/{type}", BaseUri, HttpMethod.Get);
+ var request = new Request($"discover/movie", BaseUri, HttpMethod.Get);
request.AddQueryString("api_key", ApiToken);
request.AddQueryString("language", langCode);
@@ -313,7 +333,27 @@ private async Task> Upcoming(string type, string langC
request.AddQueryString("page", page.ToString());
}
await AddDiscoverSettings(request);
- await AddGenreFilter(request, type);
+ await AddGenreFilter(request, "movie");
+ AddRetry(request);
+ var result = await Api.Request>(request);
+ return Mapper.Map>(result.results);
+ }
+ public async Task> UpcomingTv(string langCode, int? page = null)
+ {
+ var request = new Request($"discover/tv", BaseUri, HttpMethod.Get);
+ request.AddQueryString("api_key", ApiToken);
+ request.AddQueryString("language", langCode);
+
+ // Search for shows that will air in the next month
+ var startDate = DateTime.Today.AddDays(1);
+ request.AddQueryString($"first_air_date.gte", startDate.ToString("yyyy-MM-dd"));
+ request.AddQueryString($"first_air_date.lte", startDate.AddDays(30).ToString("yyyy-MM-dd"));
+ if (page != null)
+ {
+ request.AddQueryString("page", page.ToString());
+ }
+ await AddDiscoverSettings(request);
+ await AddGenreFilter(request, "tv");
AddRetry(request);
var result = await Api.Request>(request);
return Mapper.Map>(result.results);
@@ -376,8 +416,8 @@ public async Task> GetMoviesViaKeywords(string keyword
request.AddQueryString("language", langCode);
request.AddQueryString("sort_by", "vote_average.desc");
- request.AddQueryString("with_keywords", keywordId);
-
+ request.AddQueryString("with_keywords", keywordId);
+
// `vote_count` consideration isn't explicitly documented, but using only the `sort_by` filter
// does not provide the same results as `/movie/top_rated`. This appears to be adequate enough
// to filter out extremely high-rated movies due to very little votes
@@ -438,6 +478,16 @@ public async Task> GetGenres(string media, CancellationToken cancell
return result.genres ?? new List();
}
+ public async Task> GetLanguages(CancellationToken cancellationToken)
+ {
+ var request = new Request($"/configuration/languages", BaseUri, HttpMethod.Get);
+ request.AddQueryString("api_key", ApiToken);
+ AddRetry(request);
+
+ var result = await Api.Request>(request, cancellationToken);
+ return result ?? new List();
+ }
+
public Task> MultiSearch(string searchTerm, string languageCode, CancellationToken cancellationToken)
{
var request = new Request("search/multi", BaseUri, HttpMethod.Get);
@@ -472,6 +522,10 @@ private async Task AddDiscoverSettings(Request request)
{
request.AddQueryString("without_keywords", string.Join(",", settings.ExcludedKeywordIds));
}
+ if (settings.OriginalLanguages?.Any() == true)
+ {
+ request.AddQueryString("with_original_language", string.Join("|", settings.OriginalLanguages));
+ }
}
private async Task AddGenreFilter(Request request, string media_type)
@@ -479,7 +533,8 @@ private async Task AddGenreFilter(Request request, string media_type)
var settings = await Settings;
List excludedGenres;
- switch (media_type) {
+ switch (media_type)
+ {
case "tv":
excludedGenres = settings.ExcludedTvGenreIds;
break;
diff --git a/src/Ombi/.vscode/launch.json b/src/Ombi/.vscode/launch.json
index 642e584c5..9b6838630 100644
--- a/src/Ombi/.vscode/launch.json
+++ b/src/Ombi/.vscode/launch.json
@@ -6,7 +6,7 @@
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
- "program": "${workspaceFolder}/bin/Debug/net5.0/ombi.dll",
+ "program": "${workspaceFolder}/bin/Debug/net6.0/ombi.dll",
"args": ["--host", "http://localhost:3577"],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
@@ -47,4 +47,4 @@
}
},
]
- }
\ No newline at end of file
+ }
diff --git a/src/Ombi/ClientApp/.storybook/main.js b/src/Ombi/ClientApp/.storybook/main.js
new file mode 100644
index 000000000..3f1f26236
--- /dev/null
+++ b/src/Ombi/ClientApp/.storybook/main.js
@@ -0,0 +1,19 @@
+module.exports = {
+ "stories": [
+ "../src/**/*.stories.mdx",
+ "../src/**/*.stories.@(js|jsx|ts|tsx)"
+ ],
+ "addons": [
+ "@storybook/addon-links",
+ "@storybook/addon-essentials",
+ "@storybook/addon-interactions"
+ ],
+ "framework": "@storybook/angular",
+ "core": {
+ "builder": "@storybook/builder-webpack5"
+ },
+ "staticDirs": [{from :'../../wwwroot/images', to: 'images'}],
+ "features": {
+ interactionsDebugger: true,
+ }
+}
\ No newline at end of file
diff --git a/src/Ombi/ClientApp/.storybook/preview-body.html b/src/Ombi/ClientApp/.storybook/preview-body.html
new file mode 100644
index 000000000..b043609bf
--- /dev/null
+++ b/src/Ombi/ClientApp/.storybook/preview-body.html
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/src/Ombi/ClientApp/.storybook/preview.js b/src/Ombi/ClientApp/.storybook/preview.js
new file mode 100644
index 000000000..a20381a89
--- /dev/null
+++ b/src/Ombi/ClientApp/.storybook/preview.js
@@ -0,0 +1,14 @@
+import { setCompodocJson } from "@storybook/addon-docs/angular";
+import docJson from "../documentation.json";
+setCompodocJson(docJson);
+
+export const parameters = {
+ actions: { argTypesRegex: "^on[A-Z].*" },
+ controls: {
+ matchers: {
+ color: /(background|color)$/i,
+ date: /Date$/,
+ },
+ },
+ docs: { inlineStories: true },
+}
\ No newline at end of file
diff --git a/src/Ombi/ClientApp/.storybook/tsconfig.json b/src/Ombi/ClientApp/.storybook/tsconfig.json
new file mode 100644
index 000000000..54887e29c
--- /dev/null
+++ b/src/Ombi/ClientApp/.storybook/tsconfig.json
@@ -0,0 +1,24 @@
+{
+ "extends": "../src/tsconfig.json",
+ "compilerOptions": {
+ "types": [
+ "node"
+ ],
+ "typeRoots": [
+ "../node_modules/@typings"
+ ],
+ "allowSyntheticDefaultImports": true
+ },
+ "exclude": [
+ "../src/test.ts",
+ "../src/**/*.spec.ts",
+ "../projects/**/*.spec.ts"
+ ],
+ "include": [
+ "../src/**/*",
+ "../projects/**/*"
+ ],
+ "files": [
+ "./typings.d.ts"
+ ]
+}
diff --git a/src/Ombi/ClientApp/.storybook/typings.d.ts b/src/Ombi/ClientApp/.storybook/typings.d.ts
new file mode 100644
index 000000000..f73d61b39
--- /dev/null
+++ b/src/Ombi/ClientApp/.storybook/typings.d.ts
@@ -0,0 +1,4 @@
+declare module '*.md' {
+ const content: string;
+ export default content;
+}
diff --git a/src/Ombi/ClientApp/angular.json b/src/Ombi/ClientApp/angular.json
index 066a75be5..d50a19844 100644
--- a/src/Ombi/ClientApp/angular.json
+++ b/src/Ombi/ClientApp/angular.json
@@ -19,7 +19,7 @@
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
- "tsConfig": "src/tsconfig.app.json",
+ "tsConfig": "src/tsconfig.json",
"assets": [
"src/assets"
],
@@ -114,7 +114,7 @@
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
- "src/tsconfig.app.json"
+ "src/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
@@ -124,7 +124,6 @@
}
}
},
- "defaultProject": "ombi",
"cli": {
"analytics": false
}
diff --git a/src/Ombi/ClientApp/documentation.json b/src/Ombi/ClientApp/documentation.json
new file mode 100644
index 000000000..901f0d264
--- /dev/null
+++ b/src/Ombi/ClientApp/documentation.json
@@ -0,0 +1,18 @@
+{
+ "pipes": [],
+ "interfaces": [],
+ "injectables": [],
+ "guards": [],
+ "interceptors": [],
+ "classes": [],
+ "directives": [],
+ "components": [],
+ "modules": [],
+ "miscellaneous": [],
+ "routes": [],
+ "coverage": {
+ "count": 0,
+ "status": "low",
+ "files": []
+ }
+}
\ No newline at end of file
diff --git a/src/Ombi/ClientApp/package.json b/src/Ombi/ClientApp/package.json
index 80a9842b4..a2271f2bc 100644
--- a/src/Ombi/ClientApp/package.json
+++ b/src/Ombi/ClientApp/package.json
@@ -4,37 +4,40 @@
"scripts": {
"ng": "ng",
"start": "ng serve --port 3578 --configuration hmr",
- "build": "node --max_old_space_size=6144 node_modules/@angular/cli/bin/ng build --prod",
- "lint": "ng lint"
+ "build": "node --max_old_space_size=6144 node_modules/@angular/cli/bin/ng build -c production",
+ "lint": "ng lint",
+ "docs:json": "compodoc -p ./tsconfig.json -e json -d .",
+ "storybook": "start-storybook -p 6006",
+ "chromatic": "chromatic --exit-zero-on-changes",
+ "storybookbuild": "yarn build-storybook"
},
"private": true,
"dependencies": {
- "@angular/animations": "^13.2.0",
+ "@angular/animations": "^14.0.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/common": "^14.0.0",
+ "@angular/compiler": "^14.0.0",
+ "@angular/core": "^14.0.0",
+ "@angular/forms": "^14.0.0",
+ "@angular/localize": "^14.0.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",
+ "@angular/platform-browser": "^14.0.0",
+ "@angular/platform-browser-dynamic": "^14.0.0",
+ "@angular/platform-server": "^14.0.0",
+ "@angular/router": "^14.0.0",
"@angularclass/hmr": "^3.0.0",
- "@aspnet/signalr": "^1.1.0",
"@auth0/angular-jwt": "^5.0.2",
"@fortawesome/fontawesome-free": "^6.0.0",
"@fullcalendar/core": "^4.2.0",
"@fullcalendar/daygrid": "^4.4.0",
"@fullcalendar/interaction": "^4.2.0",
+ "@microsoft/signalr": "^6.0.7",
"@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": "^13.0.3",
"bootstrap": "^4.2.1",
@@ -48,34 +51,52 @@
"moment": "^2.29.1",
"ng2-cookies": "^1.0.12",
"ngx-clipboard": "^12.1.0",
- "ngx-infinite-scroll": "^9.0.0",
+ "ngx-infinite-scroll": "^14.0.0",
"ngx-moment": "^3.0.1",
"ngx-order-pipe": "^2.2.0",
"popper.js": "^1.14.3",
"primeicons": "^5.0.0",
"primeng": "^13.2.0",
+ "protractor": "~5.4.0",
"rxjs": "^7.5.4",
"sass-recursive-map-merge": "^1.0.1",
"store": "^2.0.12",
"ts-md5": "^1.2.7",
+ "ts-node": "~5.0.1",
"tslib": "^1.10.0",
+ "tslint": "^5.12.0",
"tslint-angular": "^1.1.2",
"zone.js": "~0.11.4"
},
"devDependencies": {
- "@angular-devkit/build-angular": "~13.2.0",
- "@angular/cli": "~13.2.0",
- "@angular/compiler-cli": "^13.2.0",
- "@angular/language-service": "^13.2.0",
+ "@angular-devkit/build-angular": "^14.0.0",
+ "@angular/cli": "^14.0.0",
+ "@angular/compiler-cli": "^14.0.0",
+ "@angular/language-service": "^14.0.0",
+ "@babel/core": "^7.18.9",
+ "@compodoc/compodoc": "^1.1.19",
+ "@storybook/addon-actions": "^6.5.9",
+ "@storybook/addon-essentials": "^6.5.9",
+ "@storybook/addon-interactions": "^6.5.9",
+ "@storybook/addon-links": "^6.5.9",
+ "@storybook/angular": "^6.5.9",
+ "@storybook/builder-webpack5": "^6.5.9",
+ "@storybook/jest": "^0.0.10",
+ "@storybook/manager-webpack5": "^6.5.9",
+ "@storybook/testing-library": "^0.0.13",
"@types/jasmine": "~3.6.7",
"@types/jasminewd2": "~2.0.8",
- "@types/node": "^16.10.9",
+ "@types/node": "^16.11.45",
+ "babel-loader": "^8.2.5",
+ "chromatic": "^6.7.1",
"codelyzer": "^6.0.1",
- "typescript": "~4.5.5"
+ "typescript": "~4.7.3"
},
"optionalDependencies": {
"protractor": "~5.4.0",
"ts-node": "~5.0.1",
"tslint": "^5.12.0"
- }
+ },
+ "readme": "ERROR: No README data found!",
+ "_id": "ombi@3.0.0"
}
diff --git a/src/Ombi/ClientApp/src/app/app.module.ts b/src/Ombi/ClientApp/src/app/app.module.ts
index 735dce36b..24644d1df 100644
--- a/src/Ombi/ClientApp/src/app/app.module.ts
+++ b/src/Ombi/ClientApp/src/app/app.module.ts
@@ -1,5 +1,4 @@
import { APP_BASE_HREF, CommonModule, PlatformLocation } from "@angular/common";
-import { CardsFreeModule, MDBBootstrapModule, NavbarModule } from "angular-bootstrap-md";
import { CustomPageService, ImageService, RequestService, SettingsService } from "./services";
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { HTTP_INTERCEPTORS, HttpClient, HttpClientModule } from "@angular/common/http";
@@ -69,6 +68,7 @@ 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 { ImageBackgroundComponent, ImageComponent } from "./components/";
import { environment } from "../environments/environment";
const routes: Routes = [
@@ -131,7 +131,6 @@ export function JwtTokenGetter() {
MatSnackBarModule,
DialogModule,
MatButtonModule,
- NavbarModule,
MatCardModule,
MatTooltipModule,
MatMenuModule,
@@ -145,11 +144,9 @@ export function JwtTokenGetter() {
ConfirmDialogModule,
OverlayPanelModule,
CommonModule,
- CardsFreeModule,
OverlayModule,
MatCheckboxModule,
MatProgressSpinnerModule,
- MDBBootstrapModule.forRoot(),
JwtModule.forRoot({
config: {
tokenGetter: JwtTokenGetter,
@@ -170,7 +167,9 @@ export function JwtTokenGetter() {
...environment.production ? [] :
[
NgxsReduxDevtoolsPluginModule.forRoot(),
- ]
+ ],
+ ImageBackgroundComponent,
+ ImageComponent,
],
declarations: [
AppComponent,
diff --git a/src/Ombi/ClientApp/src/app/components/image-background/image-background.component.html b/src/Ombi/ClientApp/src/app/components/image-background/image-background.component.html
new file mode 100644
index 000000000..97fff3671
--- /dev/null
+++ b/src/Ombi/ClientApp/src/app/components/image-background/image-background.component.html
@@ -0,0 +1,6 @@
+
\ No newline at end of file
diff --git a/src/Ombi/ClientApp/src/app/components/image-background/image-background.component.scss b/src/Ombi/ClientApp/src/app/components/image-background/image-background.component.scss
new file mode 100644
index 000000000..177a22d01
--- /dev/null
+++ b/src/Ombi/ClientApp/src/app/components/image-background/image-background.component.scss
@@ -0,0 +1,26 @@
+.login-gradient-bar{
+ background: linear-gradient(-10deg, transparent 20%, rgba(0,0,0,0.6) 20.0%, rgba(0,0,0,0.6) 80.0%, transparent 60%),transparent;
+ height:100%;
+ width:100%;
+ position: absolute;
+}
+
+.bg {
+ background-position: center center;
+ background-repeat: no-repeat;
+ background-attachment: fixed;
+ background-size: cover;
+ height: 100vh;
+ width: 100vw;
+ position: fixed;
+}
+
+.poster-desc {
+ padding-left: 1%;
+ color: white;
+ height: 100vh;
+ width: 100vw;
+ display: flex;
+ justify-content: end;
+ flex-direction: column;
+}
\ No newline at end of file
diff --git a/src/Ombi/ClientApp/src/app/components/image-background/image-background.component.ts b/src/Ombi/ClientApp/src/app/components/image-background/image-background.component.ts
new file mode 100644
index 000000000..ebd228d85
--- /dev/null
+++ b/src/Ombi/ClientApp/src/app/components/image-background/image-background.component.ts
@@ -0,0 +1,43 @@
+import { OmbiCommonModules } from "../modules";
+import { Component, OnDestroy, OnInit } from "@angular/core";
+import { DomSanitizer } from "@angular/platform-browser";
+import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
+import { ImageService } from "../../services";
+import { fadeInOutAnimation } from "app/animations/fadeinout";
+
+@Component({
+ standalone: true,
+ selector: 'ombi-image-background',
+ templateUrl: './image-background.component.html',
+ styleUrls: ['./image-background.component.scss'],
+ imports: [...OmbiCommonModules, BrowserAnimationsModule],
+ providers: [ ImageService ],
+ animations: [ fadeInOutAnimation ],
+ })
+ export class ImageBackgroundComponent implements OnInit, OnDestroy {
+
+ public background: any;
+ public name: string;
+ private timer: NodeJS.Timer;
+
+ constructor(private images: ImageService, private sanitizer: DomSanitizer) { }
+
+ public ngOnDestroy(): void {
+ clearTimeout(this.timer);
+ }
+
+ public ngOnInit(): void {
+ this.cycleBackground();
+
+ this.timer = setInterval(() => {
+ this.cycleBackground();
+ }, 30000);
+ }
+
+ private cycleBackground() {
+ this.images.getRandomBackgroundWithInfo().subscribe((x) => {
+ this.background = this.sanitizer.bypassSecurityTrustStyle("url(" + x.url + ")");
+ this.name = x.name;
+ });
+ }
+ }
\ No newline at end of file
diff --git a/src/Ombi/ClientApp/src/app/components/image/image.component.html b/src/Ombi/ClientApp/src/app/components/image/image.component.html
new file mode 100644
index 000000000..9ee9d7d19
--- /dev/null
+++ b/src/Ombi/ClientApp/src/app/components/image/image.component.html
@@ -0,0 +1 @@
+
diff --git a/src/Ombi/ClientApp/src/app/components/image/image.component.stories.ts b/src/Ombi/ClientApp/src/app/components/image/image.component.stories.ts
new file mode 100644
index 000000000..b6f7b21fc
--- /dev/null
+++ b/src/Ombi/ClientApp/src/app/components/image/image.component.stories.ts
@@ -0,0 +1,73 @@
+// also exported from '@storybook/angular' if you can deal with breaking changes in 6.1
+import { APP_BASE_HREF } from '@angular/common';
+import { Story, Meta, moduleMetadata } from '@storybook/angular';
+import { RequestType } from '../../interfaces';
+import { ImageComponent } from './image.component';
+
+// More on default export: https://storybook.js.org/docs/angular/writing-stories/introduction#default-export
+export default {
+ title: 'Image Component',
+ component: ImageComponent,
+ decorators: [
+ moduleMetadata({
+ providers: [
+ {
+ provide: APP_BASE_HREF,
+ useValue: ""
+ },
+ ]
+ })
+ ]
+} as Meta;
+
+// More on component templates: https://storybook.js.org/docs/angular/writing-stories/introduction#using-args
+const Template: Story = (args: ImageComponent) => ({
+ props: args,
+});
+
+export const Primary = Template.bind({});
+// More on args: https://storybook.js.org/docs/angular/writing-stories/args
+Primary.args = {
+ src: 'https://ombi.io/img/logo-orange-small.png',
+ type: RequestType.movie
+};
+
+export const ClassApplied = Template.bind({});
+ClassApplied.args = {
+ src: 'https://ombi.io/img/logo-orange-small.png',
+ type: RequestType.movie,
+ class: 'test-class'
+};
+
+export const StyleApplied = Template.bind({});
+StyleApplied.args = {
+ src: 'https://ombi.io/img/logo-orange-small.png',
+ type: RequestType.movie,
+ style: 'background-color: red;'
+};
+
+export const IdApplied = Template.bind({});
+IdApplied.args = {
+ src: 'https://ombi.io/img/logo-orange-small.png',
+ type: RequestType.movie,
+ id: 'testId123'
+};
+
+// export const InvalidMovieImage = Template.bind({});
+// InvalidMovieImage.args = {
+// src: 'https://httpstat.us/429',
+// type: RequestType.movie,
+// id: 'testId123'
+// };
+
+// export const InvalidTvImage = Template.bind({});
+// InvalidTvImage.args = {
+// src: 'https://httpstat.us/429',
+// type: RequestType.tvShow,
+// };
+
+// export const InvalidMusicImage = Template.bind({});
+// InvalidMusicImage.args = {
+// src: 'https://httpstat.us/429',
+// type: RequestType.album,
+// };
diff --git a/src/Ombi/ClientApp/src/app/components/image/image.component.ts b/src/Ombi/ClientApp/src/app/components/image/image.component.ts
new file mode 100644
index 000000000..57099016a
--- /dev/null
+++ b/src/Ombi/ClientApp/src/app/components/image/image.component.ts
@@ -0,0 +1,57 @@
+import { OmbiCommonModules } from "../modules";
+import { ChangeDetectionStrategy, Component, ElementRef, Inject, Input, ViewEncapsulation } from "@angular/core";
+import { RequestType } from "../../interfaces";
+import { APP_BASE_HREF } from "@angular/common";
+
+@Component({
+ standalone: true,
+ selector: 'ombi-image',
+ imports: [...OmbiCommonModules],
+ encapsulation: ViewEncapsulation.None,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ templateUrl: './image.component.html',
+ })
+ export class ImageComponent {
+
+ @Input() public src: string;
+ @Input() public type: RequestType;
+
+ // Attributes from the parent
+ @Input() public class: string;
+ @Input() public id: string;
+ @Input() public alt: string;
+ @Input() public style: string;
+
+ public baseUrl: string = "";
+
+ public defaultTv = "/images/default_tv_poster.png";
+ private defaultMovie = "/images/default_movie_poster.png";
+ private defaultMusic = "i/mages/default-music-placeholder.png";
+
+ constructor (@Inject(APP_BASE_HREF) public href: string) {
+ if (this.href.length > 1) {
+ this.baseUrl = this.href;
+ }
+ }
+
+ public onError(event: any) {
+ // set to a placeholder
+ switch(this.type) {
+ case RequestType.movie:
+ event.target.src = this.baseUrl + this.defaultMovie;
+ break;
+ case RequestType.tvShow:
+ event.target.src = this.baseUrl + this.defaultTv;
+ break;
+ case RequestType.album:
+ event.target.src = this.baseUrl + this.defaultMusic;
+ break;
+ }
+
+ // Retry the original image
+ const timeout = setTimeout(() => {
+ event.target.src = this.src;
+ clearTimeout(timeout);
+ }, Math.floor(Math.random() * (7000 - 1000 + 1)) + 1000);
+ }
+ }
\ No newline at end of file
diff --git a/src/Ombi/ClientApp/src/app/components/index.ts b/src/Ombi/ClientApp/src/app/components/index.ts
new file mode 100644
index 000000000..092f6504b
--- /dev/null
+++ b/src/Ombi/ClientApp/src/app/components/index.ts
@@ -0,0 +1,2 @@
+export * from "./image-background/image-background.component";
+export * from "./image/image.component";
\ No newline at end of file
diff --git a/src/Ombi/ClientApp/src/app/components/modules.ts b/src/Ombi/ClientApp/src/app/components/modules.ts
new file mode 100644
index 000000000..1bf5697e6
--- /dev/null
+++ b/src/Ombi/ClientApp/src/app/components/modules.ts
@@ -0,0 +1,3 @@
+import { CommonModule } from "@angular/common";
+
+export const OmbiCommonModules = [ CommonModule ];
\ No newline at end of file
diff --git a/src/Ombi/ClientApp/src/app/custompage/custompage.component.ts b/src/Ombi/ClientApp/src/app/custompage/custompage.component.ts
index 61094e793..37e2dce77 100644
--- a/src/Ombi/ClientApp/src/app/custompage/custompage.component.ts
+++ b/src/Ombi/ClientApp/src/app/custompage/custompage.component.ts
@@ -1,5 +1,5 @@
import { Component, OnInit, SecurityContext } from "@angular/core";
-import { FormBuilder, FormGroup, Validators } from "@angular/forms";
+import { UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms";
import { DomSanitizer } from "@angular/platform-browser";
import { AuthService } from "../auth/auth.service";
import { CustomPageService, NotificationService } from "../services";
@@ -10,11 +10,11 @@ import { CustomPageService, NotificationService } from "../services";
})
export class CustomPageComponent implements OnInit {
- public form: FormGroup;
+ public form: UntypedFormGroup;
public isEditing: boolean;
public isAdmin: boolean;
- constructor(private auth: AuthService, private settings: CustomPageService, private fb: FormBuilder,
+ constructor(private auth: AuthService, private settings: CustomPageService, private fb: UntypedFormBuilder,
private notificationService: NotificationService,
private sanitizer: DomSanitizer) {
}
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 9ca607082..a479b5072 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
@@ -2,15 +2,14 @@
-
+
{{ 'Common.' + RequestType[result.type] | translate }}
{{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 5fe422fd7..6a7911257 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
@@ -83,7 +83,7 @@ small {
}
-.image {
+::ng-deep .image {
border-radius: 10px;
opacity: 1;
display: block;
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 559a962b5..d5557c0b5 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
@@ -169,6 +169,19 @@ export class DiscoverCardComponent implements OnInit {
}
}
+ public onImageError(event: any) {
+ const originalSrc = event.target.src;
+
+ // set to a placeholder
+ event.target.src = "../../../images/default_movie_poster.png";
+
+ // Retry the original image
+ const timeout = setTimeout(() => {
+ event.target.src = originalSrc;
+ clearTimeout(timeout);
+ }, Math.floor(Math.random() * (7000 - 1000 + 1)) + 1000);
+ }
+
private getExtraMovieInfo() {
if (!this.result.imdbid) {
this.searchService.getFullMovieDetails(+this.result.id)
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 9617c993e..43cde5036 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
@@ -48,6 +48,7 @@ export class CarouselListComponent implements OnInit {
constructor(private searchService: SearchV2Service,
private storageService: StorageService,
private featureFacade: FeaturesFacade) {
+ Carousel.prototype.onTouchMove = () => { },
this.responsiveOptions = [
{
breakpoint: '4000px',
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 b1911ceee..97ff038a0 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
@@ -2,7 +2,13 @@
- 0" class="row full-height discoverResults col" >
+
+ 0"
+ class="row full-height discoverResults col"
+ infiniteScroll
+ [infiniteScrollDistance]="3"
+ [infiniteScrollThrottle]="200"
+ (scrolled)="onScroll()">
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 a8544365d..295902927 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
@@ -29,6 +29,7 @@ export class DiscoverSearchResultsComponent implements OnInit {
public filter: SearchFilter;
private isAdvancedSearch: boolean;
+ private loadPosition: number = 30;
constructor(private searchService: SearchV2Service,
private route: ActivatedRoute,
@@ -65,7 +66,7 @@ export class DiscoverSearchResultsComponent implements OnInit {
}
});
- if (this.advancedDataService) {
+ if (this.isAdvancedSearch) {
return;
}
this.loadingFlag = true;
@@ -179,6 +180,31 @@ export class DiscoverSearchResultsComponent implements OnInit {
});
}
+ public onScroll() {
+ console.log("scrolled");
+ if (this.advancedDataService) {
+ this.loadMoreAdvancedSearch();
+ return;
+ }
+ }
+
+ private loadMoreAdvancedSearch() {
+ const advancedOptions = this.advancedDataService.getOptions();
+
+ this.searchService.advancedSearch({
+ type: advancedOptions.type == RequestType.movie ? "movie" : "tv",
+ companies: advancedOptions.companies,
+ genreIds: advancedOptions.genres,
+ keywordIds : advancedOptions.keywords,
+ releaseYear: advancedOptions.releaseYear,
+ watchProviders: advancedOptions.watchProviders,
+ }, this.loadPosition, 30).then(x => {
+
+ this.loadPosition += 30;
+ this.mapAdvancedData(x);
+ });
+ }
+
private async search() {
this.clear();
this.results = await this.searchService
diff --git a/src/Ombi/ClientApp/src/app/discover/discover.module.ts b/src/Ombi/ClientApp/src/app/discover/discover.module.ts
index 414c881e6..eade4e451 100644
--- a/src/Ombi/ClientApp/src/app/discover/discover.module.ts
+++ b/src/Ombi/ClientApp/src/app/discover/discover.module.ts
@@ -8,6 +8,7 @@ import { PipeModule } from "../pipes/pipe.module";
import { RouterModule } from "@angular/router";
import { SharedModule } from "../shared/shared.module";
import { SkeletonModule } from 'primeng/skeleton';
+import { ImageComponent } from 'app/components';
@NgModule({
imports: [
@@ -18,6 +19,7 @@ import { SkeletonModule } from 'primeng/skeleton';
MatButtonToggleModule,
InfiniteScrollModule,
SkeletonModule,
+ ImageComponent
],
declarations: [
...fromComponents.components
diff --git a/src/Ombi/ClientApp/src/app/interfaces/IImages.ts b/src/Ombi/ClientApp/src/app/interfaces/IImages.ts
index 0c73df490..baa1a9829 100644
--- a/src/Ombi/ClientApp/src/app/interfaces/IImages.ts
+++ b/src/Ombi/ClientApp/src/app/interfaces/IImages.ts
@@ -1,3 +1,7 @@
export interface IImages {
url: string;
}
+export interface IImagesInfo {
+ url: string;
+ name: string;
+}
diff --git a/src/Ombi/ClientApp/src/app/interfaces/IMovieDb.ts b/src/Ombi/ClientApp/src/app/interfaces/IMovieDb.ts
index f82225434..77352de4b 100644
--- a/src/Ombi/ClientApp/src/app/interfaces/IMovieDb.ts
+++ b/src/Ombi/ClientApp/src/app/interfaces/IMovieDb.ts
@@ -17,3 +17,8 @@ export interface IDiscoverModel {
watchProviders?: number[];
companies?: number[];
}
+export interface ILanguage {
+ iso_639_1 : string;
+ english_name : string;
+ name : string;
+}
diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts
index 95b1fba00..4594d2a2f 100644
--- a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts
+++ b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts
@@ -339,7 +339,8 @@ export interface ITheMovieDbSettings extends ISettings {
showAdultMovies: boolean;
excludedKeywordIds: number[];
excludedMovieGenreIds: number[];
- excludedTvGenreIds: number[]
+ excludedTvGenreIds: number[];
+ originalLanguages: string[];
}
export interface IUpdateModel
diff --git a/src/Ombi/ClientApp/src/app/issues/issuestable.component.html b/src/Ombi/ClientApp/src/app/issues/issuestable.component.html
index 8e22d3e51..99b297b60 100644
--- a/src/Ombi/ClientApp/src/app/issues/issuestable.component.html
+++ b/src/Ombi/ClientApp/src/app/issues/issuestable.component.html
@@ -14,7 +14,7 @@
|
-
+ {{ 'Issues.Details' | translate}}
|
diff --git a/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.html b/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.html
index abad6473f..3b8a46db7 100644
--- a/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.html
+++ b/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.html
@@ -1,5 +1,5 @@
-
-
+
+
diff --git a/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.scss b/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.scss
index 7eb4a4b3c..4c6e7ea9a 100644
--- a/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.scss
+++ b/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.scss
@@ -26,15 +26,6 @@ div.centered {
transform: translate(-50%, -50%);
}
-div.bg {
- background-position: center center;
- background-repeat: no-repeat;
- background-attachment: fixed;
- background-size: cover;
- height: 100vh;
- width: 100vw;
- position: fixed;
-}
.online{
color:lightgreen;
diff --git a/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.ts b/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.ts
index 33f8873f8..e2758b146 100644
--- a/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.ts
+++ b/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.ts
@@ -1,48 +1,34 @@
-import { PlatformLocation, APP_BASE_HREF } from "@angular/common";
-import { Component, OnDestroy, OnInit, Inject } from "@angular/core";
+import { APP_BASE_HREF } from "@angular/common";
+import { Component, OnInit, Inject } from "@angular/core";
import { IMediaServerStatus } from "../interfaces";
import { ICustomizationSettings, ILandingPageSettings } from "../interfaces";
import { LandingPageService } from "../services";
import { SettingsService } from "../services";
-import { DomSanitizer } from "@angular/platform-browser";
-import { ImageService } from "../services";
-
-import { fadeInOutAnimation } from "../animations/fadeinout";
import { CustomizationFacade } from "../state/customization";
-import { ThousandShortPipe } from "../pipes/ThousandShortPipe";
@Component({
templateUrl: "./landingpage.component.html",
- animations: [fadeInOutAnimation],
styleUrls: ["./landingpage.component.scss"],
})
-export class LandingPageComponent implements OnDestroy, OnInit {
+export class LandingPageComponent implements OnInit {
public customizationSettings: ICustomizationSettings;
public landingPageSettings: ILandingPageSettings;
- public background: any;
public mediaServerStatus: IMediaServerStatus;
public baseUrl: string;
- private timer: any;
private href: string;
constructor(private settingsService: SettingsService,
- private images: ImageService, private sanitizer: DomSanitizer, private landingPageService: LandingPageService,
+ private landingPageService: LandingPageService,
private customizationFacade: CustomizationFacade,
@Inject(APP_BASE_HREF) href :string) { this.href = href }
public ngOnInit() {
this.customizationFacade.settings$().subscribe(x => this.customizationSettings = x);
this.settingsService.getLandingPage().subscribe(x => this.landingPageSettings = x);
- this.images.getRandomBackground().subscribe(x => {
- this.background = this.sanitizer.bypassSecurityTrustStyle("linear-gradient(-10deg, transparent 19%, rgba(0,0,0,0.7) 20.0%, rgba(0,0,0,0.7) 79%, transparent 80%), url(" + x.url + ")");
- });
- this.timer = setInterval(() => {
- this.cycleBackground();
- }, 30000);
const base = this.href;
if (base.length > 1) {
@@ -53,18 +39,4 @@ export class LandingPageComponent implements OnDestroy, OnInit {
this.mediaServerStatus = x;
});
}
-
- public ngOnDestroy() {
- clearInterval(this.timer);
- }
-
- public cycleBackground() {
- this.images.getRandomBackground().subscribe(x => {
- this.background = "";
- });
- this.images.getRandomBackground().subscribe(x => {
- this.background = this.sanitizer
- .bypassSecurityTrustStyle("linear-gradient(-10deg, transparent 20%, rgba(0,0,0,0.7) 20.0%, rgba(0,0,0,0.7) 80.0%, transparent 80%), url(" + x.url + ")");
- });
- }
}
diff --git a/src/Ombi/ClientApp/src/app/login/login.component.html b/src/Ombi/ClientApp/src/app/login/login.component.html
index c0932999b..71caa80b4 100644
--- a/src/Ombi/ClientApp/src/app/login/login.component.html
+++ b/src/Ombi/ClientApp/src/app/login/login.component.html
@@ -1,7 +1,4 @@
-
+
diff --git a/src/Ombi/ClientApp/src/app/login/login.component.scss b/src/Ombi/ClientApp/src/app/login/login.component.scss
index 4ad645dd8..df368ee0c 100644
--- a/src/Ombi/ClientApp/src/app/login/login.component.scss
+++ b/src/Ombi/ClientApp/src/app/login/login.component.scss
@@ -11,23 +11,6 @@ img.center {
max-width: 100%;
}
-.login-gradient-bar{
- background: linear-gradient(-10deg, transparent 20%, rgba(0,0,0,0.6) 20.0%, rgba(0,0,0,0.6) 80.0%, transparent 60%),transparent;
- height:100%;
- width:100%;
- position: absolute;
-}
-
-div.bg {
- background-position: center center;
- background-repeat: no-repeat;
- background-attachment: fixed;
- background-size: cover;
- height: 100vh;
- width: 100vw;
- position: fixed;
-}
-
.card-container.card {
max-width: 500px;
padding: 45px 45px;
diff --git a/src/Ombi/ClientApp/src/app/login/login.component.ts b/src/Ombi/ClientApp/src/app/login/login.component.ts
index f6f519191..6e8efc00b 100644
--- a/src/Ombi/ClientApp/src/app/login/login.component.ts
+++ b/src/Ombi/ClientApp/src/app/login/login.component.ts
@@ -1,5 +1,5 @@
import { Component, OnDestroy, OnInit, Inject } from "@angular/core";
-import { FormBuilder, FormGroup, Validators } from "@angular/forms";
+import { UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms";
import { ActivatedRoute, Router } from "@angular/router";
import { TranslateService } from "@ngx-translate/core";
@@ -10,25 +10,19 @@ import { PlexTvService } from "../services";
import { SettingsService } from "../services";
import { StatusService } from "../services";
-import { DomSanitizer } from "@angular/platform-browser";
-import { ImageService } from "../services";
-
-import { fadeInOutAnimation } from "../animations/fadeinout";
import { StorageService } from "../shared/storage/storage-service";
import { MatSnackBar } from "@angular/material/snack-bar";
import { CustomizationFacade } from "../state/customization";
@Component({
templateUrl: "./login.component.html",
- animations: [fadeInOutAnimation],
styleUrls: ["./login.component.scss"],
})
export class LoginComponent implements OnDestroy, OnInit {
- public form: FormGroup;
+ public form: UntypedFormGroup;
public customizationSettings: ICustomizationSettings;
public authenticationSettings: IAuthenticationSettings;
public plexEnabled: boolean;
- public background: any;
public landingFlag: boolean;
public baseUrl: string;
public loginWithOmbi: boolean;
@@ -46,7 +40,6 @@ export class LoginComponent implements OnDestroy, OnInit {
public get appNameTranslate(): object {
return { appName: this.appName };
}
- private timer: any;
private clientId: string;
private errorBody: string;
@@ -59,11 +52,9 @@ export class LoginComponent implements OnDestroy, OnInit {
private authService: AuthService,
private router: Router,
private status: StatusService,
- private fb: FormBuilder,
+ private fb: UntypedFormBuilder,
private settingsService: SettingsService,
private customziationFacade: CustomizationFacade,
- private images: ImageService,
- private sanitizer: DomSanitizer,
private route: ActivatedRoute,
@Inject(APP_BASE_HREF) href: string,
private translate: TranslateService,
@@ -111,14 +102,6 @@ export class LoginComponent implements OnDestroy, OnInit {
this.headerAuth();
});
this.settingsService.getClientId().subscribe((x) => (this.clientId = x));
- this.images.getRandomBackground().subscribe((x) => {
- this.background = this.sanitizer.bypassSecurityTrustStyle(
- "url(" + x.url + ")"
- );
- });
- this.timer = setInterval(() => {
- this.cycleBackground();
- }, 30000);
const base = this.href;
if (base.length > 1) {
@@ -132,7 +115,7 @@ export class LoginComponent implements OnDestroy, OnInit {
.subscribe((x) => (this.errorValidation = x));
}
- public onSubmit(form: FormGroup) {
+ public onSubmit(form: UntypedFormGroup) {
if (form.invalid) {
this.notify.open(this.errorValidation, "OK", {
duration: 300000,
@@ -284,18 +267,6 @@ export class LoginComponent implements OnDestroy, OnInit {
}
public ngOnDestroy() {
- clearInterval(this.timer);
clearInterval(this.pinTimer);
}
-
- private cycleBackground() {
- this.images.getRandomBackground().subscribe((x) => {
- this.background = "";
- });
- this.images.getRandomBackground().subscribe((x) => {
- this.background = this.sanitizer.bypassSecurityTrustStyle(
- "url(" + x.url + ")"
- );
- });
- }
}
diff --git a/src/Ombi/ClientApp/src/app/login/resetpassword.component.html b/src/Ombi/ClientApp/src/app/login/resetpassword.component.html
index 9fbeb7eda..201223800 100644
--- a/src/Ombi/ClientApp/src/app/login/resetpassword.component.html
+++ b/src/Ombi/ClientApp/src/app/login/resetpassword.component.html
@@ -1,8 +1,5 @@
-
+
diff --git a/src/Ombi/ClientApp/src/app/login/resetpassword.component.ts b/src/Ombi/ClientApp/src/app/login/resetpassword.component.ts
index cb030b386..bd0376cb1 100644
--- a/src/Ombi/ClientApp/src/app/login/resetpassword.component.ts
+++ b/src/Ombi/ClientApp/src/app/login/resetpassword.component.ts
@@ -1,30 +1,27 @@
-import { PlatformLocation, APP_BASE_HREF } from "@angular/common";
+import { APP_BASE_HREF } from "@angular/common";
import { Component, OnInit, Inject } from "@angular/core";
-import { FormBuilder, FormGroup, Validators } from "@angular/forms";
-import { DomSanitizer } from "@angular/platform-browser";
+import { UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms";
import { fadeInOutAnimation } from "../animations/fadeinout";
import { ICustomizationSettings } from "../interfaces";
-import { IdentityService, ImageService, NotificationService, SettingsService } from "../services";
+import { IdentityService, NotificationService, SettingsService } from "../services";
import { CustomizationFacade } from "../state/customization";
@Component({
templateUrl: "./resetpassword.component.html",
- animations: [fadeInOutAnimation],
styleUrls: ["./login.component.scss"],
})
export class ResetPasswordComponent implements OnInit {
- public form: FormGroup;
+ public form: UntypedFormGroup;
public customizationSettings: ICustomizationSettings;
public emailSettingsEnabled: boolean;
public baseUrl: string;
- public background: any;
private href: string;
constructor(private identityService: IdentityService, private notify: NotificationService,
- private fb: FormBuilder, private settingsService: SettingsService, @Inject(APP_BASE_HREF) href:string,
- private images: ImageService, private sanitizer: DomSanitizer, private customizationFacade: CustomizationFacade) {
+ private fb: UntypedFormBuilder, private settingsService: SettingsService, @Inject(APP_BASE_HREF) href:string,
+ private customizationFacade: CustomizationFacade) {
this.href = href;
this.form = this.fb.group({
email: ["", [Validators.required]],
@@ -32,9 +29,7 @@ export class ResetPasswordComponent implements OnInit {
}
public ngOnInit() {
- this.images.getRandomBackground().subscribe(x => {
- this.background = this.sanitizer.bypassSecurityTrustStyle("linear-gradient(-10deg, transparent 20%, rgba(0,0,0,0.7) 20.0%, rgba(0,0,0,0.7) 80.0%, transparent 80%),url(" + x.url + ")");
- });
+
const base = this.href;
if (base.length > 1) {
this.baseUrl = base;
@@ -43,7 +38,7 @@ export class ResetPasswordComponent implements OnInit {
this.settingsService.getEmailSettingsEnabled().subscribe(x => this.emailSettingsEnabled = x);
}
- public onSubmit(form: FormGroup) {
+ public onSubmit(form: UntypedFormGroup) {
if (this.emailSettingsEnabled) {
if (form.invalid) {
diff --git a/src/Ombi/ClientApp/src/app/login/tokenresetpassword.component.html b/src/Ombi/ClientApp/src/app/login/tokenresetpassword.component.html
index 6a1c2567f..bd8bc3e38 100644
--- a/src/Ombi/ClientApp/src/app/login/tokenresetpassword.component.html
+++ b/src/Ombi/ClientApp/src/app/login/tokenresetpassword.component.html
@@ -1,11 +1,7 @@
-
-
+
-
+
OMBI
= 7 && customizationSettings.applicationName.length < 14, 'hugeText': customizationSettings.applicationName.length >= 14 }" class="login_logo custom">{{customizationSettings.applicationName}}
@@ -13,7 +9,7 @@
The passwords do not match
-
+
The Password is required
The Email is required
The Confirm Password is required
@@ -41,16 +37,14 @@ required
-
-
-
+
-
-
+
+
-
+
diff --git a/src/Ombi/ClientApp/src/app/login/tokenresetpassword.component.ts b/src/Ombi/ClientApp/src/app/login/tokenresetpassword.component.ts
index 695a79abb..b7ef08281 100644
--- a/src/Ombi/ClientApp/src/app/login/tokenresetpassword.component.ts
+++ b/src/Ombi/ClientApp/src/app/login/tokenresetpassword.component.ts
@@ -1,10 +1,9 @@
import { ActivatedRoute, Params } from "@angular/router";
import { Component, OnInit } from "@angular/core";
-import { FormBuilder, FormGroup, Validators } from "@angular/forms";
-import { IdentityService, ImageService } from "../services";
+import { UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms";
+import { IdentityService } from "../services";
import { CustomizationFacade } from "../state/customization";
-import { DomSanitizer } from "@angular/platform-browser";
import { ICustomizationSettings } from "../interfaces";
import { IResetPasswordToken } from "../interfaces";
import { NotificationService } from "../services";
@@ -17,15 +16,12 @@ import { Router } from "@angular/router";
})
export class TokenResetPasswordComponent implements OnInit {
- public form: FormGroup;
+ public form: UntypedFormGroup;
public customizationSettings: ICustomizationSettings;
- public background: any;
public baseUrl: string;
constructor(private identityService: IdentityService, private router: Router, private route: ActivatedRoute, private notify: NotificationService,
- private fb: FormBuilder, private location: PlatformLocation, private images: ImageService,
- private sanitizer: DomSanitizer, private customizationFacade: CustomizationFacade,
- ) {
+ private fb: UntypedFormBuilder, private location: PlatformLocation, private customizationFacade: CustomizationFacade) {
this.route.queryParams
.subscribe((params: Params) => {
@@ -39,9 +35,6 @@ export class TokenResetPasswordComponent implements OnInit {
}
public ngOnInit() {
- this.images.getRandomBackground().subscribe(x => {
- this.background = this.sanitizer.bypassSecurityTrustStyle("linear-gradient(-10deg, transparent 20%, rgba(0,0,0,0.7) 20.0%, rgba(0,0,0,0.7) 80.0%, transparent 80%),url(" + x.url + ")");
- });
const base = this.location.getBaseHrefFromDOM();
if (base.length > 1) {
this.baseUrl = base;
@@ -49,7 +42,7 @@ export class TokenResetPasswordComponent implements OnInit {
this.customizationFacade.settings$().subscribe(x => this.customizationSettings = x);
}
- public onSubmit(form: FormGroup) {
+ public onSubmit(form: UntypedFormGroup) {
if (form.invalid) {
this.notify.error("Email address is required");
return;
@@ -65,6 +58,5 @@ export class TokenResetPasswordComponent implements OnInit {
});
}
});
-
}
}
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 2207ea323..20f5d303b 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
@@ -10,9 +10,8 @@
0" [imdbId]="movie.imdbId"
- [twitter]="movie.externalIds.twitterId" [facebook]="movie.externalIds.facebookId"
- [instagram]="movie.externalIds.instagramId" [available]="movie.available" [plexUrl]="movie.plexUrl"
- [embyUrl]="movie.embyUrl" [jellyfinUrl]="movie.jellyfinUrl" [isAdmin]="isAdmin"
+ [twitter]="movie.externalIds?.twitterId" [facebook]="movie.externalIds?.facebookId"
+ [instagram]="movie.externalIds?.instagramId" [available]="movie.available" [isAdmin]="isAdmin"
[canShowAdvanced]="showAdvanced && movieRequest" [type]="requestType" [has4KRequest]="movie.has4KRequest"
(openTrailer)="openDialog()" (onAdvancedOptions)="openAdvancedOptions()"
(onReProcessRequest)="reProcessRequest(false)" (onReProcess4KRequest)="reProcessRequest(true)">
@@ -24,7 +23,7 @@
-
+ 0">
{{'MediaDetails.RecommendationsTitle' | translate}}
- 0">
+
-
+ 0">
{{'MediaDetails.SimilarTitle' | translate}}
- 0">
+
\ No newline at end of file
+
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 c040fe4e0..8d1e5976b 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,6 +1,6 @@
-import { AfterViewInit, Component, OnInit, ViewChild, ViewEncapsulation } from "@angular/core";
+import { Component, OnInit, ViewEncapsulation } from "@angular/core";
import { ImageService, SearchV2Service, RequestService, MessageService, RadarrService, SettingsStateService } from "../../../services";
-import { ActivatedRoute } from "@angular/router";
+import { ActivatedRoute, Router } from "@angular/router";
import { DomSanitizer } from "@angular/platform-browser";
import { ISearchMovieResultV2 } from "../../../interfaces/ISearchMovieResultV2";
import { MatDialog } from "@angular/material/dialog";
@@ -12,7 +12,6 @@ import { NewIssueComponent } from "../shared/new-issue/new-issue.component";
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 { firstValueFrom, forkJoin } from "rxjs";
import { AdminRequestDialogComponent } from "../../../shared/admin-request-dialog/admin-request-dialog.component";
import { FeaturesFacade } from "../../../state/features/features.facade";
@@ -32,31 +31,45 @@ export class MovieDetailsComponent implements OnInit{
public issuesEnabled: boolean;
public roleName4k = "Request4KMovie";
public is4KEnabled = false;
-
public requestType = RequestType.movie;
-
-
private theMovidDbId: number;
private imdbId: string;
+ private snapMovieId: string;
- constructor(private searchService: SearchV2Service, private route: ActivatedRoute,
+
+ constructor(private searchService: SearchV2Service, private route: ActivatedRoute, private router: Router,
private sanitizer: DomSanitizer, private imageService: ImageService,
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 featureFacade: FeaturesFacade) {
- this.route.params.subscribe(async (params: any) => {
- if (typeof params.movieDbId === 'string' || params.movieDbId instanceof String) {
- if (params.movieDbId.startsWith("tt")) {
- this.imdbId = params.movieDbId;
- }
- }
- this.theMovidDbId = params.movieDbId;
+ this.snapMovieId = this.route.snapshot.params.movieDbId;
+ this.route.params.subscribe(async (params: any) => {
+ if (typeof params.movieDbId === 'string' || params.movieDbId instanceof String) {
+ if (params.movieDbId.startsWith("tt")) {
+ this.imdbId = params.movieDbId;
+ // Check if we user navigated to another movie and if so reload the component
+ if (this.imdbId !== this.snapMovieId) {
+ this.reloadComponent()
+ }
+ }
+ }
+ this.theMovidDbId = params.movieDbId;
+ // Check if we user navigated to another movie and if so reload the component
+ if (params.movieDbId !== this.snapMovieId) {
+ this.reloadComponent()
+ }
});
}
- async ngOnInit() {
+ reloadComponent() {
+ let currentUrl = this.router.url;
+ this.router.routeReuseStrategy.shouldReuseRoute = () => false;
+ this.router.onSameUrlNavigation = 'reload';
+ this.router.navigate([currentUrl]);
+ }
+ async ngOnInit() {
this.is4KEnabled = this.featureFacade.is4kEnabled();
this.issuesEnabled = this.settingsState.getIssue();
this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser");
@@ -68,6 +81,7 @@ export class MovieDetailsComponent implements OnInit{
if (this.imdbId) {
this.searchService.getMovieByImdbId(this.imdbId).subscribe(async x => {
this.movie = x;
+ this.checkPoster();
if (this.movie.requestId > 0) {
// Load up this request
this.hasRequest = true;
@@ -78,6 +92,7 @@ export class MovieDetailsComponent implements OnInit{
} else {
this.searchService.getFullMovieDetails(this.theMovidDbId).subscribe(async x => {
this.movie = x;
+ this.checkPoster();
if (this.movie.requestId > 0) {
// Load up this request
this.hasRequest = true;
@@ -272,7 +287,14 @@ export class MovieDetailsComponent implements OnInit{
}
});
}
-
+ private checkPoster() {
+ if (this.movie.posterPath == null) {
+ this.movie.posterPath = "../../../images/default_movie_poster.png";
+ }
+ else {
+ this.movie.posterPath = "https://image.tmdb.org/t/p/w300/" + this.movie.posterPath
+ };
+ }
private loadAdvancedInfo() {
const profile = this.radarrService.getQualityProfilesFromSettings();
const folders = this.radarrService.getRootFoldersFromSettings();
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 7fd3ce0ea..29d2c6beb 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
@@ -30,28 +30,35 @@
{{ this.movie.status | translateStatus }}
- {{'MediaDetails.Availability' | translate }}
- {{'Common.Available' | translate}}
- {{'Common.NotAvailable' | translate}}
-
-
- {{'MediaDetails.RequestStatus' | translate }}
- {{'Common.Denied' | translate}}
- {{'Common.ProcessingRequest' | translate}}
- {{'Common.PendingApproval' | translate}}
-
- {{'Common.NotRequested' | translate}}
-
+ {{'MediaDetails.Availability' | translate }}
+ {{'Common.Available' | translate}}
+ {{'Common.NotAvailable' | translate}}
+
+
+ {{'MediaDetails.RequestStatus' | translate }}
+
+ {{'Common.RequestDenied' | translate}}
+ {{'Common.ProcessingRequest' | translate}}
+ {{'Common.PendingApproval' | translate}}
+
+
+
+ {{'Common.RequestDenied4K' | translate}}
+ {{'Common.ProcessingRequest4K' | translate}}
+ {{'Common.PendingApproval4K' | translate}}
+
+
- {{'MediaDetails.RequestedBy' | translate }}
- {{request.requestedUser.userAlias}}
+ {{'MediaDetails.RequestedBy' | translate }}
+ {{request.requestedUser.userAlias}}
- {{'MediaDetails.RequestDate' | translate }}
- {{request.requestedDate | amUserLocale | amDateFormat: 'LL'}}
+ {{'MediaDetails.RequestDate' | translate }}
+ {{request.requestedDate4k | amUserLocale | amDateFormat: 'LL'}}
+ request.requestedDate4k"> {{request.requestedDate | amUserLocale | amDateFormat: 'LL'}}
@@ -59,9 +66,14 @@
{{RequestSource[request.source]}}
-
- {{'MediaDetails.DeniedReason' | translate }}
+
+ {{'MediaDetails.DeniedReason' | translate }}
+
{{request.deniedReason}}
+
+
+ {{request.deniedReason4K}}
+
@@ -72,7 +84,7 @@
{{'MediaDetails.Quality' | translate }}
- {{"4K" | quality}}
+ {{"4K" | quality}}
diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.html b/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.html
index 49875514d..e14323a0e 100644
--- a/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.html
+++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.html
@@ -6,10 +6,10 @@
-
+
-
+
diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.scss b/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.scss
index b73d71007..644902159 100644
--- a/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.scss
+++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.scss
@@ -65,7 +65,7 @@ body .ui-carousel .ui-carousel-content .ui-carousel-next:not(.ui-state-disabled)
@media (min-width: 979px) {
- .cast-profile-img {
+ :host ::ng-deep .cast-profile-img {
border-radius: 100%;
width: 200px;
max-height: 200px;
@@ -74,7 +74,7 @@ body .ui-carousel .ui-carousel-content .ui-carousel-next:not(.ui-state-disabled)
}
@media (max-width: 978px) {
- .cast-profile-img {
+ :host ::ng-deep .cast-profile-img {
border-radius: 100%;
width: 100px;
max-height: 100px;
diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/media-poster/media-poster.component.html b/src/Ombi/ClientApp/src/app/media-details/components/shared/media-poster/media-poster.component.html
index f0a6f04ea..28ef26041 100644
--- a/src/Ombi/ClientApp/src/app/media-details/components/shared/media-poster/media-poster.component.html
+++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/media-poster/media-poster.component.html
@@ -1,8 +1,8 @@
|