Compare commits

..

No commits in common. "develop" and "v4.37.3" have entirely different histories.

485 changed files with 26105 additions and 40662 deletions

35
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View file

@ -0,0 +1,35 @@
---
name: "\U0001F41B Bug report"
about: Create a report to help us improve
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Logs (Logs directory where Ombi is located)**
If applicable, a snippet of the logs that seems relevant to the bug if present.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
**Ombi Version (please complete the following information):**
- Version [e.g. 4.0.958]
- Media Server [e.g. Plex]
- Database Type: SQLite (Please change if using MySQL)
**Additional context**
Add any other context about the problem here.

View file

@ -1,50 +0,0 @@
name: "\U0001F41B Bug report"
description: 'Report a reproducible bug in Ombi'
body:
- type: markdown
attributes:
value: Thanks for taking the time to file a bug report! Please fill out this form as completely as possible.
- type: markdown
attributes:
value: |
If you leave out sections there is a high likelihood your issue will be closed.
If you have a question or you think your issue might be caused by your application code, you can get help from the community on [Discord](https://discord.gg/Sa7wNWb).
- type: textarea
attributes:
label: Summary
description: |
Clearly describe what the expected behavior is vs. what is actually happening. Please include any reproduction steps that is required to reproduce this issue.
If your summary is simply, for example: "I cannot setup Plex", then you will need to [continue debugging on your own](https://docs.ombi.app/) to more precisely define your issue before proceeding.
validations:
required: true
- type: input
id: version
attributes:
label: Ombi Version
description: What version of ombi are you running?
validations:
required: true
- type: dropdown
attributes:
label: What platform(s) does this occur on?
multiple: true
options:
- Docker
- Windows
- Linux
validations:
required: true
- type: dropdown
attributes:
label: What database are you using?
options:
- SQLite (Default)
- MySQL
validations:
required: true
- type: textarea
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell

View file

@ -3,8 +3,8 @@ contact_links:
- name: Docs - name: Docs
url: https://docs.ombi.app/ url: https://docs.ombi.app/
about: The Ombi documentation should help guide you through installation and setup as well as help resolve common problems and answer frequently asked questions about: The Ombi documentation should help guide you through installation and setup as well as help resolve common problems and answer frequently asked questions
- name: Discord support - name: Reddit support
url: https://discord.gg/Sa7wNWb url: https://www.reddit.com/r/Ombi
about: Ask questions about Ombi about: Ask questions about Ombi
- name: Feature suggestions - name: Feature suggestions
url: https://ombifeatures.featureupvote.com url: https://ombifeatures.featureupvote.com

View file

@ -12,10 +12,10 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/setup-node@v2 - uses: actions/setup-node@v2
with: with:
node-version: '20' node-version: '18'
- name: NodeModules Cache - name: NodeModules Cache
uses: actions/cache@v4 uses: actions/cache@v2
with: with:
path: '**/node_modules' path: '**/node_modules'
key: node_modules-${{ hashFiles('**/yarn.lock') }} key: node_modules-${{ hashFiles('**/yarn.lock') }}
@ -27,7 +27,7 @@ jobs:
run: yarn --cwd ./src/Ombi/ClientApp run build run: yarn --cwd ./src/Ombi/ClientApp run build
- name: Publish UI Artifacts - name: Publish UI Artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v2
with: with:
name: angular_dist name: angular_dist
path: | path: |
@ -39,10 +39,10 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/setup-dotnet@v1 - uses: actions/setup-dotnet@v1
with: with:
dotnet-version: '8.0.x' dotnet-version: '6.0.x'
- name: Nuget Cache - name: Nuget Cache
uses: actions/cache@v4 uses: actions/cache@v2
with: with:
path: ~/.nuget/packages path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }} key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
@ -84,10 +84,10 @@ jobs:
strategy: strategy:
matrix: matrix:
include: include:
- os: win-x64 - os: win10-x64
format: zip format: zip
compression: zip compression: zip
- os: win-x86 - os: win10-x86
format: zip format: zip
compression: zip compression: zip
- os: linux-x64 - os: linux-x64
@ -106,13 +106,13 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/setup-dotnet@v1 - uses: actions/setup-dotnet@v1
with: with:
dotnet-version: '8.0.x' dotnet-version: '6.0.x'
- uses: actions/setup-dotnet@v1 - uses: actions/setup-dotnet@v1
with: with:
dotnet-version: '5.0.x' dotnet-version: '5.0.x'
- name: Nuget Cache - name: Nuget Cache
uses: actions/cache@v4 uses: actions/cache@v2
with: with:
path: ~/.nuget/packages path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }} key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
@ -130,7 +130,7 @@ jobs:
working-directory: src/Ombi working-directory: src/Ombi
- name: Download Angular - name: Download Angular
uses: actions/download-artifact@v4 uses: actions/download-artifact@v2
with: with:
name: angular_dist name: angular_dist
path: ~/src/Ombi/dist path: ~/src/Ombi/dist
@ -156,7 +156,7 @@ jobs:
directory: 'src/Ombi/${{ matrix.os }}' directory: 'src/Ombi/${{ matrix.os }}'
- name: Publish Release - name: Publish Release
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v2
with: with:
name: ${{ matrix.os }} name: ${{ matrix.os }}
path: | path: |
@ -170,7 +170,7 @@ jobs:
- name: Download Artifacts - name: Download Artifacts
id: download id: download
uses: actions/download-artifact@v4 uses: actions/download-artifact@v2
with: with:
path: artifacts path: artifacts
@ -190,7 +190,7 @@ jobs:
if: contains(github.ref, 'develop') if: contains(github.ref, 'develop')
with: with:
prerelease: true prerelease: true
generate_release_notes: false generate_release_notes: true
body: ${{ needs.versioning.outputs.changelog }} body: ${{ needs.versioning.outputs.changelog }}
name: ${{ needs.versioning.outputs.tag }} name: ${{ needs.versioning.outputs.tag }}
tag_name: ${{ needs.versioning.outputs.tag }} tag_name: ${{ needs.versioning.outputs.tag }}

View file

@ -1,47 +1,47 @@
# name: 'Chromatic' name: 'Chromatic'
# # Event for the workflow # Event for the workflow
# on: on:
# push: push:
# workflow_dispatch: workflow_dispatch:
# # List of jobs # List of jobs
# jobs: jobs:
# storybook-build: storybook-build:
# # Operating System # Operating System
# runs-on: ubuntu-latest runs-on: ubuntu-latest
# steps: steps:
# - name: Checkout repository - name: Checkout repository
# uses: actions/checkout@v2 uses: actions/checkout@v2
# with: with:
# fetch-depth: 0 fetch-depth: 0
# - name: NodeModules Cache - name: NodeModules Cache
# uses: actions/cache@v4 uses: actions/cache@v2
# with: with:
# path: '**/node_modules' path: '**/node_modules'
# key: node_modules-${{ hashFiles('**/yarn.lock') }} key: node_modules-${{ hashFiles('**/yarn.lock') }}
# - name: Install dependencies - name: Install dependencies
# working-directory: ./src/Ombi/ClientApp working-directory: ./src/Ombi/ClientApp
# run: yarn run: yarn
# - name: Publish to Chromatic - name: Publish to Chromatic
# if: github.ref != 'refs/heads/master' if: github.ref != 'refs/heads/master'
# uses: chromaui/action@v1 uses: chromaui/action@v1
# with: with:
# projectToken: 7c47e1a1a4bd projectToken: 7c47e1a1a4bd
# exitZeroOnChanges: true exitZeroOnChanges: true
# workingDir: ./src/Ombi/ClientApp workingDir: ./src/Ombi/ClientApp
# buildScriptName: storybookbuild buildScriptName: storybookbuild
# exitOnceUploaded: true exitOnceUploaded: true
# - name: Publish to Chromatic and auto accept changes - name: Publish to Chromatic and auto accept changes
# if: github.ref == 'refs/heads/develop' if: github.ref == 'refs/heads/develop'
# uses: chromaui/action@v1 uses: chromaui/action@v1
# with: with:
# projectToken: 7c47e1a1a4bd projectToken: 7c47e1a1a4bd
# autoAcceptChanges: true # 👈 Option to accept all changes autoAcceptChanges: true # 👈 Option to accept all changes
# workingDir: ./src/Ombi/ClientApp workingDir: ./src/Ombi/ClientApp
# buildScriptName: storybookbuild buildScriptName: storybookbuild
# exitOnceUploaded: true exitOnceUploaded: true

View file

@ -37,7 +37,7 @@ jobs:
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v3 uses: github/codeql-action/init@v1
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file. # If you wish to specify custom queries, you can do so here or in a config file.
@ -48,7 +48,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@v3 uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell. # Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl # 📚 https://git.io/JvXDl
@ -62,4 +62,4 @@ jobs:
# make release # make release
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3 uses: github/codeql-action/analyze@v1

View file

@ -22,9 +22,9 @@ jobs:
dotnet-version: 6.0.x dotnet-version: 6.0.x
- uses: actions/setup-node@v2 - uses: actions/setup-node@v2
with: with:
node-version: '20' node-version: '18'
- uses: actions/cache@v4 - uses: actions/cache@v2
with: with:
path: | path: |
'**/node_modules' '**/node_modules'
@ -43,8 +43,8 @@ jobs:
- name: Run Docker Image - name: Run Docker Image
run: nohup docker run --rm -p 5000:5000 ombi & run: nohup docker run --rm -p 5000:5000 ombi &
- name: Run Wiremock # - name: Run Wiremock Plex
run: nohup docker run --rm -p 32400:8080 --name wiremock wiremock/wiremock:2.35.0 & # run: nohup docker run -it --rm -p 32400:8080 --name wiremock wiremock/wiremock:2.35.0
- name: Sleep for server to start - name: Sleep for server to start
run: sleep 20 run: sleep 20
@ -61,7 +61,7 @@ jobs:
# nohup dotnet run --project ./src/Ombi -- --host http://*:3577 & # nohup dotnet run --project ./src/Ombi -- --host http://*:3577 &
- name: Cypress Tests - name: Cypress Tests
uses: cypress-io/github-action@v4 uses: cypress-io/github-action@v2.8.2
with: with:
record: true record: true
browser: chrome browser: chrome
@ -73,9 +73,3 @@ jobs:
env: env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Stop Docker
if: always()
run: |
docker ps -q | xargs -I {} docker logs {}
docker container kill $(docker ps -q)

View file

@ -17,10 +17,10 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/setup-node@v2 - uses: actions/setup-node@v2
with: with:
node-version: '20' node-version: '18'
- name: NodeModules Cache - name: NodeModules Cache
uses: actions/cache@v4 uses: actions/cache@v2
with: with:
path: '**/node_modules' path: '**/node_modules'
key: node_modules-${{ hashFiles('**/yarn.lock') }} key: node_modules-${{ hashFiles('**/yarn.lock') }}
@ -38,10 +38,10 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/setup-dotnet@v1 - uses: actions/setup-dotnet@v1
with: with:
dotnet-version: '8.0.x' dotnet-version: '6.0.x'
- name: Nuget Cache - name: Nuget Cache
uses: actions/cache@v4 uses: actions/cache@v2
with: with:
path: ~/.nuget/packages path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }} key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
@ -76,10 +76,10 @@ jobs:
strategy: strategy:
matrix: matrix:
include: include:
- os: win-x64 - os: win10-x64
format: zip format: zip
compression: zip compression: zip
- os: win-x86 - os: win10-x86
format: zip format: zip
compression: zip compression: zip
- os: linux-x64 - os: linux-x64
@ -98,10 +98,10 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/setup-dotnet@v1 - uses: actions/setup-dotnet@v1
with: with:
dotnet-version: '8.0.x' dotnet-version: '6.0.x'
- name: Nuget Cache - name: Nuget Cache
uses: actions/cache@v4 uses: actions/cache@v2
with: with:
path: ~/.nuget/packages path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }} key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}

View file

@ -1,509 +1,3 @@
## [4.49.5](https://github.com/Ombi-app/Ombi/compare/v4.49.4...v4.49.5) (2025-08-23)
### Bug Fixes
* set MarkedAsApproved on TV requests ([57d3880](https://github.com/Ombi-app/Ombi/commit/57d3880115f8e65e7d7d522aaa725b01878b45fe))
## [4.49.4](https://github.com/Ombi-app/Ombi/compare/v4.49.3...v4.49.4) (2025-08-23)
## [4.49.3](https://github.com/Ombi-app/Ombi/compare/v4.49.2...v4.49.3) (2025-08-17)
### Bug Fixes
* **plex-api:** update Plex Watchlist URL ([11fd7a5](https://github.com/Ombi-app/Ombi/commit/11fd7a5fc853da75974a16bf4fdecd72a836f54b))
## [4.49.2](https://github.com/Ombi-app/Ombi/compare/v4.49.1...v4.49.2) (2025-07-12)
### Performance Improvements
* **discover:** :zap: Improve the loading performance on the discover page ([97d5167](https://github.com/Ombi-app/Ombi/commit/97d5167db6c9f915021f32b96b281d7db3741d7f))
## [4.49.1](https://github.com/Ombi-app/Ombi/compare/v4.49.0...v4.49.1) (2025-07-12)
### Bug Fixes
* **auth:** Fixed an issue where refreshing the page as a power user would stop the application from loading [#5242](https://github.com/Ombi-app/Ombi/issues/5242) ([cee4014](https://github.com/Ombi-app/Ombi/commit/cee40146ee02f7fb79e2019d6fe2f9d5c5dbdfc8))
# [4.49.0](https://github.com/Ombi-app/Ombi/compare/v4.48.5...v4.49.0) (2025-07-11)
### Features
* Added the ability for the Watchlist to automatically refresh the users token. This will reduce the need for the user to log in ([067c029](https://github.com/Ombi-app/Ombi/commit/067c029f42e9fd853d060fdb2093013b15ac14c0))
## [4.48.5](https://github.com/Ombi-app/Ombi/compare/v4.48.4...v4.48.5) (2025-05-14)
### Bug Fixes
* filter out excluded notification agents from user preferences ([c9ab4f4](https://github.com/Ombi-app/Ombi/commit/c9ab4f4f9faa66dbf263da693db1eefcf68beeec)), closes [#5196](https://github.com/Ombi-app/Ombi/issues/5196)
## [4.48.4](https://github.com/Ombi-app/Ombi/compare/v4.48.3...v4.48.4) (2025-05-14)
### Bug Fixes
* **translations:** 🌐 New translations from Crowdin [skip ci] ([dbbfdd9](https://github.com/Ombi-app/Ombi/commit/dbbfdd926f0808f6d16f0b2cd8b5406e6b610c82))
* **translations:** 🌐 New translations from Crowdin [skip ci] ([53a6a09](https://github.com/Ombi-app/Ombi/commit/53a6a092b14b8b8bdbff95d066926d3dbe6951f4))
* **ui:** correct timezone handling in OmbiDatePipe ([f88c5ad](https://github.com/Ombi-app/Ombi/commit/f88c5ad818fadea7064e7dfbe46f07eae855109a)), closes [#5102](https://github.com/Ombi-app/Ombi/issues/5102)
## [4.48.3](https://github.com/Ombi-app/Ombi/compare/v4.48.2...v4.48.3) (2025-05-14)
### Bug Fixes
* Correct 4K movie request existence check ([ba6e708](https://github.com/Ombi-app/Ombi/commit/ba6e708e189f52f2ff4ebc073fa38a4f53f1061c)), closes [#4798](https://github.com/Ombi-app/Ombi/issues/4798)
## [4.48.2](https://github.com/Ombi-app/Ombi/compare/v4.48.1...v4.48.2) (2025-05-14)
### Bug Fixes
* **radarr:** ensure RequestedUser is loaded when creating tags ([f8658fe](https://github.com/Ombi-app/Ombi/commit/f8658fe6d56488aa5caa68093245cbf021a31810)), closes [#5045](https://github.com/Ombi-app/Ombi/issues/5045)
## [4.48.1](https://github.com/Ombi-app/Ombi/compare/v4.48.0...v4.48.1) (2025-05-14)
# [4.48.0](https://github.com/Ombi-app/Ombi/compare/v4.47.3...v4.48.0) (2025-05-14)
### Features
* added the watchlist notification ([0dfd453](https://github.com/Ombi-app/Ombi/commit/0dfd4533dba01cb04ea2217c020de8833ddf39c6))
## [4.47.3](https://github.com/Ombi-app/Ombi/compare/v4.47.2...v4.47.3) (2025-04-13)
### Bug Fixes
* [#5223](https://github.com/Ombi-app/Ombi/issues/5223) ([cf0c161](https://github.com/Ombi-app/Ombi/commit/cf0c1614a496b4f7cf19d78e885c3e37dae5cf0f))
## [4.47.2](https://github.com/Ombi-app/Ombi/compare/v4.47.0...v4.47.2) (2025-03-11)
### Bug Fixes
* **user-import:** Do not import users that do not have access to the server [#5064](https://github.com/Ombi-app/Ombi/issues/5064) ([a801cfd](https://github.com/Ombi-app/Ombi/commit/a801cfdb0946cbee3c35b7e917a240f69020f221))
# [4.47.0](https://github.com/Ombi-app/Ombi/compare/v4.46.8...v4.47.0) (2025-01-03)
### Features
* **wizard:** :sparkles: Added the ability to start with a different database ([#5208](https://github.com/Ombi-app/Ombi/issues/5208)) ([cc98fc6](https://github.com/Ombi-app/Ombi/commit/cc98fc6aca27111a8afc3b7b5b8e53207b73fe15))
## [4.46.8](https://github.com/Ombi-app/Ombi/compare/v4.46.7...v4.46.8) (2025-01-03)
### Bug Fixes
* **radarr-settings:** this.normalForm is undefined ([#5207](https://github.com/Ombi-app/Ombi/issues/5207)) ([dc2b958](https://github.com/Ombi-app/Ombi/commit/dc2b958915bf6cb77e093ada843ef6d9f62a3755)), closes [#4994](https://github.com/Ombi-app/Ombi/issues/4994)
## [4.46.7](https://github.com/Ombi-app/Ombi/compare/v4.46.6...v4.46.7) (2024-12-03)
### Bug Fixes
* **requests:** :bug: Power users can now set profiles and root folders when requesting ([138df1e](https://github.com/Ombi-app/Ombi/commit/138df1eb25c709c1939d01d4c9f9ece63f8e0fde))
## [4.46.6](https://github.com/Ombi-app/Ombi/compare/v4.46.5...v4.46.6) (2024-11-24)
## [4.46.5](https://github.com/Ombi-app/Ombi/compare/v4.46.4...v4.46.5) (2024-11-23)
### Bug Fixes
* **Fixed the UI not applying the correct timezone settings:** :bug: ([029ea79](https://github.com/Ombi-app/Ombi/commit/029ea7919220fbc506898733caeb4370053051a7))
## [4.46.4](https://github.com/Ombi-app/Ombi/compare/v4.46.3...v4.46.4) (2024-09-09)
## [4.46.3](https://github.com/Ombi-app/Ombi/compare/v4.46.2...v4.46.3) (2024-09-07)
### Bug Fixes
* **radarr-4k:** :bug: Fixed an issue where the overrides wouldn't work for 4k Requests ([0fb29a0](https://github.com/Ombi-app/Ombi/commit/0fb29a0b16b1fc87f71df1a589f6141324cf2f1b))
## [4.46.2](https://github.com/Ombi-app/Ombi/compare/v4.46.1...v4.46.2) (2024-09-03)
### Bug Fixes
* **radarr:** :bug: Enable validation on the radarr settings page ([0af3511](https://github.com/Ombi-app/Ombi/commit/0af3511e819d24e0f4edf6f33931e61bba743224))
## [4.46.1](https://github.com/Ombi-app/Ombi/compare/v4.46.0...v4.46.1) (2024-08-27)
### Bug Fixes
* src/Ombi.Notifications/Ombi.Notifications.csproj to reduce vulnerabilities ([#5167](https://github.com/Ombi-app/Ombi/issues/5167)) ([e1f2a84](https://github.com/Ombi-app/Ombi/commit/e1f2a848065d79c8bba9eafff4f1f5db4a994b53))
# [4.46.0](https://github.com/Ombi-app/Ombi/compare/v4.45.1...v4.46.0) (2024-08-20)
### Bug Fixes
* **discover:** Improved rendering on the discover page ([ea00d6c](https://github.com/Ombi-app/Ombi/commit/ea00d6c12f4441da243287d0fbc706d66c0afd82))
* src/Ombi.Store/Ombi.Store.csproj to reduce vulnerabilities ([#5160](https://github.com/Ombi-app/Ombi/issues/5160)) ([9c21074](https://github.com/Ombi-app/Ombi/commit/9c2107418939ee92e50c59765481f30efac12eff))
### Features
* upgrade @ngx-translate/core from 14.0.0 to 15.0.0 ([#5158](https://github.com/Ombi-app/Ombi/issues/5158)) ([48d3dec](https://github.com/Ombi-app/Ombi/commit/48d3dec26d36002a9d613432fb7f9232d8801cba))
* upgrade @ngx-translate/http-loader from 7.0.0 to 8.0.0 ([#5159](https://github.com/Ombi-app/Ombi/issues/5159)) ([3bd98c1](https://github.com/Ombi-app/Ombi/commit/3bd98c1d711786bff66f1528dcdddcafe256abd2))
## [4.45.1](https://github.com/Ombi-app/Ombi/compare/v4.45.0...v4.45.1) (2024-08-20)
### Bug Fixes
* **plex:** Fixed some errors around the scanner that was causing the scan to fail ([d9787dc](https://github.com/Ombi-app/Ombi/commit/d9787dc32aace808d196f6f87456ef45de3d7bbf))
# [4.45.0](https://github.com/Ombi-app/Ombi/compare/v4.44.1...v4.45.0) (2024-08-07)
# [4.44.0](https://github.com/Ombi-app/Ombi/compare/v4.43.22...v4.44.0) (2024-07-11)
### Features
* Adding postgres support to ombi (beta) ([#5050](https://github.com/Ombi-app/Ombi/issues/5050)) ([f8c6102](https://github.com/Ombi-app/Ombi/commit/f8c61027bf53d657d7955a98b69d7ab90b66a75a))
## [4.43.22](https://github.com/Ombi-app/Ombi/compare/v4.43.21...v4.43.22) (2024-07-08)
## [4.43.21](https://github.com/Ombi-app/Ombi/compare/v4.43.20...v4.43.21) (2024-06-26)
## [4.43.20](https://github.com/Ombi-app/Ombi/compare/v4.43.16...v4.43.20) (2024-05-14)
### Bug Fixes
* upgrade multiple dependencies with Snyk ([#5104](https://github.com/Ombi-app/Ombi/issues/5104)) [skip ci] ([a1083f6](https://github.com/Ombi-app/Ombi/commit/a1083f67c73c968b9ff0a0feebe5a9aac6a7c7c9))
## [4.43.16](https://github.com/Ombi-app/Ombi/compare/v4.43.15...v4.43.16) (2024-04-01)
## [4.43.15](https://github.com/Ombi-app/Ombi/compare/v4.43.14...v4.43.15) (2024-03-30)
### Bug Fixes
* fixed emails not being able to load the template ([6b49d9b](https://github.com/Ombi-app/Ombi/commit/6b49d9bc7108a0b663ca05de19dbf4841c9c43c1))
## [4.43.14](https://github.com/Ombi-app/Ombi/compare/v4.43.13...v4.43.14) (2024-03-06)
### Performance Improvements
* ⚡ Improve render performance on the discover, movie and tv pages ([#5084](https://github.com/Ombi-app/Ombi/issues/5084)) ([71c86a8](https://github.com/Ombi-app/Ombi/commit/71c86a8db9e63bf0ab779f9a8b5d62a42c246392))
## [4.43.13](https://github.com/Ombi-app/Ombi/compare/v4.43.12...v4.43.13) (2024-03-05)
## [4.43.12](https://github.com/Ombi-app/Ombi/compare/v4.43.11...v4.43.12) (2024-03-05)
### Bug Fixes
* src/Ombi/ClientApp/package.json & src/Ombi/ClientApp/yarn.lock to reduce vulnerabilities ([#5040](https://github.com/Ombi-app/Ombi/issues/5040)) [skip ci] ([955a742](https://github.com/Ombi-app/Ombi/commit/955a742fae1d0a3983c59cf77eb1a2d222f18b48))
* src/Ombi/ClientApp/package.json & src/Ombi/ClientApp/yarn.lock to reduce vulnerabilities ([#5072](https://github.com/Ombi-app/Ombi/issues/5072)) [skip ci] ([af6a986](https://github.com/Ombi-app/Ombi/commit/af6a9867719deb7b651a6a78352a8ce0df7a0cf0))
* src/Ombi/Ombi.csproj to reduce vulnerabilities ([#5066](https://github.com/Ombi-app/Ombi/issues/5066)) [skip ci] ([71df058](https://github.com/Ombi-app/Ombi/commit/71df05886512b8589f193a5cda0166c694438fc0))
* upgrade @fortawesome/fontawesome-free from 6.4.2 to 6.5.0 ([#5053](https://github.com/Ombi-app/Ombi/issues/5053)) [skip ci] ([5017e38](https://github.com/Ombi-app/Ombi/commit/5017e38f87e32821adb744935fffcb2d76927e2c))
* upgrade @types/jquery from 3.5.27 to 3.5.28 ([#5049](https://github.com/Ombi-app/Ombi/issues/5049)) [skip ci] ([2c8fe80](https://github.com/Ombi-app/Ombi/commit/2c8fe8087aea227e7425e82392ad9ccb3f8261b4))
* upgrade moment from 2.29.4 to 2.30.1 ([#5075](https://github.com/Ombi-app/Ombi/issues/5075)) [skip ci] ([460fa39](https://github.com/Ombi-app/Ombi/commit/460fa39bb95c73bafcd65fcc394fecca04d3ac49))
* upgrade multiple dependencies with Snyk ([#5073](https://github.com/Ombi-app/Ombi/issues/5073)) [skip ci] ([a27b459](https://github.com/Ombi-app/Ombi/commit/a27b4592471c58fca9ad5193b979171fa7c5e66d))
## [4.43.11](https://github.com/Ombi-app/Ombi/compare/v4.43.10...v4.43.11) (2024-01-11)
### Bug Fixes
* **emby:** Add more logging on the PlaySync to check for Tv Shows without a valid TMDB ([08eb13b](https://github.com/Ombi-app/Ombi/commit/08eb13b788582d576a0e1befdb8e84ef7ff0d2f3))
## [4.43.10](https://github.com/Ombi-app/Ombi/compare/v4.43.9...v4.43.10) (2023-11-20)
### Bug Fixes
* **radarr-4k:** 🐛 Fixed an issue when using Radarr 4k with user set quality profiles. There are now user quality profiles for 4k profile [#5025](https://github.com/Ombi-app/Ombi/issues/5025) ([62b9a1f](https://github.com/Ombi-app/Ombi/commit/62b9a1f65fc4ee5f1eaf9dfabf37742a9007433e))
## [4.43.9](https://github.com/Ombi-app/Ombi/compare/v4.43.8...v4.43.9) (2023-11-18)
### Bug Fixes
* **sonarr:** 🐛 Correctly monitor episodes ([57e7830](https://github.com/Ombi-app/Ombi/commit/57e7830f8e54b65ce3c1f0b122cbcc517d1af926))
## [4.43.8](https://github.com/Ombi-app/Ombi/compare/v4.43.7...v4.43.8) (2023-11-09)
## [4.43.7](https://github.com/Ombi-app/Ombi/compare/v4.43.6...v4.43.7) (2023-11-09)
### Bug Fixes
* upgrade @microsoft/signalr from 6.0.22 to 6.0.23 ([#5032](https://github.com/Ombi-app/Ombi/issues/5032)) [skip ci] ([11edac9](https://github.com/Ombi-app/Ombi/commit/11edac961b0b828658be83a9c4e67079345d3b0b))
* upgrade @types/jquery from 3.5.22 to 3.5.23 ([#5034](https://github.com/Ombi-app/Ombi/issues/5034)) [skip ci] ([9e28879](https://github.com/Ombi-app/Ombi/commit/9e28879fc1a479e1bd77ca003e3e748fec27f081))
## [4.43.6](https://github.com/Ombi-app/Ombi/compare/v4.43.5...v4.43.6) (2023-11-01)
### Bug Fixes
* **discord:** 🐛 Fixed an issue where the Icon in the discord notifications wouldn't apply ([32da949](https://github.com/Ombi-app/Ombi/commit/32da949a9547f68c57eb4338f749228b7de167c2))
* src/Ombi/ClientApp/package.json & src/Ombi/ClientApp/yarn.lock to reduce vulnerabilities ([#5010](https://github.com/Ombi-app/Ombi/issues/5010)) [skip ci] ([9c2e1b4](https://github.com/Ombi-app/Ombi/commit/9c2e1b435305d51cc9ab7f5d6932ccd3fa723e6c))
* upgrade @fortawesome/fontawesome-free from 6.4.0 to 6.4.2 ([#5005](https://github.com/Ombi-app/Ombi/issues/5005)) [skip ci] ([f703ff2](https://github.com/Ombi-app/Ombi/commit/f703ff255cf389a60bdece824214d38f57f03f90))
* upgrade @microsoft/signalr from 6.0.18 to 6.0.20 ([#4999](https://github.com/Ombi-app/Ombi/issues/4999)) [skip ci] ([563a044](https://github.com/Ombi-app/Ombi/commit/563a0443ea09ff71c5aa740173b4f3c5627cb543))
* upgrade @microsoft/signalr from 6.0.21 to 6.0.22 ([#5020](https://github.com/Ombi-app/Ombi/issues/5020)) ([1261a44](https://github.com/Ombi-app/Ombi/commit/1261a446e7ffa4d7540623f76ecc9d7e643ca4ce))
* upgrade @types/jquery from 3.5.16 to 3.5.17 ([#5011](https://github.com/Ombi-app/Ombi/issues/5011)) [skip ci] ([40ee175](https://github.com/Ombi-app/Ombi/commit/40ee175ccd6e53b1254833163954b6a1be0d5251))
* upgrade @types/jquery from 3.5.18 to 3.5.19 ([#5022](https://github.com/Ombi-app/Ombi/issues/5022)) ([291425e](https://github.com/Ombi-app/Ombi/commit/291425e6091d90ac07010ff65cc3a53309965546))
* upgrade cypress-real-events from 1.10.0 to 1.10.1 ([#5014](https://github.com/Ombi-app/Ombi/issues/5014)) ([ed06c22](https://github.com/Ombi-app/Ombi/commit/ed06c22fb26fb605b857f3f8e1b26b2dbab15710))
* upgrade cypress-real-events from 1.8.1 to 1.9.1 ([#5000](https://github.com/Ombi-app/Ombi/issues/5000)) [skip ci] ([19e0a88](https://github.com/Ombi-app/Ombi/commit/19e0a886ced344bfe6284f3916fba12826b7de08))
* upgrade jquery from 3.7.0 to 3.7.1 ([#5015](https://github.com/Ombi-app/Ombi/issues/5015)) ([7bc915c](https://github.com/Ombi-app/Ombi/commit/7bc915cc14ed27ad0f35142279f9362e5b7b27b8))
* upgrade multiple dependencies with Snyk ([#5030](https://github.com/Ombi-app/Ombi/issues/5030)) ([7e1e254](https://github.com/Ombi-app/Ombi/commit/7e1e254cfe6c84c1f143388f436d63efd4686e55))
* upgrade zone.js from 0.13.1 to 0.13.2 ([#5019](https://github.com/Ombi-app/Ombi/issues/5019)) ([c5c8dda](https://github.com/Ombi-app/Ombi/commit/c5c8dda7e4f744fa47841efba9f0e8fee9ef67c6))
## [4.43.4](https://github.com/Ombi-app/Ombi/compare/v4.43.3...v4.43.4) (2023-07-28)
### Bug Fixes
* **user-importer:** Fixed not importing all correct users [#4989](https://github.com/Ombi-app/Ombi/issues/4989) ([34c32f8](https://github.com/Ombi-app/Ombi/commit/34c32f8338705ea3f790d95b91c9ada21a41b9f2))
## [4.43.3](https://github.com/Ombi-app/Ombi/compare/v4.43.2...v4.43.3) (2023-07-28)
### Bug Fixes
* switch back to the old plex friends API [#4989](https://github.com/Ombi-app/Ombi/issues/4989) ([c8ad12e](https://github.com/Ombi-app/Ombi/commit/c8ad12eb5f53889609d1793ae907afd33ba6ef38))
## [4.43.2](https://github.com/Ombi-app/Ombi/compare/v4.43.1...v4.43.2) (2023-07-19)
### Bug Fixes
* **plex-api:** Switch over to the new API to avoid deprecation & save… ([#4986](https://github.com/Ombi-app/Ombi/issues/4986)) ([2f2d35e](https://github.com/Ombi-app/Ombi/commit/2f2d35ec867a8e5488e368db294bd37bcf92d843))
* Remove old trending source ([#4987](https://github.com/Ombi-app/Ombi/issues/4987)) ([aacaa3e](https://github.com/Ombi-app/Ombi/commit/aacaa3e140b43f5d196da612f785cc4451717752))
## [4.43.1](https://github.com/Ombi-app/Ombi/compare/v4.43.0...v4.43.1) (2023-07-16)
### Bug Fixes
* **user-importer:** don't delete admins in the cleanup ([895b9bf](https://github.com/Ombi-app/Ombi/commit/895b9bf6a060a678d4b0cca8083aa96c38e47b95))
# [4.43.0](https://github.com/Ombi-app/Ombi/compare/v4.42.3...v4.43.0) (2023-07-14)
### Features
* Add Auto Approve 4K role ([#4982](https://github.com/Ombi-app/Ombi/issues/4982)) ([#4983](https://github.com/Ombi-app/Ombi/issues/4983)) ([ac05495](https://github.com/Ombi-app/Ombi/commit/ac054954254b9d77a42e057f1065570c7fdc1093)), closes [#4957](https://github.com/Ombi-app/Ombi/issues/4957)
## [4.42.3](https://github.com/Ombi-app/Ombi/compare/v4.42.2...v4.42.3) (2023-07-13)
### Bug Fixes
* **user-importer:** Do not delete the Plex Admin as part of the user Importer cleanup [#4870](https://github.com/Ombi-app/Ombi/issues/4870) ([#4981](https://github.com/Ombi-app/Ombi/issues/4981)) ([4e80e7b](https://github.com/Ombi-app/Ombi/commit/4e80e7b7c3239a46a645ab6d1054993734ad4dd6))
## [4.42.2](https://github.com/Ombi-app/Ombi/compare/v4.42.1...v4.42.2) (2023-07-03)
### Bug Fixes
* Remove Angular TSLint ([#4973](https://github.com/Ombi-app/Ombi/issues/4973)) ([93969b5](https://github.com/Ombi-app/Ombi/commit/93969b5a2d82f442299bee418fae43cb590d7743))
* upgrade jquery from 3.6.1 to 3.7.0 ([#4974](https://github.com/Ombi-app/Ombi/issues/4974)) ([f2552ef](https://github.com/Ombi-app/Ombi/commit/f2552ef6ede011080a8d5499e11930c4d41d04c2))
* upgrade multiple dependencies with Snyk ([#4961](https://github.com/Ombi-app/Ombi/issues/4961)) ([3c3edf6](https://github.com/Ombi-app/Ombi/commit/3c3edf6273fa98c420989ebcebfee52b2545e402))
* upgrade zone.js from 0.11.8 to 0.13.0 ([#4975](https://github.com/Ombi-app/Ombi/issues/4975)) ([37f6564](https://github.com/Ombi-app/Ombi/commit/37f65648a2f8742020b0954acec4168aee048942))
## [4.42.1](https://github.com/Ombi-app/Ombi/compare/v4.42.0...v4.42.1) (2023-06-20)
### Bug Fixes
* More automation tests mainly around the Plex Settings page ([#4821](https://github.com/Ombi-app/Ombi/issues/4821)) ([21bfc5a](https://github.com/Ombi-app/Ombi/commit/21bfc5a45adf6da6a80854e19494a8ffdc9c0761))
* src/Ombi.Notifications/Ombi.Notifications.csproj to reduce vulnerabilities ([#4969](https://github.com/Ombi-app/Ombi/issues/4969)) [skip ci] ([8584ad4](https://github.com/Ombi-app/Ombi/commit/8584ad46053c51f5da40b24f3efd1b9e5a031ddd))
* upgrade @fortawesome/fontawesome-free from 6.1.2 to 6.4.0 ([#4965](https://github.com/Ombi-app/Ombi/issues/4965)) [skip ci] ([84454e5](https://github.com/Ombi-app/Ombi/commit/84454e53c00c808e8a393c7750bdc418a7593e91))
* upgrade @microsoft/signalr from 6.0.11 to 6.0.16 ([#4964](https://github.com/Ombi-app/Ombi/issues/4964)) [skip ci] ([a0201e3](https://github.com/Ombi-app/Ombi/commit/a0201e3f585dc52f717e33c46ede35a4eccac736))
* upgrade cypress-real-events from 1.7.4 to 1.8.1 ([#4968](https://github.com/Ombi-app/Ombi/issues/4968)) [skip ci] ([8a24b56](https://github.com/Ombi-app/Ombi/commit/8a24b56299c3bc98bf0d719ba448972aaa7f7461))
* upgrade multiple dependencies with Snyk ([#4963](https://github.com/Ombi-app/Ombi/issues/4963)) [skip ci] ([6025c5e](https://github.com/Ombi-app/Ombi/commit/6025c5ed757438d3a5d79bd36fd789ef0297ce70))
* upgrade primeng from 15.0.0-rc.1 to 15.4.1 ([#4962](https://github.com/Ombi-app/Ombi/issues/4962)) [skip ci] ([23a4fed](https://github.com/Ombi-app/Ombi/commit/23a4fede69898a25b342aed78a8cda553c1fd18d))
# [4.42.0](https://github.com/Ombi-app/Ombi/compare/v4.41.1...v4.42.0) (2023-06-02)
### Bug Fixes
* **translations:** 🌐 New translations from Crowdin [skip ci] ([#4926](https://github.com/Ombi-app/Ombi/issues/4926)) ([151efe1](https://github.com/Ombi-app/Ombi/commit/151efe19d0012b85f317c175da5ab4802ea14e20))
### Features
* **emby:** Show watched status for TV requests ([1f37de0](https://github.com/Ombi-app/Ombi/commit/1f37de08888812b6d130d92bb664a89e89149105))
## [4.41.1](https://github.com/Ombi-app/Ombi/compare/v4.41.0...v4.41.1) (2023-05-27)
# [4.41.0](https://github.com/Ombi-app/Ombi/compare/v4.40.0...v4.41.0) (2023-05-27)
### Bug Fixes
* Fix various styling issues ([#4935](https://github.com/Ombi-app/Ombi/issues/4935)) ([90b934a](https://github.com/Ombi-app/Ombi/commit/90b934a36996c0f489096f3641350a1c0d3b7c89))
### Features
* **emby:** Show end-user external IP address to Emby when logging in as an Emby user ([#4949](https://github.com/Ombi-app/Ombi/issues/4949)) ([79cef7e](https://github.com/Ombi-app/Ombi/commit/79cef7e0f8643e36536a9ea84dd1a07c232403a9)), closes [#4947](https://github.com/Ombi-app/Ombi/issues/4947)
# [4.40.0](https://github.com/Ombi-app/Ombi/compare/v4.39.1...v4.40.0) (2023-05-18)
# [4.39.0](https://github.com/Ombi-app/Ombi/compare/v4.35.11...v4.39.0) (2023-05-17)
### Bug Fixes
* **emby:** Fix Emby played sync running a full sync during recently added sync ([#4932](https://github.com/Ombi-app/Ombi/issues/4932)) ([9424586](https://github.com/Ombi-app/Ombi/commit/9424586e9c1b622b6475aeb8ee3cf4a8f346da6e))
### Features
* Hide watched status when request is not available ([#4934](https://github.com/Ombi-app/Ombi/issues/4934)) ([82c7f1c](https://github.com/Ombi-app/Ombi/commit/82c7f1c44fd7c87d57cc2b0c34a10fcda7628f4e))
## [4.38.2](https://github.com/Ombi-app/Ombi/compare/v4.38.1...v4.38.2) (2023-05-17)
## [4.38.1](https://github.com/Ombi-app/Ombi/compare/v4.38.0...v4.38.1) (2023-05-09)
### Bug Fixes
* **API:** Allow RequestOnBehalf rights if requested from the API ([#4919](https://github.com/Ombi-app/Ombi/issues/4919)) ([bb6dedd](https://github.com/Ombi-app/Ombi/commit/bb6deddfaecb3d6c7c3c6970414444b619bb9106))
* **notificaitons:** Add the RequestedByAlias field to the Notification Message ([7e9c8be](https://github.com/Ombi-app/Ombi/commit/7e9c8bec6b02bb4e11f8db50394e493d4dd07723))
# [4.38.0](https://github.com/Ombi-app/Ombi/compare/v4.37.3...v4.38.0) (2023-05-07)
### Bug Fixes
* remove sort header ([969bc7b](https://github.com/Ombi-app/Ombi/commit/969bc7bb25ea900ab9199509b079b36843e5bd6f))
### Features
* **emby:** Show watched status for Movie requests ([9cfb10b](https://github.com/Ombi-app/Ombi/commit/9cfb10bb1ee69067a6f47bd2c8a72d4e6834350e))
## [4.37.3](https://github.com/Ombi-app/Ombi/compare/v4.37.2...v4.37.3) (2023-05-07) ## [4.37.3](https://github.com/Ombi-app/Ombi/compare/v4.37.2...v4.37.3) (2023-05-07)
@ -624,7 +118,7 @@
## [4.35.12](https://github.com/Ombi-app/Ombi/compare/v4.35.10...v4.35.12) (2023-03-25) ## [4.35.12](https://github.com/Ombi-app/Ombi/compare/v4.35.9...v4.35.12) (2023-03-25)
### Bug Fixes ### Bug Fixes
@ -637,6 +131,10 @@
## [4.22.5](https://github.com/Ombi-app/Ombi/compare/v4.22.4...v4.22.5) (2022-08-05)
## [4.35.8](https://github.com/Ombi-app/Ombi/compare/v4.35.7...v4.35.8) (2023-02-17) ## [4.35.8](https://github.com/Ombi-app/Ombi/compare/v4.35.7...v4.35.8) (2023-02-17)
@ -877,448 +375,3 @@
## [4.27.8](https://github.com/Ombi-app/Ombi/compare/v4.27.7...v4.27.8) (2022-10-07)
## [4.27.7](https://github.com/Ombi-app/Ombi/compare/v4.27.6...v4.27.7) (2022-10-07)
### Bug Fixes
* Fixes default image for recently requested items. ([#4767](https://github.com/Ombi-app/Ombi/issues/4767)) ([2e6f35f](https://github.com/Ombi-app/Ombi/commit/2e6f35f89abb3dd3685ec8289f8620c7ef7072cd))
## [4.27.6](https://github.com/Ombi-app/Ombi/compare/v4.27.5...v4.27.6) (2022-10-01)
### Bug Fixes
* **notifications:** Fixed the error when sending multiple test notifications. Added more logging when Discord complains the message is invalid ([fc14780](https://github.com/Ombi-app/Ombi/commit/fc14780bd354483119ddcbb55a8c382e1890a783))
## [4.27.5](https://github.com/Ombi-app/Ombi/compare/v4.27.4...v4.27.5) (2022-09-30)
### Bug Fixes
* **importer:** 🐛 Allow you to only import Plex Admins without the Plex Users ([8c9ad9b](https://github.com/Ombi-app/Ombi/commit/8c9ad9b414fdc6c88bdb911d6057ae5d38783b98))
## [4.27.4](https://github.com/Ombi-app/Ombi/compare/v4.27.3...v4.27.4) (2022-09-30)
## [4.27.3](https://github.com/Ombi-app/Ombi/compare/v4.27.2...v4.27.3) (2022-09-30)
### Bug Fixes
* **availability:** 🐛 Fixed a issue with the availability checker after the previous update. Added full test coverage around that area ([28e2480](https://github.com/Ombi-app/Ombi/commit/28e248046ad56390595f84172bbd5f5961325b4d))
## [4.27.2](https://github.com/Ombi-app/Ombi/compare/v4.27.1...v4.27.2) (2022-09-29)
### Bug Fixes
* **sonarr:** :bug: Cleaned up and removed Sonarr v3 option, sonarr v3 is now the default. This allows us to get ready for the upcoming Sonarr v4 ([#4764](https://github.com/Ombi-app/Ombi/issues/4764)) ([2cddec7](https://github.com/Ombi-app/Ombi/commit/2cddec759004b6490f686ff74cb092238e3dc946))
## [4.27.1](https://github.com/Ombi-app/Ombi/compare/v4.27.0...v4.27.1) (2022-09-20)
### Bug Fixes
* **plex:** stop the plex sync from deleting episodes when we can't find the plex key ([66b05e5](https://github.com/Ombi-app/Ombi/commit/66b05e5a85dbfe1fec5f9366e80987f2cfa1f4fe))
# [4.27.0](https://github.com/Ombi-app/Ombi/compare/v4.26.0...v4.27.0) (2022-09-14)
### Features
* Recently requested improvements ([#4755](https://github.com/Ombi-app/Ombi/issues/4755)) ([ff04d87](https://github.com/Ombi-app/Ombi/commit/ff04d875343604c77c391bf55d0968977e480281))
# [4.26.0](https://github.com/Ombi-app/Ombi/compare/v4.25.1...v4.26.0) (2022-09-07)
### Features
* **notifications:** Add more curly variables for partially available notification ([66aa101](https://github.com/Ombi-app/Ombi/commit/66aa101019c4c4b34e186db9d303049d02b9c781))
## [4.25.1](https://github.com/Ombi-app/Ombi/compare/v4.25.0...v4.25.1) (2022-09-07)
### Bug Fixes
* **webhook:** Remove added trailing slash from webhook URL [#4710](https://github.com/Ombi-app/Ombi/issues/4710) ([369eb33](https://github.com/Ombi-app/Ombi/commit/369eb339171671101be219486e2aab27a20f3d74))
# [4.25.0](https://github.com/Ombi-app/Ombi/compare/v4.24.0...v4.25.0) (2022-08-23)
### Bug Fixes
* fixed stats controller ([#4742](https://github.com/Ombi-app/Ombi/issues/4742)) ([47ea64b](https://github.com/Ombi-app/Ombi/commit/47ea64b5a401770f1943b575ca40f84d515e96b3))
### Features
* Watchlist history errors([#4741](https://github.com/Ombi-app/Ombi/issues/4741)) ([c222f1a](https://github.com/Ombi-app/Ombi/commit/c222f1a945e944ef34e68cad2b61f40e57cab823))
# [4.24.0](https://github.com/Ombi-app/Ombi/compare/v4.23.2...v4.24.0) (2022-08-22)
### Features
* add crew on movie page ([#4722](https://github.com/Ombi-app/Ombi/issues/4722)) ([1d53261](https://github.com/Ombi-app/Ombi/commit/1d532613823804b25984bd1d223d081a54ad143d))
## [4.23.2](https://github.com/Ombi-app/Ombi/compare/v4.23.1...v4.23.2) (2022-08-22)
### Bug Fixes
* Fix conflicting property name for Swagger ([#4733](https://github.com/Ombi-app/Ombi/issues/4733)) ([d661f32](https://github.com/Ombi-app/Ombi/commit/d661f32e8a9e105faab6380b4b7b642896b98163))
## [4.23.1](https://github.com/Ombi-app/Ombi/compare/v4.23.0...v4.23.1) (2022-08-12)
### Bug Fixes
* Localize recently requested on discover page ([#4729](https://github.com/Ombi-app/Ombi/issues/4729)) ([bf65c76](https://github.com/Ombi-app/Ombi/commit/bf65c76ff9ce38f65a9e5feb872734e8d8e35eb6))
# [4.23.0](https://github.com/Ombi-app/Ombi/compare/v4.22.5...v4.23.0) (2022-08-09)
### Bug Fixes
* Log Microsoft warnings to log file ([#4723](https://github.com/Ombi-app/Ombi/issues/4723)) ([26ac75f](https://github.com/Ombi-app/Ombi/commit/26ac75f0c223c2a91e3471797ae46ede3fde89cc))
### Features
* ✨ Recently Requested on Discover Page ([#4387](https://github.com/Ombi-app/Ombi/issues/4387)) ([44d38fb](https://github.com/Ombi-app/Ombi/commit/44d38fbaae521dbb467b61c7471b2384015ac52e))
## [4.22.4](https://github.com/Ombi-app/Ombi/compare/v4.22.3...v4.22.4) (2022-08-04)
### Bug Fixes
* :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.22.3](https://github.com/Ombi-app/Ombi/compare/v4.22.2...v4.22.3) (2022-07-28)
### Bug Fixes
* Override Sonarr V3 Profiles endpoint ([#4678](https://github.com/Ombi-app/Ombi/issues/4678)) ([875da95](https://github.com/Ombi-app/Ombi/commit/875da959f353119b05138d68ee6d32a49e14b91e))
## [4.22.2](https://github.com/Ombi-app/Ombi/compare/v4.22.1...v4.22.2) (2022-07-25)
### Bug Fixes
* fixed an issue where I broke images for some users ([81ddc85](https://github.com/Ombi-app/Ombi/commit/81ddc8553b9094c3f6843b036daebb2eb9262e00))
## [4.22.1](https://github.com/Ombi-app/Ombi/compare/v4.22.0...v4.22.1) (2022-07-25)
### Bug Fixes
* **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.22.0](https://github.com/Ombi-app/Ombi/compare/v4.21.2...v4.22.0) (2022-07-22)
### Features
* **discover:** ✨ Added infinite scroll on advanced search results ([898bc89](https://github.com/Ombi-app/Ombi/commit/898bc89fa78245c1f3de9481f6c724f087a16e39))
## [4.21.2](https://github.com/Ombi-app/Ombi/compare/v4.21.1...v4.21.2) (2022-07-22)
### Bug Fixes
* Landing and Login page improvements ([#4690](https://github.com/Ombi-app/Ombi/issues/4690)) ([6d423b5](https://github.com/Ombi-app/Ombi/commit/6d423b5447c52c5e59d8d2bd92a23b47468eb736))
## [4.21.1](https://github.com/Ombi-app/Ombi/compare/v4.21.0...v4.21.1) (2022-07-11)
### Bug Fixes
* **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))
# [4.21.0](https://github.com/Ombi-app/Ombi/compare/v4.20.4...v4.21.0) (2022-06-22)
### Features
* Upgrade to Angular14 ([#4668](https://github.com/Ombi-app/Ombi/issues/4668)) ([b9d55a4](https://github.com/Ombi-app/Ombi/commit/b9d55a469b412558cbf67c1e25db7fdda5964cd8))
### Performance Improvements
* stop populating obsolete subscribe fields ([#4625](https://github.com/Ombi-app/Ombi/issues/4625)) ([9a73463](https://github.com/Ombi-app/Ombi/commit/9a734637665f671b17c2bb440d93b35a891c142b))
## [4.20.4](https://github.com/Ombi-app/Ombi/compare/v4.20.3...v4.20.4) (2022-06-15)
### Bug Fixes
* fixed build ([f877921](https://github.com/Ombi-app/Ombi/commit/f8779219146051ea74f8b6408658ff7975afb88b))
## [4.20.3](https://github.com/Ombi-app/Ombi/compare/v4.20.2...v4.20.3) (2022-06-05)
### Bug Fixes
* **plex:** 🐛 Fixed an issue with the Plex Sync ([ab1a11a](https://github.com/Ombi-app/Ombi/commit/ab1a11af78efbe9d37bd55aa80a640796c138a98))
## [4.20.2](https://github.com/Ombi-app/Ombi/compare/v4.20.1...v4.20.2) (2022-06-03)
### Bug Fixes
* :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.20.1](https://github.com/Ombi-app/Ombi/compare/v4.20.0...v4.20.1) (2022-05-27)
### Bug Fixes
* 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))
# [4.20.0](https://github.com/Ombi-app/Ombi/compare/v4.19.1...v4.20.0) (2022-04-28)
### Features
* **discover:** Show more relevant shows in upcoming TV ([8357819](https://github.com/Ombi-app/Ombi/commit/8357819b53b8c675c0b246d7006b5a778bdba33f))
## [4.19.1](https://github.com/Ombi-app/Ombi/compare/v4.19.0...v4.19.1) (2022-04-27)
# [4.19.0](https://github.com/Ombi-app/Ombi/compare/v4.18.0...v4.19.0) (2022-04-27)
### Features
* **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.18.0](https://github.com/Ombi-app/Ombi/compare/v4.17.0...v4.18.0) (2022-04-26)
### Bug Fixes
* **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
* **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))
# [4.17.0](https://github.com/Ombi-app/Ombi/compare/v4.16.17...v4.17.0) (2022-04-25)
## [4.16.17](https://github.com/Ombi-app/Ombi/compare/v4.16.16...v4.16.17) (2022-04-25)
## [4.16.16](https://github.com/Ombi-app/Ombi/compare/v4.16.15...v4.16.16) (2022-04-25)
### Bug Fixes
* **4616:** :bug: fixed mandatory fields ([d8f2260](https://github.com/Ombi-app/Ombi/commit/d8f2260c7ae3ed48386743b7adbd06e284487034))
## [4.16.15](https://github.com/Ombi-app/Ombi/compare/v4.16.14...v4.16.15) (2022-04-24)
### Features
* **discover:** Add original language filter ([ef7ec86](https://github.com/Ombi-app/Ombi/commit/ef7ec861d8aede2a4817752c990617f583805391))
## [4.16.14](https://github.com/Ombi-app/Ombi/compare/v4.16.13...v4.16.14) (2022-04-19)
## [4.16.13](https://github.com/Ombi-app/Ombi/compare/v4.16.12...v4.16.13) (2022-04-19)
## [4.44.1](https://github.com/Ombi-app/Ombi/compare/v4.44.0...v4.44.1) (2024-07-22)
## [4.43.5](https://github.com/Ombi-app/Ombi/compare/v4.43.4...v4.43.5) (2023-08-24)
# [4.44.0](https://github.com/Ombi-app/Ombi/compare/v4.43.22...v4.44.0) (2024-07-11)
### Features
* Adding postgres support to ombi (beta) ([#5050](https://github.com/Ombi-app/Ombi/issues/5050)) ([f8c6102](https://github.com/Ombi-app/Ombi/commit/f8c61027bf53d657d7955a98b69d7ab90b66a75a))
## [4.43.22](https://github.com/Ombi-app/Ombi/compare/v4.43.21...v4.43.22) (2024-07-08)
## [4.43.21](https://github.com/Ombi-app/Ombi/compare/v4.43.20...v4.43.21) (2024-06-26)
## [4.43.20](https://github.com/Ombi-app/Ombi/compare/v4.43.16...v4.43.20) (2024-05-14)
### Bug Fixes
* upgrade multiple dependencies with Snyk ([#5104](https://github.com/Ombi-app/Ombi/issues/5104)) [skip ci] ([a1083f6](https://github.com/Ombi-app/Ombi/commit/a1083f67c73c968b9ff0a0feebe5a9aac6a7c7c9))
## [4.43.16](https://github.com/Ombi-app/Ombi/compare/v4.43.15...v4.43.16) (2024-04-01)
## [4.43.15](https://github.com/Ombi-app/Ombi/compare/v4.43.14...v4.43.15) (2024-03-30)
### Bug Fixes
* fixed emails not being able to load the template ([6b49d9b](https://github.com/Ombi-app/Ombi/commit/6b49d9bc7108a0b663ca05de19dbf4841c9c43c1))
## [4.43.14](https://github.com/Ombi-app/Ombi/compare/v4.43.13...v4.43.14) (2024-03-06)
### Performance Improvements
* ⚡ Improve render performance on the discover, movie and tv pages ([#5084](https://github.com/Ombi-app/Ombi/issues/5084)) ([71c86a8](https://github.com/Ombi-app/Ombi/commit/71c86a8db9e63bf0ab779f9a8b5d62a42c246392))
## [4.43.13](https://github.com/Ombi-app/Ombi/compare/v4.43.12...v4.43.13) (2024-03-05)
## [4.43.12](https://github.com/Ombi-app/Ombi/compare/v4.43.11...v4.43.12) (2024-03-05)
### Bug Fixes
* src/Ombi/ClientApp/package.json & src/Ombi/ClientApp/yarn.lock to reduce vulnerabilities ([#5040](https://github.com/Ombi-app/Ombi/issues/5040)) [skip ci] ([955a742](https://github.com/Ombi-app/Ombi/commit/955a742fae1d0a3983c59cf77eb1a2d222f18b48))
* src/Ombi/ClientApp/package.json & src/Ombi/ClientApp/yarn.lock to reduce vulnerabilities ([#5072](https://github.com/Ombi-app/Ombi/issues/5072)) [skip ci] ([af6a986](https://github.com/Ombi-app/Ombi/commit/af6a9867719deb7b651a6a78352a8ce0df7a0cf0))
* src/Ombi/Ombi.csproj to reduce vulnerabilities ([#5066](https://github.com/Ombi-app/Ombi/issues/5066)) [skip ci] ([71df058](https://github.com/Ombi-app/Ombi/commit/71df05886512b8589f193a5cda0166c694438fc0))
* upgrade @fortawesome/fontawesome-free from 6.4.2 to 6.5.0 ([#5053](https://github.com/Ombi-app/Ombi/issues/5053)) [skip ci] ([5017e38](https://github.com/Ombi-app/Ombi/commit/5017e38f87e32821adb744935fffcb2d76927e2c))
* upgrade @types/jquery from 3.5.27 to 3.5.28 ([#5049](https://github.com/Ombi-app/Ombi/issues/5049)) [skip ci] ([2c8fe80](https://github.com/Ombi-app/Ombi/commit/2c8fe8087aea227e7425e82392ad9ccb3f8261b4))
* upgrade moment from 2.29.4 to 2.30.1 ([#5075](https://github.com/Ombi-app/Ombi/issues/5075)) [skip ci] ([460fa39](https://github.com/Ombi-app/Ombi/commit/460fa39bb95c73bafcd65fcc394fecca04d3ac49))
* upgrade multiple dependencies with Snyk ([#5073](https://github.com/Ombi-app/Ombi/issues/5073)) [skip ci] ([a27b459](https://github.com/Ombi-app/Ombi/commit/a27b4592471c58fca9ad5193b979171fa7c5e66d))
## [4.43.11](https://github.com/Ombi-app/Ombi/compare/v4.43.10...v4.43.11) (2024-01-11)
### Bug Fixes
* **emby:** Add more logging on the PlaySync to check for Tv Shows without a valid TMDB ([08eb13b](https://github.com/Ombi-app/Ombi/commit/08eb13b788582d576a0e1befdb8e84ef7ff0d2f3))
## [4.43.10](https://github.com/Ombi-app/Ombi/compare/v4.43.9...v4.43.10) (2023-11-20)
### Bug Fixes
* **radarr-4k:** 🐛 Fixed an issue when using Radarr 4k with user set quality profiles. There are now user quality profiles for 4k profile [#5025](https://github.com/Ombi-app/Ombi/issues/5025) ([62b9a1f](https://github.com/Ombi-app/Ombi/commit/62b9a1f65fc4ee5f1eaf9dfabf37742a9007433e))
## [4.43.9](https://github.com/Ombi-app/Ombi/compare/v4.43.8...v4.43.9) (2023-11-18)
### Bug Fixes
* **sonarr:** 🐛 Correctly monitor episodes ([57e7830](https://github.com/Ombi-app/Ombi/commit/57e7830f8e54b65ce3c1f0b122cbcc517d1af926))
## [4.43.8](https://github.com/Ombi-app/Ombi/compare/v4.43.7...v4.43.8) (2023-11-09)

986
README.md

File diff suppressed because it is too large Load diff

2309
src/.idea/.idea.Ombi/.idea/contentModel.xml generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,440 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DBNavigator.Project.DDLFileAttachmentManager">
<mappings />
<preferences />
</component>
<component name="DBNavigator.Project.DatabaseAssistantManager">
<assistants />
</component>
<component name="DBNavigator.Project.DatabaseBrowserManager">
<autoscroll-to-editor value="false" />
<autoscroll-from-editor value="true" />
<show-object-properties value="true" />
<loaded-nodes />
</component>
<component name="DBNavigator.Project.DatabaseFileManager">
<open-files />
</component>
<component name="DBNavigator.Project.ExecutionManager">
<retain-sticky-names value="false" />
</component>
<component name="DBNavigator.Project.ParserDiagnosticsManager">
<diagnostics-history />
</component>
<component name="DBNavigator.Project.Settings">
<connections />
<browser-settings>
<general>
<display-mode value="TABBED" />
<navigation-history-size value="100" />
<show-object-details value="false" />
<enable-sticky-paths value="true" />
</general>
<filters>
<object-type-filter>
<object-type name="SCHEMA" enabled="true" />
<object-type name="USER" enabled="true" />
<object-type name="ROLE" enabled="true" />
<object-type name="PRIVILEGE" enabled="true" />
<object-type name="CHARSET" enabled="true" />
<object-type name="TABLE" enabled="true" />
<object-type name="VIEW" enabled="true" />
<object-type name="MATERIALIZED_VIEW" enabled="true" />
<object-type name="NESTED_TABLE" enabled="true" />
<object-type name="COLUMN" enabled="true" />
<object-type name="INDEX" enabled="true" />
<object-type name="CONSTRAINT" enabled="true" />
<object-type name="DATASET_TRIGGER" enabled="true" />
<object-type name="DATABASE_TRIGGER" enabled="true" />
<object-type name="SYNONYM" enabled="true" />
<object-type name="SEQUENCE" enabled="true" />
<object-type name="PROCEDURE" enabled="true" />
<object-type name="FUNCTION" enabled="true" />
<object-type name="PACKAGE" enabled="true" />
<object-type name="TYPE" enabled="true" />
<object-type name="TYPE_ATTRIBUTE" enabled="true" />
<object-type name="ARGUMENT" enabled="true" />
<object-type name="JAVA_CLASS" enabled="true" />
<object-type name="JAVA_INNER_CLASS" enabled="true" />
<object-type name="JAVA_FIELD" enabled="true" />
<object-type name="JAVA_METHOD" enabled="true" />
<object-type name="DIMENSION" enabled="true" />
<object-type name="CLUSTER" enabled="true" />
<object-type name="DBLINK" enabled="true" />
<object-type name="CREDENTIAL" enabled="true" />
<object-type name="AI_PROFILE" enabled="true" />
</object-type-filter>
</filters>
<sorting>
<object-type name="COLUMN" sorting-type="NAME" />
<object-type name="FUNCTION" sorting-type="NAME" />
<object-type name="PROCEDURE" sorting-type="NAME" />
<object-type name="ARGUMENT" sorting-type="POSITION" />
<object-type name="TYPE ATTRIBUTE" sorting-type="POSITION" />
</sorting>
<default-editors>
<object-type name="VIEW" editor-type="SELECTION" />
<object-type name="PACKAGE" editor-type="SELECTION" />
<object-type name="TYPE" editor-type="SELECTION" />
</default-editors>
</browser-settings>
<navigation-settings>
<lookup-filters>
<lookup-objects>
<object-type name="SCHEMA" enabled="true" />
<object-type name="USER" enabled="false" />
<object-type name="ROLE" enabled="false" />
<object-type name="PRIVILEGE" enabled="false" />
<object-type name="CHARSET" enabled="false" />
<object-type name="TABLE" enabled="true" />
<object-type name="VIEW" enabled="true" />
<object-type name="MATERIALIZED VIEW" enabled="true" />
<object-type name="INDEX" enabled="true" />
<object-type name="CONSTRAINT" enabled="true" />
<object-type name="DATASET TRIGGER" enabled="true" />
<object-type name="DATABASE TRIGGER" enabled="true" />
<object-type name="SYNONYM" enabled="false" />
<object-type name="SEQUENCE" enabled="true" />
<object-type name="PROCEDURE" enabled="true" />
<object-type name="FUNCTION" enabled="true" />
<object-type name="PACKAGE" enabled="true" />
<object-type name="TYPE" enabled="true" />
<object-type name="JAVA CLASS" enabled="true" />
<object-type name="INNER CLASS" enabled="true" />
<object-type name="JAVA FIELD" enabled="true" />
<object-type name="JAVA METHOD" enabled="true" />
<object-type name="JAVA PARAMETER" enabled="true" />
<object-type name="DIMENSION" enabled="false" />
<object-type name="CLUSTER" enabled="false" />
<object-type name="DBLINK" enabled="false" />
<object-type name="CREDENTIAL" enabled="false" />
</lookup-objects>
<force-database-load value="false" />
<prompt-connection-selection value="true" />
<prompt-schema-selection value="true" />
</lookup-filters>
</navigation-settings>
<dataset-grid-settings>
<general>
<enable-zooming value="true" />
<enable-column-tooltip value="true" />
</general>
<sorting>
<nulls-first value="true" />
<max-sorting-columns value="4" />
</sorting>
<audit-columns>
<column-names value="" />
<visible value="true" />
<editable value="false" />
</audit-columns>
</dataset-grid-settings>
<dataset-editor-settings>
<text-editor-popup>
<active value="false" />
<active-if-empty value="false" />
<data-length-threshold value="100" />
<popup-delay value="1000" />
</text-editor-popup>
<values-actions-popup>
<show-popup-button value="true" />
<element-count-threshold value="1000" />
<data-length-threshold value="250" />
</values-actions-popup>
<general>
<fetch-block-size value="100" />
<fetch-timeout value="30" />
<trim-whitespaces value="true" />
<convert-empty-strings-to-null value="true" />
<select-content-on-cell-edit value="true" />
<large-value-preview-active value="true" />
</general>
<filters>
<prompt-filter-dialog value="true" />
<default-filter-type value="BASIC" />
</filters>
<qualified-text-editor text-length-threshold="300">
<content-types>
<content-type name="Text" enabled="true" />
<content-type name="Properties" enabled="true" />
<content-type name="XML" enabled="true" />
<content-type name="DTD" enabled="true" />
<content-type name="HTML" enabled="true" />
<content-type name="XHTML" enabled="true" />
<content-type name="CSS" enabled="true" />
<content-type name="SQL" enabled="true" />
<content-type name="PL/SQL" enabled="true" />
<content-type name="JavaScript" enabled="true" />
<content-type name="JSON" enabled="true" />
<content-type name="JSON5" enabled="true" />
<content-type name="YAML" enabled="true" />
<content-type name="C#" enabled="true" />
</content-types>
</qualified-text-editor>
<record-navigation>
<navigation-target value="VIEWER" />
</record-navigation>
</dataset-editor-settings>
<code-editor-settings>
<general>
<show-object-navigation-gutter value="false" />
<show-spec-declaration-navigation-gutter value="true" />
<enable-spellchecking value="true" />
<enable-reference-spellchecking value="false" />
</general>
<confirmations>
<save-changes value="false" />
<revert-changes value="true" />
<exit-on-changes value="ASK" />
</confirmations>
</code-editor-settings>
<code-completion-settings>
<filters>
<basic-filter>
<filter-element type="RESERVED_WORD" id="keyword" selected="true" />
<filter-element type="RESERVED_WORD" id="function" selected="true" />
<filter-element type="RESERVED_WORD" id="parameter" selected="true" />
<filter-element type="RESERVED_WORD" id="datatype" selected="true" />
<filter-element type="RESERVED_WORD" id="exception" selected="true" />
<filter-element type="OBJECT" id="schema" selected="true" />
<filter-element type="OBJECT" id="role" selected="true" />
<filter-element type="OBJECT" id="user" selected="true" />
<filter-element type="OBJECT" id="privilege" selected="true" />
<user-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="false" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</user-schema>
<public-schema>
<filter-element type="OBJECT" id="table" selected="false" />
<filter-element type="OBJECT" id="view" selected="false" />
<filter-element type="OBJECT" id="materialized view" selected="false" />
<filter-element type="OBJECT" id="index" selected="false" />
<filter-element type="OBJECT" id="constraint" selected="false" />
<filter-element type="OBJECT" id="trigger" selected="false" />
<filter-element type="OBJECT" id="synonym" selected="false" />
<filter-element type="OBJECT" id="sequence" selected="false" />
<filter-element type="OBJECT" id="procedure" selected="false" />
<filter-element type="OBJECT" id="function" selected="false" />
<filter-element type="OBJECT" id="package" selected="false" />
<filter-element type="OBJECT" id="type" selected="false" />
<filter-element type="OBJECT" id="dimension" selected="false" />
<filter-element type="OBJECT" id="cluster" selected="false" />
<filter-element type="OBJECT" id="dblink" selected="false" />
</public-schema>
<any-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</any-schema>
</basic-filter>
<extended-filter>
<filter-element type="RESERVED_WORD" id="keyword" selected="true" />
<filter-element type="RESERVED_WORD" id="function" selected="true" />
<filter-element type="RESERVED_WORD" id="parameter" selected="true" />
<filter-element type="RESERVED_WORD" id="datatype" selected="true" />
<filter-element type="RESERVED_WORD" id="exception" selected="true" />
<filter-element type="OBJECT" id="schema" selected="true" />
<filter-element type="OBJECT" id="user" selected="true" />
<filter-element type="OBJECT" id="role" selected="true" />
<filter-element type="OBJECT" id="privilege" selected="true" />
<user-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</user-schema>
<public-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</public-schema>
<any-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</any-schema>
</extended-filter>
</filters>
<sorting enabled="true">
<sorting-element type="RESERVED_WORD" id="keyword" />
<sorting-element type="RESERVED_WORD" id="datatype" />
<sorting-element type="OBJECT" id="column" />
<sorting-element type="OBJECT" id="table" />
<sorting-element type="OBJECT" id="view" />
<sorting-element type="OBJECT" id="materialized view" />
<sorting-element type="OBJECT" id="index" />
<sorting-element type="OBJECT" id="constraint" />
<sorting-element type="OBJECT" id="trigger" />
<sorting-element type="OBJECT" id="synonym" />
<sorting-element type="OBJECT" id="sequence" />
<sorting-element type="OBJECT" id="procedure" />
<sorting-element type="OBJECT" id="function" />
<sorting-element type="OBJECT" id="package" />
<sorting-element type="OBJECT" id="type" />
<sorting-element type="OBJECT" id="dimension" />
<sorting-element type="OBJECT" id="cluster" />
<sorting-element type="OBJECT" id="dblink" />
<sorting-element type="OBJECT" id="schema" />
<sorting-element type="OBJECT" id="role" />
<sorting-element type="OBJECT" id="user" />
<sorting-element type="RESERVED_WORD" id="function" />
<sorting-element type="RESERVED_WORD" id="parameter" />
</sorting>
<format>
<enforce-code-style-case value="true" />
</format>
</code-completion-settings>
<execution-engine-settings>
<statement-execution>
<fetch-block-size value="100" />
<execution-timeout value="20" />
<debug-execution-timeout value="600" />
<focus-result value="false" />
<prompt-execution value="false" />
</statement-execution>
<script-execution>
<command-line-interfaces />
<execution-timeout value="300" />
</script-execution>
<method-execution>
<execution-timeout value="30" />
<debug-execution-timeout value="600" />
<parameter-history-size value="10" />
</method-execution>
</execution-engine-settings>
<operation-settings>
<transactions>
<uncommitted-changes>
<on-project-close value="ASK" />
<on-disconnect value="ASK" />
<on-autocommit-toggle value="ASK" />
</uncommitted-changes>
<multiple-uncommitted-changes>
<on-commit value="ASK" />
<on-rollback value="ASK" />
</multiple-uncommitted-changes>
</transactions>
<session-browser>
<disconnect-session value="ASK" />
<kill-session value="ASK" />
<reload-on-filter-change value="false" />
</session-browser>
<compiler>
<compile-type value="KEEP" />
<compile-dependencies value="ASK" />
<always-show-controls value="false" />
</compiler>
</operation-settings>
<ddl-file-settings>
<extensions>
<mapping file-type-id="VIEW" extensions="vw" />
<mapping file-type-id="TRIGGER" extensions="trg" />
<mapping file-type-id="PROCEDURE" extensions="prc" />
<mapping file-type-id="FUNCTION" extensions="fnc" />
<mapping file-type-id="PACKAGE" extensions="pkg" />
<mapping file-type-id="PACKAGE_SPEC" extensions="pks" />
<mapping file-type-id="PACKAGE_BODY" extensions="pkb" />
<mapping file-type-id="TYPE" extensions="tpe" />
<mapping file-type-id="TYPE_SPEC" extensions="tps" />
<mapping file-type-id="TYPE_BODY" extensions="tpb" />
<mapping file-type-id="JAVA_SOURCE" extensions="sql" />
</extensions>
<general>
<lookup-ddl-files value="true" />
<create-ddl-files value="false" />
<synchronize-ddl-files value="true" />
<use-qualified-names value="false" />
<make-scripts-rerunnable value="true" />
</general>
</ddl-file-settings>
<assistant-settings>
<credential-settings>
<credentials />
</credential-settings>
</assistant-settings>
<general-settings>
<regional-settings>
<date-format value="MEDIUM" />
<number-format value="UNGROUPED" />
<locale value="SYSTEM_DEFAULT" />
<use-custom-formats value="false" />
</regional-settings>
<environment>
<environment-types>
<environment-type id="development" name="Development" description="Development environment" color="-2430209/-12296320" readonly-code="false" readonly-data="false" />
<environment-type id="integration" name="Integration" description="Integration environment" color="-2621494/-12163514" readonly-code="true" readonly-data="false" />
<environment-type id="production" name="Production" description="Productive environment" color="-11574/-10271420" readonly-code="true" readonly-data="true" />
<environment-type id="other" name="Other" description="" color="-1576/-10724543" readonly-code="false" readonly-data="false" />
</environment-types>
<visibility-settings>
<connection-tabs value="true" />
<dialog-headers value="true" />
<object-editor-tabs value="true" />
<script-editor-tabs value="false" />
<execution-result-tabs value="true" />
</visibility-settings>
</environment>
</general-settings>
</component>
</project>

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="UserContentModel"> <component name="ContentModelUserStore">
<attachedFolders /> <attachedFolders />
<explicitIncludes /> <explicitIncludes />
<explicitExcludes /> <explicitExcludes />

8
src/.idea/.idea.Ombi/.idea/modules.xml generated Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/.idea.Ombi/riderModule.iml" filepath="$PROJECT_DIR$/.idea/.idea.Ombi/riderModule.iml" />
</modules>
</component>
</project>

View file

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RiderProjectSettingsUpdater">
<option name="singleClickDiffPreview" value="1" />
<option name="vcsConfiguration" value="3" />
</component>
</project>

View file

@ -1,20 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="57001998-efde-494a-80b3-d7acfc91f770" name="Default Changelist" comment=""> <list default="true" id="57001998-efde-494a-80b3-d7acfc91f770" name="Default Changelist" comment="">
<change beforePath="$PROJECT_DIR$/Ombi/ClientApp/src/app/settings/plex/plex.component.html" beforeDir="false" afterPath="$PROJECT_DIR$/Ombi/ClientApp/src/app/settings/plex/plex.component.html" afterDir="false" /> <change afterPath="$PROJECT_DIR$/Ombi.Core/Engine/Interfaces/IMusicSearchEngineV2.cs" afterDir="false" />
<change afterPath="$PROJECT_DIR$/Ombi.Core/Engine/V2/MusicSearchEngineV2.cs" afterDir="false" />
<change afterPath="$PROJECT_DIR$/Ombi.Core/Models/Search/V2/Music/ArtistInformation.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/.idea.Ombi/.idea/contentModel.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.Ombi/.idea/contentModel.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/.idea.Ombi/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.Ombi/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/config/applicationhost.config" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/config/applicationhost.config" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Ombi.Api.MusicBrainz/Models/Artist/ArtistInformation.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Ombi.Api.MusicBrainz/Models/Artist/ArtistInformation.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Ombi.DependencyInjection/IocExtensions.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Ombi.DependencyInjection/IocExtensions.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Ombi/ClientApp/src/app/media-details/components/artist/artist-details.component.ts" beforeDir="false" afterPath="$PROJECT_DIR$/Ombi/ClientApp/src/app/media-details/components/artist/artist-details.component.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Ombi/ClientApp/src/app/services/searchV2.service.ts" beforeDir="false" afterPath="$PROJECT_DIR$/Ombi/ClientApp/src/app/services/searchV2.service.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Ombi/Controllers/V2/SearchController.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Ombi/Controllers/V2/SearchController.cs" afterDir="false" />
</list> </list>
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" /> <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" /> <option name="LAST_RESOLUTION" value="IGNORE" />
</component> </component>
<component name="DpaMonitoringSettings">
<option name="firstShow" value="false" />
</component>
<component name="FileEditorManager"> <component name="FileEditorManager">
<leaf> <leaf>
<file pinned="false" current-in-tab="false"> <file pinned="false" current-in-tab="false">
@ -232,75 +237,27 @@
<component name="Git.Settings"> <component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." /> <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
</component> </component>
<component name="GitHubPullRequestSearchHistory">{
&quot;lastFilter&quot;: {
&quot;state&quot;: &quot;OPEN&quot;,
&quot;assignee&quot;: &quot;tidusjar&quot;
}
}</component>
<component name="GitToolBoxStore">
<option name="recentBranches">
<RecentBranches>
<option name="branchesForRepo">
<list>
<RecentBranchesForRepo>
<option name="branches">
<list>
<RecentBranch>
<option name="branchName" value="wizard-database" />
<option name="lastUsedInstant" value="1735917525" />
</RecentBranch>
<RecentBranch>
<option name="branchName" value="develop" />
<option name="lastUsedInstant" value="1735917524" />
</RecentBranch>
</list>
</option>
<option name="repositoryRootUrl" value="file://$PROJECT_DIR$/.." />
</RecentBranchesForRepo>
</list>
</option>
</RecentBranches>
</option>
</component>
<component name="GithubProjectSettings">
<option name="branchProtectionPatterns">
<list>
<option value="master" />
<option value="develop" />
</list>
</option>
</component>
<component name="GithubPullRequestsUISettings">{
&quot;selectedUrlAndAccountId&quot;: {
&quot;url&quot;: &quot;https://github.com/ombi-app/ombi&quot;,
&quot;accountId&quot;: &quot;22dd09fe-fb9e-48a4-bfcc-3c152edf3f25&quot;
}
}</component>
<component name="HighlightingSettingsPerFile"> <component name="HighlightingSettingsPerFile">
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/990126b794024fe2bd16aebdd37eba1d7b600/93/25662f04/ServerVersion.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/3bd4df5aff92cabbc4d630be64227073db1b8539b3a1e47786b4b189d7cdb7/DbContext.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/449b441523c469ed34ff5a5e14f0bafcd8f097aa463655303dc19048fa44ac3/EntityFrameworkServiceCollectionExtensions.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/7d81b2d4f22bee75e5438c707251ae43cb0974c207db91ffc159118c84b4eb9/ServiceProvider.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/a424e6912048b4cd25715f158e789aae24db5c2911d9e622d39bc6ac3246c6/MySqlConnectionStringBuilder.cs" root0="SKIP_HIGHLIGHTING" />
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/bd1d5c50194fea68ff3559c160230b0ab50f5acf4ce3061bffd6d62958e2182/ExceptionDispatchInfo.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/e9881a453a581134c1a18331ac1f8f1201a5382a685bf2a40777fa22619/DbContextOptions`.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Api.MusicBrainz/IMusicBrainzApi.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Api.MusicBrainz/MusicBrainzApi.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/Interfaces/IMusicSearchEngineV2.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/MusicSearchEngine.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/RecentlyAddedEngine.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/UserStatsEngine.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/V2/IMultiSearchEngine.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/V2/MultiSearchEngine.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/V2/MusicSearchEngineV2.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Core/Models/Search/V2/Music/ArtistInformation.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.DependencyInjection/IocExtensions.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Helpers.Tests/EmbyHelperTests.cs" root0="FORCE_HIGHLIGHTING" /> <setting file="file://$PROJECT_DIR$/Ombi.Helpers.Tests/EmbyHelperTests.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Api.MusicBrainz/MusicBrainzApi.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Schedule.Tests/OmbiQuartzTests.cs" root0="FORCE_HIGHLIGHTING" /> <setting file="file://$PROJECT_DIR$/Ombi.Schedule.Tests/OmbiQuartzTests.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi/Controllers/V1/TokenController.cs" root0="FORCE_HIGHLIGHTING" /> <setting file="file://$PROJECT_DIR$/Ombi.Api.MusicBrainz/Models/Artist/ArtistInformation.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi/Controllers/V2/SearchController.cs" root0="FORCE_HIGHLIGHTING" /> <setting file="file://$PROJECT_DIR$/Ombi/Controllers/V2/SearchController.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.DependencyInjection/IocExtensions.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/V2/MultiSearchEngine.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/V2/IMultiSearchEngine.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Api.MusicBrainz/IMusicBrainzApi.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/Interfaces/IMusicSearchEngineV2.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Core/Models/Search/V2/Music/ArtistInformation.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="mock:///Dummy.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/V2/MusicSearchEngineV2.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/RecentlyAddedEngine.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="mock:///Dummy.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi/Controllers/V1/TokenController.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/MusicSearchEngine.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi/Program.cs" root0="FORCE_HIGHLIGHTING" /> <setting file="file://$PROJECT_DIR$/Ombi/Program.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/UserStatsEngine.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="mock:///Dummy.cs" root0="FORCE_HIGHLIGHTING" />
</component> </component>
<component name="IdeDocumentHistory"> <component name="IdeDocumentHistory">
<option name="CHANGED_PATHS"> <option name="CHANGED_PATHS">
@ -318,17 +275,12 @@
<component name="PackageJsonUpdateNotifier"> <component name="PackageJsonUpdateNotifier">
<dismissed value="$PROJECT_DIR$/Ombi/ClientApp/package.json" /> <dismissed value="$PROJECT_DIR$/Ombi/ClientApp/package.json" />
</component> </component>
<component name="ProjectColorInfo">{
&quot;customColor&quot;: &quot;&quot;,
&quot;associatedIndex&quot;: 0
}</component>
<component name="ProjectFrameBounds" extendedState="6"> <component name="ProjectFrameBounds" extendedState="6">
<option name="x" value="1087" /> <option name="x" value="1087" />
<option name="y" value="-1113" /> <option name="y" value="-1113" />
<option name="width" value="1400" /> <option name="width" value="1400" />
<option name="height" value="1000" /> <option name="height" value="1000" />
</component> </component>
<component name="ProjectId" id="2wGwbN5gDqLwyiO1WJdlwJzZ5M9" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true"> <component name="ProjectLevelVcsManager" settingsEditedManually="true">
<ConfirmationsSetting value="2" id="Add" /> <ConfirmationsSetting value="2" id="Add" />
</component> </component>
@ -391,26 +343,27 @@
<pane id="FileSystemExplorer" /> <pane id="FileSystemExplorer" />
</panes> </panes>
</component> </component>
<component name="ProjectViewState"> <component name="PropertiesComponent">
<option name="hideEmptyMiddlePackages" value="true" /> <property name="ASKED_SHARE_PROJECT_CONFIGURATION_FILES" value="true" />
<option name="showLibraryContents" value="true" /> <property name="Rider.DefaultBreakpoints.AreToggled" value="true" />
<property name="Rider.ProjectViewActivator.IsNotFirstRun" value="true" />
<property name="SHARE_PROJECT_CONFIGURATION_FILES" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="nodejs_package_manager_path" value="npm" />
</component> </component>
<component name="PropertiesComponent"><![CDATA[{ <component name="RunDashboard">
"keyToString": { <option name="ruleStates">
".NET Launch Settings Profile.Ombi.Schedule.Tests.executor": "Run", <list>
".NET Launch Settings Profile.Ombi.executor": "Debug", <RuleState>
"RunOnceActivity.ShowReadmeOnStart": "true", <option name="name" value="ConfigurationTypeDashboardGroupingRule" />
"RunOnceActivity.git.unshallow": "true", </RuleState>
"fb34c741-04ca-4b4f-8ea1-651a011b42c8.executor": "Debug", <RuleState>
"git-widget-placeholder": "watchlist-expired-notification", <option name="name" value="StatusDashboardGroupingRule" />
"node.js.detected.package.eslint": "true", </RuleState>
"node.js.selected.package.eslint": "(autodetect)", </list>
"node.js.selected.package.tslint": "(autodetect)", </option>
"nodejs_package_manager_path": "yarn", </component>
"vue.rearranger.settings.migration": "true" <component name="RunManager" selected=".NET Launch Settings Profile.Ombi: IIS Express">
}
}]]></component>
<component name="RunManager" selected=".NET Launch Settings Profile.Ombi">
<configuration name="Ombi" type="LaunchSettings" factoryName=".NET Launch Settings Profile"> <configuration name="Ombi" type="LaunchSettings" factoryName=".NET Launch Settings Profile">
<option name="LAUNCH_PROFILE_PROJECT_FILE_PATH" value="$PROJECT_DIR$/Ombi/Ombi.csproj" /> <option name="LAUNCH_PROFILE_PROJECT_FILE_PATH" value="$PROJECT_DIR$/Ombi/Ombi.csproj" />
<option name="LAUNCH_PROFILE_TFM" value=".NETCoreApp,Version=v2.2" /> <option name="LAUNCH_PROFILE_TFM" value=".NETCoreApp,Version=v2.2" />
@ -423,7 +376,7 @@
<option name="SEND_DEBUG_REQUEST" value="1" /> <option name="SEND_DEBUG_REQUEST" value="1" />
<option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" /> <option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" />
<method v="2"> <method v="2">
<option name="Build" /> <option name="Build" enabled="true" />
</method> </method>
</configuration> </configuration>
<configuration name="Ombi: IIS Express" type="LaunchSettings" factoryName=".NET Launch Settings Profile"> <configuration name="Ombi: IIS Express" type="LaunchSettings" factoryName=".NET Launch Settings Profile">
@ -438,7 +391,7 @@
<option name="SEND_DEBUG_REQUEST" value="1" /> <option name="SEND_DEBUG_REQUEST" value="1" />
<option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" /> <option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" />
<method v="2"> <method v="2">
<option name="Build" /> <option name="Build" enabled="true" />
</method> </method>
</configuration> </configuration>
<configuration name="Ombi.Schedule.Tests" type="LaunchSettings" factoryName=".NET Launch Settings Profile"> <configuration name="Ombi.Schedule.Tests" type="LaunchSettings" factoryName=".NET Launch Settings Profile">
@ -453,7 +406,7 @@
<option name="SEND_DEBUG_REQUEST" value="1" /> <option name="SEND_DEBUG_REQUEST" value="1" />
<option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" /> <option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" />
<method v="2"> <method v="2">
<option name="Build" /> <option name="Build" enabled="true" />
</method> </method>
</configuration> </configuration>
<configuration name="Ombi.Schedule.Tests: IIS Express" type="LaunchSettings" factoryName=".NET Launch Settings Profile"> <configuration name="Ombi.Schedule.Tests: IIS Express" type="LaunchSettings" factoryName=".NET Launch Settings Profile">
@ -468,7 +421,7 @@
<option name="SEND_DEBUG_REQUEST" value="1" /> <option name="SEND_DEBUG_REQUEST" value="1" />
<option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" /> <option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" />
<method v="2"> <method v="2">
<option name="Build" /> <option name="Build" enabled="true" />
</method> </method>
</configuration> </configuration>
<configuration name="Ombi.Updater" type="LaunchSettings" factoryName=".NET Launch Settings Profile"> <configuration name="Ombi.Updater" type="LaunchSettings" factoryName=".NET Launch Settings Profile">
@ -483,11 +436,10 @@
<option name="SEND_DEBUG_REQUEST" value="1" /> <option name="SEND_DEBUG_REQUEST" value="1" />
<option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" /> <option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" />
<method v="2"> <method v="2">
<option name="Build" /> <option name="Build" enabled="true" />
</method> </method>
</configuration> </configuration>
</component> </component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager"> <component name="TaskManager">
<task active="true" id="Default" summary="Default task"> <task active="true" id="Default" summary="Default task">
<changelist id="57001998-efde-494a-80b3-d7acfc91f770" name="Default Changelist" comment="" /> <changelist id="57001998-efde-494a-80b3-d7acfc91f770" name="Default Changelist" comment="" />
@ -496,9 +448,6 @@
<option name="presentableId" value="Default" /> <option name="presentableId" value="Default" />
<updated>1563957157468</updated> <updated>1563957157468</updated>
<workItem from="1563957162999" duration="5401000" /> <workItem from="1563957162999" duration="5401000" />
<workItem from="1745681294313" duration="1814000" />
<workItem from="1747080279165" duration="838000" />
<workItem from="1747082180432" duration="1994000" />
</task> </task>
<servers /> <servers />
</component> </component>
@ -544,11 +493,7 @@
</layout> </layout>
</component> </component>
<component name="TypeScriptGeneratedFilesManager"> <component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" /> <option name="version" value="1" />
</component>
<component name="UnityProjectConfiguration" hasMinimizedUI="false" />
<component name="VcsManagerConfiguration">
<option name="CLEAR_INITIAL_COMMIT_MESSAGE" value="true" />
</component> </component>
<component name="XDebuggerManager"> <component name="XDebuggerManager">
<breakpoint-manager> <breakpoint-manager>
@ -560,7 +505,7 @@
<line-breakpoint enabled="true" type="DotNet Breakpoints"> <line-breakpoint enabled="true" type="DotNet Breakpoints">
<url>file://$PROJECT_DIR$/Ombi/Controllers/V1/TokenController.cs</url> <url>file://$PROJECT_DIR$/Ombi/Controllers/V1/TokenController.cs</url>
<line>48</line> <line>48</line>
<properties documentPath="$PROJECT_DIR$/Ombi/Controllers/V1/TokenController.cs"> <properties documentPath="$PROJECT_DIR$/Ombi/Controllers/V1/TokenController.cs" initialLine="48">
<startOffsets> <startOffsets>
<option value="1518" /> <option value="1518" />
</startOffsets> </startOffsets>
@ -573,12 +518,12 @@
<line-breakpoint enabled="true" type="DotNet Breakpoints"> <line-breakpoint enabled="true" type="DotNet Breakpoints">
<url>file://$PROJECT_DIR$/Ombi.Core/Engine/V2/MultiSearchEngine.cs</url> <url>file://$PROJECT_DIR$/Ombi.Core/Engine/V2/MultiSearchEngine.cs</url>
<line>59</line> <line>59</line>
<properties documentPath="$PROJECT_DIR$/Ombi.Core/Engine/V2/MultiSearchEngine.cs" containingFunctionPresentation="Method 'MultiSearch'"> <properties documentPath="$PROJECT_DIR$/Ombi.Core/Engine/V2/MultiSearchEngine.cs" initialLine="59">
<startOffsets> <startOffsets>
<option value="2369" /> <option value="2276" />
</startOffsets> </startOffsets>
<endOffsets> <endOffsets>
<option value="2576" /> <option value="2316" />
</endOffsets> </endOffsets>
</properties> </properties>
<option name="timeStamp" value="4" /> <option name="timeStamp" value="4" />
@ -586,12 +531,12 @@
<line-breakpoint enabled="true" type="DotNet Breakpoints"> <line-breakpoint enabled="true" type="DotNet Breakpoints">
<url>file://$PROJECT_DIR$/Ombi.Core/Engine/V2/MultiSearchEngine.cs</url> <url>file://$PROJECT_DIR$/Ombi.Core/Engine/V2/MultiSearchEngine.cs</url>
<line>49</line> <line>49</line>
<properties documentPath="$PROJECT_DIR$/Ombi.Core/Engine/V2/MultiSearchEngine.cs" containingFunctionPresentation="Method 'MultiSearch'"> <properties documentPath="$PROJECT_DIR$/Ombi.Core/Engine/V2/MultiSearchEngine.cs" initialLine="49">
<startOffsets> <startOffsets>
<option value="1903" /> <option value="2001" />
</startOffsets> </startOffsets>
<endOffsets> <endOffsets>
<option value="1945" /> <option value="2002" />
</endOffsets> </endOffsets>
</properties> </properties>
<option name="timeStamp" value="5" /> <option name="timeStamp" value="5" />
@ -599,55 +544,16 @@
<line-breakpoint enabled="true" type="DotNet Breakpoints"> <line-breakpoint enabled="true" type="DotNet Breakpoints">
<url>file://$PROJECT_DIR$/Ombi.Api.MusicBrainz/MusicBrainzApi.cs</url> <url>file://$PROJECT_DIR$/Ombi.Api.MusicBrainz/MusicBrainzApi.cs</url>
<line>30</line> <line>30</line>
<properties documentPath="$PROJECT_DIR$/Ombi.Api.MusicBrainz/MusicBrainzApi.cs" containingFunctionPresentation="Method 'SearchArtist'"> <properties documentPath="$PROJECT_DIR$/Ombi.Api.MusicBrainz/MusicBrainzApi.cs" initialLine="30">
<startOffsets> <startOffsets>
<option value="833" /> <option value="917" />
</startOffsets> </startOffsets>
<endOffsets> <endOffsets>
<option value="834" /> <option value="1016" />
</endOffsets> </endOffsets>
</properties> </properties>
<option name="timeStamp" value="7" /> <option name="timeStamp" value="7" />
</line-breakpoint> </line-breakpoint>
<line-breakpoint enabled="true" type="DotNet Breakpoints">
<url>file://$PROJECT_DIR$/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs</url>
<line>110</line>
<properties documentPath="$PROJECT_DIR$/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs" containingFunctionPresentation="Method 'Execute'">
<startOffsets>
<option value="5123" />
</startOffsets>
<endOffsets>
<option value="5206" />
</endOffsets>
</properties>
<option name="timeStamp" value="10" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DotNet Breakpoints">
<url>file://$PROJECT_DIR$/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs</url>
<line>77</line>
<properties documentPath="$PROJECT_DIR$/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs" containingFunctionPresentation="Method 'Execute'">
<startOffsets>
<option value="3324" />
</startOffsets>
<endOffsets>
<option value="3365" />
</endOffsets>
</properties>
<option name="timeStamp" value="11" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DotNet Breakpoints">
<url>file://$PROJECT_DIR$/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs</url>
<line>100</line>
<properties documentPath="$PROJECT_DIR$/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs" containingFunctionPresentation="Method 'Execute'">
<startOffsets>
<option value="4602" />
</startOffsets>
<endOffsets>
<option value="4636" />
</endOffsets>
</properties>
<option name="timeStamp" value="12" />
</line-breakpoint>
</breakpoints> </breakpoints>
</breakpoint-manager> </breakpoint-manager>
<watches-manager> <watches-manager>

14
src/.idea/.idea.Ombi/riderModule.iml generated Normal file
View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="RIDER_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$USER_HOME$/.nuget/packages/microsoft.net.test.sdk/16.0.1/build/netcoreapp1.0" />
<content url="file://$USER_HOME$/.nuget/packages/nunit3testadapter/3.13.0/build/netcoreapp1.0/NUnit3.TestAdapter.dll" />
<content url="file://$USER_HOME$/.nuget/packages/nunit3testadapter/3.13.0/build/netcoreapp1.0/NUnit3.TestAdapter.pdb" />
<content url="file://$USER_HOME$/.nuget/packages/nunit3testadapter/3.13.0/build/netcoreapp1.0/nunit.engine.netstandard.dll" />
<content url="file://$MODULE_DIR$/../../../CHANGELOG.md" />
<content url="file://$MODULE_DIR$/../../../appveyor.yml" />
<content url="file://$MODULE_DIR$/../../../build.cake" />
<content url="file://$MODULE_DIR$/../.." />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View file

@ -1,31 +1,22 @@
{ {
"version": "2.0.0", "version": "0.1.0",
"command": "dotnet", "command": "dotnet",
"isShellCommand": true,
"args": [], "args": [],
"tasks": [ "tasks": [
{ {
"label": "build", "taskName": "build",
"type": "shell",
"command": "dotnet",
"args": [ "args": [
"build",
"${workspaceRoot}/Ombi/Ombi.csproj" "${workspaceRoot}/Ombi/Ombi.csproj"
], ],
"problemMatcher": "$msCompile", "isBuildCommand": true,
"group": { "problemMatcher": "$msCompile"
"_id": "build",
"isDefault": false
}
}, },
{ {
"label": "lint", "taskName": "lint",
"type": "shell",
"command": "npm", "command": "npm",
"args": [ "isShellCommand": true,
"run", "args": ["run", "lint"]
"lint"
],
"problemMatcher": []
} }
] ]
} }

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<Configurations>Debug;Release;NonUiBuild</Configurations> <Configurations>Debug;Release;NonUiBuild</Configurations>
</PropertyGroup> </PropertyGroup>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<Configurations>Debug;Release;NonUiBuild</Configurations> <Configurations>Debug;Release;NonUiBuild</Configurations>
</PropertyGroup> </PropertyGroup>

View file

@ -7,7 +7,6 @@ namespace Ombi.Api.Discord.Models
{ {
public string content { get; set; } public string content { get; set; }
public string username { get; set; } public string username { get; set; }
public string avatar_url { get; set; }
public List<DiscordEmbeds> embeds { get; set; } public List<DiscordEmbeds> embeds { get; set; }
} }
@ -33,6 +32,7 @@ namespace Ombi.Api.Discord.Models
{ {
public string name { get; set; } public string name { get; set; }
public string url { get; set; } public string url { get; set; }
public string iconurl { get; set; }
} }
public class DiscordField public class DiscordField

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<Configurations>Debug;Release;NonUiBuild</Configurations> <Configurations>Debug;Release;NonUiBuild</Configurations>
</PropertyGroup> </PropertyGroup>

View file

@ -56,7 +56,7 @@ namespace Ombi.Api.Emby
return obj; return obj;
} }
public async Task<EmbyUser> LogIn(string username, string password, string apiKey, string baseUri, string clientIpAddress) public async Task<EmbyUser> LogIn(string username, string password, string apiKey, string baseUri)
{ {
var request = new Request("emby/users/authenticatebyname", baseUri, HttpMethod.Post); var request = new Request("emby/users/authenticatebyname", baseUri, HttpMethod.Post);
var body = new var body = new
@ -71,11 +71,6 @@ namespace Ombi.Api.Emby
$"MediaBrowser Client=\"Ombi\", Device=\"Ombi\", DeviceId=\"v3\", Version=\"v3\""); $"MediaBrowser Client=\"Ombi\", Device=\"Ombi\", DeviceId=\"v3\", Version=\"v3\"");
AddHeaders(request, apiKey); AddHeaders(request, apiKey);
if (!string.IsNullOrEmpty(clientIpAddress))
{
request.AddHeader("X-Forwarded-For", clientIpAddress);
}
var obj = await Api.Request<EmbyUser>(request); var obj = await Api.Request<EmbyUser>(request);
return obj; return obj;
} }
@ -253,49 +248,5 @@ namespace Ombi.Api.Emby
req.AddContentHeader("Content-Type", "application/json"); req.AddContentHeader("Content-Type", "application/json");
req.AddHeader("Device", "Ombi"); req.AddHeader("Device", "Ombi");
} }
public async Task<EmbyItemContainer<EmbyMovie>> GetMoviesPlayed(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri) =>
await GetPlayed<EmbyMovie>("Movie", apiKey, userId, baseUri, startIndex, count, parentIdFilder, "ProviderIds");
public async Task<EmbyItemContainer<EmbyEpisodes>> GetTvPlayed(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri) =>
await GetPlayed<EmbyEpisodes>("Episode", apiKey, userId, baseUri, startIndex, count, parentIdFilder);
private async Task<EmbyItemContainer<T>> GetPlayed<T>(
string type,
string apiKey,
string userId,
string baseUri,
int startIndex,
int count,
string parentIdFilder = default,
string fields = default)
{
var request = new Request($"emby/items", baseUri, HttpMethod.Get);
request.AddQueryString("Recursive", true.ToString());
request.AddQueryString("IncludeItemTypes", type);
if (!string.IsNullOrEmpty(fields))
{
request.AddQueryString("Fields", fields);
}
request.AddQueryString("UserId", userId);
request.AddQueryString("isPlayed", true.ToString());
// paginate and display recently played items first
request.AddQueryString("sortBy", "DatePlayed");
request.AddQueryString("SortOrder", "Descending");
request.AddQueryString("startIndex", startIndex.ToString());
request.AddQueryString("limit", count.ToString());
if (!string.IsNullOrEmpty(parentIdFilder))
{
request.AddQueryString("ParentId", parentIdFilder);
}
AddHeaders(request, apiKey);
var obj = await Api.Request<EmbyItemContainer<T>>(request);
return obj;
}
} }
} }

View file

@ -11,7 +11,7 @@ namespace Ombi.Api.Emby
{ {
Task<EmbySystemInfo> GetSystemInformation(string apiKey, string baseUrl); Task<EmbySystemInfo> GetSystemInformation(string apiKey, string baseUrl);
Task<List<EmbyUser>> GetUsers(string baseUri, string apiKey); Task<List<EmbyUser>> GetUsers(string baseUri, string apiKey);
Task<EmbyUser> LogIn(string username, string password, string apiKey, string baseUri, string clientIpAddress); Task<EmbyUser> LogIn(string username, string password, string apiKey, string baseUri);
Task<EmbyItemContainer<EmbyMovie>> GetAllMovies(string apiKey, string parentIdFilder, int startIndex, int count, string userId, Task<EmbyItemContainer<EmbyMovie>> GetAllMovies(string apiKey, string parentIdFilder, int startIndex, int count, string userId,
string baseUri); string baseUri);
@ -32,8 +32,5 @@ namespace Ombi.Api.Emby
Task<EmbyItemContainer<EmbyMovie>> RecentlyAddedMovies(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri); Task<EmbyItemContainer<EmbyMovie>> RecentlyAddedMovies(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri);
Task<EmbyItemContainer<EmbyEpisodes>> RecentlyAddedEpisodes(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri); Task<EmbyItemContainer<EmbyEpisodes>> RecentlyAddedEpisodes(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri);
Task<EmbyItemContainer<EmbySeries>> RecentlyAddedShows(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri); Task<EmbyItemContainer<EmbySeries>> RecentlyAddedShows(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri);
Task<EmbyItemContainer<EmbyMovie>> GetMoviesPlayed(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri);
Task<EmbyItemContainer<EmbyEpisodes>> GetTvPlayed(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri);
} }
} }

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<Configurations>Debug;Release;NonUiBuild</Configurations> <Configurations>Debug;Release;NonUiBuild</Configurations>
</PropertyGroup> </PropertyGroup>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<Configurations>Debug;Release;NonUiBuild</Configurations> <Configurations>Debug;Release;NonUiBuild</Configurations>
</PropertyGroup> </PropertyGroup>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<Configurations>Debug;Release;NonUiBuild</Configurations> <Configurations>Debug;Release;NonUiBuild</Configurations>
</PropertyGroup> </PropertyGroup>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<Configurations>Debug;Release;NonUiBuild</Configurations> <Configurations>Debug;Release;NonUiBuild</Configurations>
</PropertyGroup> </PropertyGroup>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<Configurations>Debug;Release;NonUiBuild</Configurations> <Configurations>Debug;Release;NonUiBuild</Configurations>
</PropertyGroup> </PropertyGroup>

View file

@ -21,7 +21,7 @@ namespace Ombi.Api.Plex
Task<PlexMetadata> GetMetadata(string authToken, string plexFullHost, string itemId); Task<PlexMetadata> GetMetadata(string authToken, string plexFullHost, string itemId);
Task<PlexMetadata> GetSeasons(string authToken, string plexFullHost, string ratingKey); Task<PlexMetadata> GetSeasons(string authToken, string plexFullHost, string ratingKey);
Task<PlexContainer> GetAllEpisodes(string authToken, string host, string section, int start, int retCount); Task<PlexContainer> GetAllEpisodes(string authToken, string host, string section, int start, int retCount);
Task<PlexUsers> GetUsers(string authToken); Task<PlexFriends> GetUsers(string authToken);
Task<PlexAccount> GetAccount(string authToken); Task<PlexAccount> GetAccount(string authToken);
Task<PlexMetadata> GetRecentlyAdded(string authToken, string uri, string sectionId); Task<PlexMetadata> GetRecentlyAdded(string authToken, string uri, string sectionId);
Task<OAuthContainer> GetPin(int pinId); Task<OAuthContainer> GetPin(int pinId);
@ -29,6 +29,5 @@ namespace Ombi.Api.Plex
Task<PlexAddWrapper> AddUser(string emailAddress, string serverId, string authToken, int[] libs); Task<PlexAddWrapper> AddUser(string emailAddress, string serverId, string authToken, int[] libs);
Task<PlexWatchlistContainer> GetWatchlist(string plexToken, CancellationToken cancellationToken); Task<PlexWatchlistContainer> GetWatchlist(string plexToken, CancellationToken cancellationToken);
Task<PlexWatchlistMetadataContainer> GetWatchlistMetadata(string ratingKey, string plexToken, CancellationToken cancellationToken); Task<PlexWatchlistMetadataContainer> GetWatchlistMetadata(string ratingKey, string plexToken, CancellationToken cancellationToken);
Task<bool> Ping(string authToken, CancellationToken cancellationToken = default);
} }
} }

View file

@ -2,42 +2,46 @@
namespace Ombi.Api.Plex.Models.Friends namespace Ombi.Api.Plex.Models.Friends
{ {
[XmlRoot(ElementName = "User")] [XmlRoot(ElementName = "Server")]
public class UserFriends public class Server
{ {
[XmlAttribute(AttributeName = "id")] [XmlAttribute(AttributeName = "id")]
public string Id { get; set; } public string Id { get; set; }
/// <summary> [XmlAttribute(AttributeName = "serverId")]
/// Title is for Home Users only public string ServerId { get; set; }
/// </summary> [XmlAttribute(AttributeName = "machineIdentifier")]
public string MachineIdentifier { get; set; }
[XmlAttribute(AttributeName = "name")]
public string Name { get; set; }
[XmlAttribute(AttributeName = "lastSeenAt")]
public string LastSeenAt { get; set; }
[XmlAttribute(AttributeName = "numLibraries")]
public string NumLibraries { get; set; }
[XmlAttribute(AttributeName = "owned")]
public string Owned { get; set; }
}
[XmlRoot(ElementName = "User")]
public class UserFriends
{
[XmlElement(ElementName = "Server")]
public Server Server { get; set; }
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
[XmlAttribute(AttributeName = "title")] [XmlAttribute(AttributeName = "title")]
public string Title { get; set; } public string Title { get; set; }
[XmlAttribute(AttributeName = "username")] [XmlAttribute(AttributeName = "username")]
public string Username { get; set; } public string Username { get; set; }
[XmlAttribute(AttributeName = "email")] [XmlAttribute(AttributeName = "email")]
public string Email { get; set; } public string Email { get; set; }
/// <summary> [XmlAttribute(AttributeName = "recommendationsPlaylistId")]
/// DO NOT USE THIS public string RecommendationsPlaylistId { get; set; }
/// Home Users can actually be an unmanaged account with an email/username to log in. [XmlAttribute(AttributeName = "thumb")]
/// </summary> public string Thumb { get; set; }
[XmlAttribute(AttributeName = "home")]
public bool HomeUser { get; set; }
[XmlElement(ElementName = "Server")]
public PlexUserServer[] Server { get; set; }
}
public class PlexUserServer
{
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
[XmlAttribute(AttributeName = "serverId")]
public string ServerId { get; set; }
} }
[XmlRoot(ElementName = "MediaContainer")] [XmlRoot(ElementName = "MediaContainer")]
public class PlexUsers public class PlexFriends
{ {
[XmlElement(ElementName = "User")] [XmlElement(ElementName = "User")]
public UserFriends[] User { get; set; } public UserFriends[] User { get; set; }

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>

View file

@ -65,10 +65,10 @@ namespace Ombi.Api.Plex
} }
private const string SignInUri = "https://plex.tv/users/sign_in.json"; private const string SignInUri = "https://plex.tv/users/sign_in.json";
private const string FriendsUri = "https://plex.tv/api/users"; private const string FriendsUri = "https://plex.tv/pms/friends/all";
private const string GetAccountUri = "https://plex.tv/users/account.json"; private const string GetAccountUri = "https://plex.tv/users/account.json";
private const string ServerUri = "https://plex.tv/pms/servers.xml"; private const string ServerUri = "https://plex.tv/pms/servers.xml";
private const string WatchlistUri = "https://discover.provider.plex.tv/"; private const string WatchlistUri = "https://metadata.provider.plex.tv/";
/// <summary> /// <summary>
/// Sign into the Plex API /// Sign into the Plex API
@ -195,12 +195,12 @@ namespace Ombi.Api.Plex
/// </summary> /// </summary>
/// <param name="authToken"></param> /// <param name="authToken"></param>
/// <returns></returns> /// <returns></returns>
public async Task<PlexUsers> GetUsers(string authToken) public async Task<PlexFriends> GetUsers(string authToken)
{ {
var request = new Request(string.Empty, FriendsUri, HttpMethod.Get, ContentType.Xml); var request = new Request(string.Empty, FriendsUri, HttpMethod.Get, ContentType.Xml);
await AddHeaders(request, authToken); await AddHeaders(request, authToken);
return await Api.Request<PlexUsers>(request); return await Api.Request<PlexFriends>(request);
} }
public async Task<PlexMetadata> GetRecentlyAdded(string authToken, string uri, string sectionId) public async Task<PlexMetadata> GetRecentlyAdded(string authToken, string uri, string sectionId)
@ -320,30 +320,6 @@ namespace Ombi.Api.Plex
return result; return result;
} }
/// <summary>
/// Pings the Plex API to validate if a token is still valid
/// </summary>
/// <param name="authToken">The authentication token to validate</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>True if the token is valid, false otherwise</returns>
public async Task<bool> Ping(string authToken, CancellationToken cancellationToken = default)
{
try
{
var request = new Request("api/v2/ping", "https://plex.tv/", HttpMethod.Get);
await AddHeaders(request, authToken);
// We don't need to parse the response, just check if the request succeeds
await Api.Request(request, cancellationToken);
return true;
}
catch
{
// If the request fails (401, 403, etc.), the token is invalid
return false;
}
}
/// <summary> /// <summary>
/// Adds the required headers and also the authorization header /// Adds the required headers and also the authorization header

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>
@ -11,7 +11,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<Configurations>Debug;Release;NonUiBuild</Configurations> <Configurations>Debug;Release;NonUiBuild</Configurations>
</PropertyGroup> </PropertyGroup>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>
@ -13,7 +13,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.2" /> <PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<Configurations>Debug;Release;NonUiBuild</Configurations> <Configurations>Debug;Release;NonUiBuild</Configurations>
</PropertyGroup> </PropertyGroup>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>

View file

@ -49,7 +49,7 @@ namespace Ombi.Api.Sonarr
public async Task<List<MonitoredEpisodeResult>> MonitorEpisode(int[] episodeIds, bool monitor, string apiKey, string baseUrl) public async Task<List<MonitoredEpisodeResult>> MonitorEpisode(int[] episodeIds, bool monitor, string apiKey, string baseUrl)
{ {
var request = new Request($"{ApiBaseUrl}episode/monitor", baseUrl, HttpMethod.Put); var request = new Request($"{ApiBaseUrl}Episode/monitor", baseUrl, HttpMethod.Put);
request.AddHeader("X-Api-Key", apiKey); request.AddHeader("X-Api-Key", apiKey);
request.AddJsonBody(new { episodeIds = episodeIds, monitored = monitor }); request.AddJsonBody(new { episodeIds = episodeIds, monitored = monitor });
return await Api.Request<List<MonitoredEpisodeResult>>(request); return await Api.Request<List<MonitoredEpisodeResult>>(request);

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<Configurations>Debug;Release;NonUiBuild</Configurations> <Configurations>Debug;Release;NonUiBuild</Configurations>
</PropertyGroup> </PropertyGroup>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<Configurations>Debug;Release;NonUiBuild</Configurations> <Configurations>Debug;Release;NonUiBuild</Configurations>
</PropertyGroup> </PropertyGroup>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>
@ -11,8 +11,8 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Polly" Version="7.2.3" /> <PackageReference Include="Polly" Version="7.2.3" />
</ItemGroup> </ItemGroup>

View file

@ -52,7 +52,6 @@ namespace Ombi.Core.Tests.Engine
_subject = _mocker.CreateInstance<MovieRequestEngine>(); _subject = _mocker.CreateInstance<MovieRequestEngine>();
var list = DbHelper.GetQueryableMockDbSet(new RequestSubscription()); var list = DbHelper.GetQueryableMockDbSet(new RequestSubscription());
_mocker.Setup<IRepository<RequestSubscription>, IQueryable<RequestSubscription>>(x => x.GetAll()).Returns(new List<RequestSubscription>().AsQueryable().BuildMock()); _mocker.Setup<IRepository<RequestSubscription>, IQueryable<RequestSubscription>>(x => x.GetAll()).Returns(new List<RequestSubscription>().AsQueryable().BuildMock());
_mocker.Setup<IUserPlayedMovieRepository, IQueryable<UserPlayedMovie>>(x => x.GetAll()).Returns(new List<UserPlayedMovie>().AsQueryable().BuildMock());
} }
[Test] [Test]

View file

@ -300,13 +300,13 @@ namespace Ombi.Core.Tests.Engine
{ {
UserId = "id1", UserId = "id1",
RequestType = RequestType.Movie, RequestType = RequestType.Movie,
RequestDate = today.AddMinutes(-1), RequestDate = today.AddHours(-1),
}, },
new RequestLog new RequestLog
{ {
UserId = "id1", UserId = "id1",
RequestType = RequestType.Movie, RequestType = RequestType.Movie,
RequestDate = today.AddMinutes(-2), RequestDate = today.AddHours(-2),
}, },
}; };
var repoMock = _mocker.GetMock<IRepository<RequestLog>>(); var repoMock = _mocker.GetMock<IRepository<RequestLog>>();

View file

@ -298,13 +298,13 @@ namespace Ombi.Core.Tests.Engine
{ {
UserId = "id1", UserId = "id1",
RequestType = RequestType.Album, RequestType = RequestType.Album,
RequestDate = today.AddMinutes(-1), RequestDate = today.AddHours(-1),
}, },
new RequestLog new RequestLog
{ {
UserId = "id1", UserId = "id1",
RequestType = RequestType.Album, RequestType = RequestType.Album,
RequestDate = today.AddMinutes(-2), RequestDate = today.AddHours(-2),
}, },
}; };
var repoMock = _mocker.GetMock<IRepository<RequestLog>>(); var repoMock = _mocker.GetMock<IRepository<RequestLog>>();

View file

@ -304,7 +304,7 @@ namespace Ombi.Core.Tests.Engine
{ {
UserId = "id1", UserId = "id1",
RequestType = RequestType.TvShow, RequestType = RequestType.TvShow,
RequestDate = today.AddMinutes(-1), RequestDate = today.AddHours(-1),
EpisodeCount = 1, EpisodeCount = 1,
}, },
new RequestLog new RequestLog
@ -312,7 +312,7 @@ namespace Ombi.Core.Tests.Engine
UserId = "id1", UserId = "id1",
RequestType = RequestType.TvShow, RequestType = RequestType.TvShow,
EpisodeCount = 1, EpisodeCount = 1,
RequestDate = today.AddMinutes(-2), RequestDate = today.AddHours(-2),
}, },
}; };
var repoMock = _mocker.GetMock<IRepository<RequestLog>>(); var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
@ -345,7 +345,7 @@ namespace Ombi.Core.Tests.Engine
{ {
UserId = "id1", UserId = "id1",
RequestType = RequestType.TvShow, RequestType = RequestType.TvShow,
RequestDate = today.AddMinutes(-1), RequestDate = today.AddHours(-1),
EpisodeCount = 5, EpisodeCount = 5,
}, },
new RequestLog new RequestLog
@ -353,7 +353,7 @@ namespace Ombi.Core.Tests.Engine
UserId = "id1", UserId = "id1",
RequestType = RequestType.TvShow, RequestType = RequestType.TvShow,
EpisodeCount = 4, EpisodeCount = 4,
RequestDate = today.AddMinutes(-2), RequestDate = today.AddHours(-2),
}, },
}; };
var repoMock = _mocker.GetMock<IRepository<RequestLog>>(); var repoMock = _mocker.GetMock<IRepository<RequestLog>>();

View file

@ -46,9 +46,8 @@ namespace Ombi.Core.Tests.Engine.V2
var requestSubs = new Mock<IRepository<RequestSubscription>>(); var requestSubs = new Mock<IRepository<RequestSubscription>>();
var mediaCache = new Mock<IMediaCacheService>(); var mediaCache = new Mock<IMediaCacheService>();
var featureService = new Mock<IFeatureService>(); var featureService = new Mock<IFeatureService>();
var userPlayedMovieRepository = new Mock<IUserPlayedMovieRepository>();
_engine = new MovieRequestEngine(movieApi.Object, requestService.Object, user.Object, notificationHelper.Object, rules.Object, movieSender.Object, _engine = new MovieRequestEngine(movieApi.Object, requestService.Object, user.Object, notificationHelper.Object, rules.Object, movieSender.Object,
logger.Object, userManager.Object, requestLogRepo.Object, cache.Object, ombiSettings.Object, requestSubs.Object, mediaCache.Object, featureService.Object, userPlayedMovieRepository.Object); logger.Object, userManager.Object, requestLogRepo.Object, cache.Object, ombiSettings.Object, requestSubs.Object, mediaCache.Object, featureService.Object);
} }
[Test] [Test]

View file

@ -1,15 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType> <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<Configurations>Debug;Release;NonUiBuild</Configurations> <Configurations>Debug;Release;NonUiBuild</Configurations>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AutoFixture" Version="4.18.0" /> <PackageReference Include="AutoFixture" Version="4.17.0" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" /> <PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
<PackageReference Include="Moq" Version="4.18.2" /> <PackageReference Include="Moq" Version="4.18.2" />
<PackageReference Include="Moq.AutoMock" Version="3.4.0" /> <PackageReference Include="Moq.AutoMock" Version="3.4.0" />
<PackageReference Include="Nunit" Version="3.13.3" /> <PackageReference Include="Nunit" Version="3.13.3" />
@ -18,7 +18,8 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<packagereference Include="Microsoft.NET.Test.Sdk" Version="17.6.2"></packagereference> <PackageReference Include="Microsoft.AspNetCore.Identity" Version="2.2.0" />
<packagereference Include="Microsoft.NET.Test.Sdk" Version="17.3.2"></packagereference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -54,17 +54,6 @@ namespace Ombi.Core.Tests.Rule.Request
Assert.True(request.Approved); Assert.True(request.Approved);
} }
[Test]
public async Task Should_ReturnSuccess_WhenAdminAndRequest4KMovie()
{
UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.Admin)).ReturnsAsync(true);
var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie, Is4kRequest = true };
var result = await Rule.Execute(request);
Assert.True(result.Success);
Assert.True(request.Approved);
}
[Test] [Test]
public async Task Should_ReturnSuccess_WhenAdminAndRequestTV() public async Task Should_ReturnSuccess_WhenAdminAndRequestTV()
{ {
@ -87,17 +76,6 @@ namespace Ombi.Core.Tests.Rule.Request
Assert.True(request.Approved); Assert.True(request.Approved);
} }
[Test]
public async Task Should_ReturnSuccess_WhenAutoApprove4KMovieAndRequest4KMovie()
{
UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.AutoApprove4KMovie)).ReturnsAsync(true);
var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie, Is4kRequest = true };
var result = await Rule.Execute(request);
Assert.True(result.Success);
Assert.True(request.Approved);
}
[Test] [Test]
public async Task Should_ReturnFail_WhenAutoApproveMovie_And_RequestTV() public async Task Should_ReturnFail_WhenAutoApproveMovie_And_RequestTV()
{ {
@ -137,7 +115,7 @@ namespace Ombi.Core.Tests.Rule.Request
public async Task Should_ReturnFail_WhenAutoApproveTV_And_RequestMovie() public async Task Should_ReturnFail_WhenAutoApproveTV_And_RequestMovie()
{ {
UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.AutoApproveTv)).ReturnsAsync(true); UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.AutoApproveTv)).ReturnsAsync(true);
var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie }; var request = new BaseRequest() { RequestType = Store.Entities.RequestType.Movie };
var result = await Rule.Execute(request); var result = await Rule.Execute(request);
Assert.True(result.Success); Assert.True(result.Success);
@ -148,7 +126,7 @@ namespace Ombi.Core.Tests.Rule.Request
public async Task Should_ReturnFail_WhenNoClaimsAndRequestMovie() public async Task Should_ReturnFail_WhenNoClaimsAndRequestMovie()
{ {
UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), It.IsAny<string>())).ReturnsAsync(false); UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), It.IsAny<string>())).ReturnsAsync(false);
var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie }; var request = new BaseRequest() { RequestType = Store.Entities.RequestType.Movie };
var result = await Rule.Execute(request); var result = await Rule.Execute(request);
Assert.True(result.Success); Assert.True(result.Success);

View file

@ -51,20 +51,11 @@ namespace Ombi.Core.Tests.Rule.Request
} }
[Test] [Test]
public async Task Should_ReturnSuccess_WhenRequestingMovieWithAutoApproveRole() public async Task Should_ReturnSuccess_WhenRequestingMovie4KWithMovieRole()
{
UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.AutoApproveMovie)).ReturnsAsync(true);
var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie };
var result = await Rule.Execute(request);
Assert.True(result.Success);
}
[Test]
public async Task Should_ReturnSuccess_WhenRequestingMovie4KWithMovie4KRole()
{ {
UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.RequestMovie)).ReturnsAsync(true);
UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.Request4KMovie)).ReturnsAsync(true); UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.Request4KMovie)).ReturnsAsync(true);
var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie, Is4kRequest = true }; var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie, Has4KRequest = true };
var result = await Rule.Execute(request); var result = await Rule.Execute(request);
Assert.True(result.Success); Assert.True(result.Success);
@ -83,29 +74,15 @@ namespace Ombi.Core.Tests.Rule.Request
} }
[Test] [Test]
public async Task Should_ReturnSuccess_WhenRequestingMovie4KWithAutoApprove4K() public async Task Should_ReturnSuccess_WhenRequestingMovie4KWithAutoApprove()
{
UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.RequestMovie)).ReturnsAsync(false);
UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.AutoApproveMovie)).ReturnsAsync(false);
UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.Request4KMovie)).ReturnsAsync(false);
UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.AutoApprove4KMovie)).ReturnsAsync(true);
var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie, Is4kRequest = true };
var result = await Rule.Execute(request);
Assert.True(result.Success);
}
[Test]
public async Task Should_ReturnFailure_WhenRequestingMovie4KWithout4KRoles()
{ {
UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.RequestMovie)).ReturnsAsync(true); UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.RequestMovie)).ReturnsAsync(true);
UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.AutoApproveMovie)).ReturnsAsync(true); UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.AutoApproveMovie)).ReturnsAsync(true);
UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.Request4KMovie)).ReturnsAsync(false); UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.Request4KMovie)).ReturnsAsync(false);
UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.AutoApprove4KMovie)).ReturnsAsync(false); var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie, Has4KRequest = true };
var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie, Is4kRequest = true };
var result = await Rule.Execute(request); var result = await Rule.Execute(request);
Assert.False(result.Success); Assert.True(result.Success);
} }
[Test] [Test]

View file

@ -173,7 +173,6 @@ namespace Ombi.Core.Tests.Services
[Test] [Test]
[Ignore("Flaky")]
public async Task GetRecentlyRequested_HideUsernames() public async Task GetRecentlyRequested_HideUsernames()
{ {
_mocker.Setup<ISettingsService<CustomizationSettings>, Task<CustomizationSettings>>(x => x.GetSettingsAsync()) _mocker.Setup<ISettingsService<CustomizationSettings>, Task<CustomizationSettings>>(x => x.GetSettingsAsync())

View file

@ -69,8 +69,6 @@ namespace Ombi.Core.Authentication
private readonly ISettingsService<EmbySettings> _embySettings; private readonly ISettingsService<EmbySettings> _embySettings;
private readonly ISettingsService<JellyfinSettings> _jellyfinSettings; private readonly ISettingsService<JellyfinSettings> _jellyfinSettings;
private readonly ISettingsService<AuthenticationSettings> _authSettings; private readonly ISettingsService<AuthenticationSettings> _authSettings;
private string _clientIpAddress;
public string ClientIpAddress { get => _clientIpAddress; set => _clientIpAddress = value; }
public override async Task<bool> CheckPasswordAsync(OmbiUser user, string password) public override async Task<bool> CheckPasswordAsync(OmbiUser user, string password)
{ {
@ -90,7 +88,7 @@ namespace Ombi.Core.Authentication
} }
if (user.UserType == UserType.EmbyUser || user.UserType == UserType.EmbyConnectUser) if (user.UserType == UserType.EmbyUser || user.UserType == UserType.EmbyConnectUser)
{ {
return await CheckEmbyPasswordAsync(user, password, ClientIpAddress); return await CheckEmbyPasswordAsync(user, password);
} }
if (user.UserType == UserType.JellyfinUser) if (user.UserType == UserType.JellyfinUser)
{ {
@ -170,7 +168,7 @@ namespace Ombi.Core.Authentication
/// <param name="user"></param> /// <param name="user"></param>
/// <param name="password"></param> /// <param name="password"></param>
/// <returns></returns> /// <returns></returns>
private async Task<bool> CheckEmbyPasswordAsync(OmbiUser user, string password, string clientIpAddress="") private async Task<bool> CheckEmbyPasswordAsync(OmbiUser user, string password)
{ {
var embySettings = await _embySettings.GetSettingsAsync(); var embySettings = await _embySettings.GetSettingsAsync();
var client = _embyApi.CreateClient(embySettings); var client = _embyApi.CreateClient(embySettings);
@ -198,7 +196,7 @@ namespace Ombi.Core.Authentication
{ {
try try
{ {
var result = await client.LogIn(user.UserName, password, server.ApiKey, server.FullUri, clientIpAddress); var result = await client.LogIn(user.UserName, password, server.ApiKey, server.FullUri);
if (result != null) if (result != null)
{ {
return true; return true;

View file

@ -1,52 +0,0 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Ombi.Api.Plex;
namespace Ombi.Core.Authentication
{
public interface IPlexTokenKeepAliveService
{
Task<bool> KeepTokenAliveAsync(string token, CancellationToken cancellationToken);
}
public class PlexTokenKeepAliveService : IPlexTokenKeepAliveService
{
private readonly IPlexApi _plexApi;
private readonly ILogger<PlexTokenKeepAliveService> _logger;
public PlexTokenKeepAliveService(IPlexApi plexApi, ILogger<PlexTokenKeepAliveService> logger)
{
_plexApi = plexApi;
_logger = logger;
}
public async Task<bool> KeepTokenAliveAsync(string token, CancellationToken cancellationToken)
{
try
{
if (string.IsNullOrEmpty(token))
{
_logger.LogWarning("Token is null or empty");
return false;
}
// Use the Ping method to validate the token
var isValid = await _plexApi.Ping(token, cancellationToken);
if (!isValid)
{
_logger.LogWarning("Token validation failed - token may be expired or invalid");
}
return isValid;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while keeping token alive");
return false;
}
}
}
}

View file

@ -33,8 +33,7 @@ namespace Ombi.Core.Engine
INotificationHelper helper, IRuleEvaluator r, IMovieSender sender, ILogger<MovieRequestEngine> log, INotificationHelper helper, IRuleEvaluator r, IMovieSender sender, ILogger<MovieRequestEngine> log,
OmbiUserManager manager, IRepository<RequestLog> rl, ICacheService cache, OmbiUserManager manager, IRepository<RequestLog> rl, ICacheService cache,
ISettingsService<OmbiSettings> ombiSettings, IRepository<RequestSubscription> sub, IMediaCacheService mediaCacheService, ISettingsService<OmbiSettings> ombiSettings, IRepository<RequestSubscription> sub, IMediaCacheService mediaCacheService,
IFeatureService featureService, IFeatureService featureService)
IUserPlayedMovieRepository userPlayedMovieRepository)
: base(user, requestService, r, manager, cache, ombiSettings, sub) : base(user, requestService, r, manager, cache, ombiSettings, sub)
{ {
MovieApi = movieApi; MovieApi = movieApi;
@ -44,7 +43,6 @@ namespace Ombi.Core.Engine
_requestLog = rl; _requestLog = rl;
_mediaCacheService = mediaCacheService; _mediaCacheService = mediaCacheService;
_featureService = featureService; _featureService = featureService;
_userPlayedMovieRepository = userPlayedMovieRepository;
} }
private IMovieDbApi MovieApi { get; } private IMovieDbApi MovieApi { get; }
@ -54,7 +52,6 @@ namespace Ombi.Core.Engine
private readonly IRepository<RequestLog> _requestLog; private readonly IRepository<RequestLog> _requestLog;
private readonly IMediaCacheService _mediaCacheService; private readonly IMediaCacheService _mediaCacheService;
private readonly IFeatureService _featureService; private readonly IFeatureService _featureService;
protected readonly IUserPlayedMovieRepository _userPlayedMovieRepository;
/// <summary> /// <summary>
/// Requests the movie. /// Requests the movie.
@ -80,8 +77,7 @@ namespace Ombi.Core.Engine
var userDetails = await GetUser(); var userDetails = await GetUser();
var canRequestOnBehalf = model.RequestOnBehalf.HasValue(); var canRequestOnBehalf = model.RequestOnBehalf.HasValue();
var isAdmin = Username.Equals("API", StringComparison.CurrentCultureIgnoreCase) var isAdmin = await UserManager.IsInRoleAsync(userDetails, OmbiRoles.PowerUser)
|| await UserManager.IsInRoleAsync(userDetails, OmbiRoles.PowerUser)
|| await UserManager.IsInRoleAsync(userDetails, OmbiRoles.Admin); || await UserManager.IsInRoleAsync(userDetails, OmbiRoles.Admin);
if (canRequestOnBehalf && !isAdmin) if (canRequestOnBehalf && !isAdmin)
{ {
@ -256,7 +252,7 @@ namespace Ombi.Core.Engine
var requests = await (OrderMovies(allRequests, orderFilter.OrderType)).Skip(position).Take(count) var requests = await (OrderMovies(allRequests, orderFilter.OrderType)).Skip(position).Take(count)
.ToListAsync(); .ToListAsync();
await FillAdditionalFields(shouldHide, requests); await CheckForSubscription(shouldHide.UserId, requests);
return new RequestsViewModel<MovieRequests> return new RequestsViewModel<MovieRequests>
{ {
Collection = requests, Collection = requests,
@ -300,7 +296,7 @@ namespace Ombi.Core.Engine
var total = requests.Count(); var total = requests.Count();
requests = requests.Skip(position).Take(count).ToList(); requests = requests.Skip(position).Take(count).ToList();
await FillAdditionalFields(shouldHide, requests); await CheckForSubscription(shouldHide.UserId, requests);
return new RequestsViewModel<MovieRequests> return new RequestsViewModel<MovieRequests>
{ {
Collection = requests, Collection = requests,
@ -385,7 +381,7 @@ namespace Ombi.Core.Engine
// TODO fix this so we execute this on the server // TODO fix this so we execute this on the server
requests = requests.Skip(position).Take(count).ToList(); requests = requests.Skip(position).Take(count).ToList();
await FillAdditionalFields(shouldHide, requests); await CheckForSubscription(shouldHide.UserId, requests);
return new RequestsViewModel<MovieRequests> return new RequestsViewModel<MovieRequests>
{ {
Collection = requests, Collection = requests,
@ -428,7 +424,7 @@ namespace Ombi.Core.Engine
var total = requests.Count(); var total = requests.Count();
requests = requests.Skip(position).Take(count).ToList(); requests = requests.Skip(position).Take(count).ToList();
await FillAdditionalFields(shouldHide, requests); await CheckForSubscription(shouldHide.UserId, requests);
return new RequestsViewModel<MovieRequests> return new RequestsViewModel<MovieRequests>
{ {
Collection = requests, Collection = requests,
@ -510,25 +506,18 @@ namespace Ombi.Core.Engine
allRequests = await MovieRepository.GetWithUser().ToListAsync(); allRequests = await MovieRepository.GetWithUser().ToListAsync();
} }
await FillAdditionalFields(shouldHide, allRequests); await CheckForSubscription(shouldHide.UserId, allRequests);
return allRequests; return allRequests;
} }
public async Task<MovieRequests> GetRequest(int requestId) public async Task<MovieRequests> GetRequest(int requestId)
{ {
var shouldHide = await HideFromOtherUsers();
// TODO: this query should return the request only if the user is allowed to see it (see shouldHide implementations)
var request = await MovieRepository.GetWithUser().Where(x => x.Id == requestId).FirstOrDefaultAsync(); var request = await MovieRepository.GetWithUser().Where(x => x.Id == requestId).FirstOrDefaultAsync();
await FillAdditionalFields(shouldHide, new List<MovieRequests> { request }); await CheckForSubscription((await GetUser()).Id, new List<MovieRequests> { request });
return request; return request;
} }
private async Task FillAdditionalFields(HideResult shouldHide, List<MovieRequests> requests)
{
await CheckForSubscription(shouldHide.UserId, requests);
await CheckForPlayed(shouldHide, requests);
}
private async Task CheckForSubscription(string UserId, List<MovieRequests> movieRequests) private async Task CheckForSubscription(string UserId, List<MovieRequests> movieRequests)
{ {
@ -555,23 +544,6 @@ namespace Ombi.Core.Engine
} }
} }
private async Task CheckForPlayed(HideResult shouldHide, List<MovieRequests> movieRequests)
{
var theMovieDbIds = movieRequests.Select(x => x.TheMovieDbId);
var plays = await _userPlayedMovieRepository.GetAll().Where(x =>
theMovieDbIds.Contains(x.TheMovieDbId))
.ToListAsync();
foreach (var request in movieRequests)
{
request.WatchedByRequestedUser = plays.Exists(x => x.TheMovieDbId == request.TheMovieDbId && x.UserId == request.RequestedUserId);
if (!shouldHide.Hide)
{
request.PlayedByUsersCount = plays.Count(x => x.TheMovieDbId == request.TheMovieDbId);
}
}
}
/// <summary> /// <summary>
/// Searches the movie request. /// Searches the movie request.
/// </summary> /// </summary>
@ -591,20 +563,20 @@ namespace Ombi.Core.Engine
} }
var results = allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToList(); var results = allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToList();
await FillAdditionalFields(shouldHide, results); await CheckForSubscription(shouldHide.UserId, results);
return results; return results;
} }
public async Task<RequestEngineResult> ApproveMovieById(int requestId, bool is4K) public async Task<RequestEngineResult> ApproveMovieById(int requestId, bool is4K)
{ {
var request = await MovieRepository.GetWithUser().FirstOrDefaultAsync(x => x.Id == requestId); var request = await MovieRepository.Find(requestId);
return await ApproveMovie(request, is4K); return await ApproveMovie(request, is4K);
} }
public async Task<RequestEngineResult> DenyMovieById(int modelId, string denyReason, bool is4K) public async Task<RequestEngineResult> DenyMovieById(int modelId, string denyReason, bool is4K)
{ {
var request = await MovieRepository.GetWithUser().FirstOrDefaultAsync(x => x.Id == modelId); var request = await MovieRepository.Find(modelId);
if (request == null) if (request == null)
{ {
return new RequestEngineResult return new RequestEngineResult
@ -790,7 +762,7 @@ namespace Ombi.Core.Engine
public async Task<RequestEngineResult> ReProcessRequest(int requestId, bool is4K, CancellationToken cancellationToken) public async Task<RequestEngineResult> ReProcessRequest(int requestId, bool is4K, CancellationToken cancellationToken)
{ {
var request = await MovieRepository.GetWithUser().FirstOrDefaultAsync(x => x.Id == requestId); var request = await MovieRepository.Find(requestId);
if (request == null) if (request == null)
{ {
return new RequestEngineResult return new RequestEngineResult
@ -805,7 +777,7 @@ namespace Ombi.Core.Engine
public async Task<RequestEngineResult> MarkUnavailable(int modelId, bool is4K) public async Task<RequestEngineResult> MarkUnavailable(int modelId, bool is4K)
{ {
var request = await MovieRepository.GetWithUser().FirstOrDefaultAsync(x => x.Id == modelId); var request = await MovieRepository.Find(modelId);
if (request == null) if (request == null)
{ {
return new RequestEngineResult return new RequestEngineResult
@ -834,7 +806,7 @@ namespace Ombi.Core.Engine
public async Task<RequestEngineResult> MarkAvailable(int modelId, bool is4K) public async Task<RequestEngineResult> MarkAvailable(int modelId, bool is4K)
{ {
var request = await MovieRepository.GetWithUser().FirstOrDefaultAsync(x => x.Id == modelId); var request = await MovieRepository.Find(modelId);
if (request == null) if (request == null)
{ {
return new RequestEngineResult return new RequestEngineResult

View file

@ -35,8 +35,7 @@ namespace Ombi.Core.Engine
public TvRequestEngine(ITvMazeApi tvApi, IMovieDbApi movApi, IRequestServiceMain requestService, ICurrentUser user, public TvRequestEngine(ITvMazeApi tvApi, IMovieDbApi movApi, IRequestServiceMain requestService, ICurrentUser user,
INotificationHelper helper, IRuleEvaluator rule, OmbiUserManager manager, ILogger<TvRequestEngine> logger, INotificationHelper helper, IRuleEvaluator rule, OmbiUserManager manager, ILogger<TvRequestEngine> logger,
ITvSender sender, IRepository<RequestLog> rl, ISettingsService<OmbiSettings> settings, ICacheService cache, ITvSender sender, IRepository<RequestLog> rl, ISettingsService<OmbiSettings> settings, ICacheService cache,
IRepository<RequestSubscription> sub, IMediaCacheService mediaCacheService, IRepository<RequestSubscription> sub, IMediaCacheService mediaCacheService) : base(user, requestService, rule, manager, cache, settings, sub)
IUserPlayedEpisodeRepository userPlayedEpisodeRepository) : base(user, requestService, rule, manager, cache, settings, sub)
{ {
TvApi = tvApi; TvApi = tvApi;
MovieDbApi = movApi; MovieDbApi = movApi;
@ -45,7 +44,6 @@ namespace Ombi.Core.Engine
TvSender = sender; TvSender = sender;
_requestLog = rl; _requestLog = rl;
_mediaCacheService = mediaCacheService; _mediaCacheService = mediaCacheService;
_userPlayedEpisodeRepository = userPlayedEpisodeRepository;
} }
private INotificationHelper NotificationHelper { get; } private INotificationHelper NotificationHelper { get; }
@ -56,7 +54,6 @@ namespace Ombi.Core.Engine
private readonly ILogger<TvRequestEngine> _logger; private readonly ILogger<TvRequestEngine> _logger;
private readonly IRepository<RequestLog> _requestLog; private readonly IRepository<RequestLog> _requestLog;
private readonly IMediaCacheService _mediaCacheService; private readonly IMediaCacheService _mediaCacheService;
private readonly IUserPlayedEpisodeRepository _userPlayedEpisodeRepository;
public async Task<RequestEngineResult> RequestTvShow(TvRequestViewModel tv) public async Task<RequestEngineResult> RequestTvShow(TvRequestViewModel tv)
{ {
@ -164,7 +161,7 @@ namespace Ombi.Core.Engine
var user = await GetUser(); var user = await GetUser();
var canRequestOnBehalf = tv.RequestOnBehalf.HasValue(); var canRequestOnBehalf = tv.RequestOnBehalf.HasValue();
var isAdmin = Username.Equals("API", StringComparison.CurrentCultureIgnoreCase) || await UserManager.IsInRoleAsync(user, OmbiRoles.PowerUser) || await UserManager.IsInRoleAsync(user, OmbiRoles.Admin); var isAdmin = await UserManager.IsInRoleAsync(user, OmbiRoles.PowerUser) || await UserManager.IsInRoleAsync(user, OmbiRoles.Admin);
if (tv.RequestOnBehalf.HasValue() && !isAdmin) if (tv.RequestOnBehalf.HasValue() && !isAdmin)
{ {
return new RequestEngineResult return new RequestEngineResult
@ -295,7 +292,7 @@ namespace Ombi.Core.Engine
.Skip(position).Take(count).ToListAsync(); .Skip(position).Take(count).ToListAsync();
} }
await FillAdditionalFields(shouldHide, allRequests); await CheckForSubscription(shouldHide, allRequests);
return new RequestsViewModel<TvRequests> return new RequestsViewModel<TvRequests>
{ {
@ -331,7 +328,7 @@ namespace Ombi.Core.Engine
return new RequestsViewModel<TvRequests>(); return new RequestsViewModel<TvRequests>();
} }
await FillAdditionalFields(shouldHide, allRequests); await CheckForSubscription(shouldHide, allRequests);
return new RequestsViewModel<TvRequests> return new RequestsViewModel<TvRequests>
{ {
@ -354,7 +351,7 @@ namespace Ombi.Core.Engine
allRequests = await TvRepository.Get().ToListAsync(); allRequests = await TvRepository.Get().ToListAsync();
} }
await FillAdditionalFields(shouldHide, allRequests); await CheckForSubscription(shouldHide, allRequests);
return allRequests; return allRequests;
} }
@ -399,7 +396,7 @@ namespace Ombi.Core.Engine
? allRequests.OrderBy(x => prop.GetValue(x)).ToList() ? allRequests.OrderBy(x => prop.GetValue(x)).ToList()
: allRequests.OrderByDescending(x => prop.GetValue(x)).ToList(); : allRequests.OrderByDescending(x => prop.GetValue(x)).ToList();
await FillAdditionalFields(shouldHide, allRequests); await CheckForSubscription(shouldHide, allRequests);
// Make sure we do not show duplicate child requests // Make sure we do not show duplicate child requests
allRequests = allRequests.DistinctBy(x => x.ParentRequest.Title).ToList(); allRequests = allRequests.DistinctBy(x => x.ParentRequest.Title).ToList();
@ -472,7 +469,7 @@ namespace Ombi.Core.Engine
? allRequests.OrderBy(x => prop.GetValue(x)).ToList() ? allRequests.OrderBy(x => prop.GetValue(x)).ToList()
: allRequests.OrderByDescending(x => prop.GetValue(x)).ToList(); : allRequests.OrderByDescending(x => prop.GetValue(x)).ToList();
await FillAdditionalFields(shouldHide, allRequests); await CheckForSubscription(shouldHide, allRequests);
// Make sure we do not show duplicate child requests // Make sure we do not show duplicate child requests
allRequests = allRequests.DistinctBy(x => x.ParentRequest.Title).ToList(); allRequests = allRequests.DistinctBy(x => x.ParentRequest.Title).ToList();
@ -526,7 +523,7 @@ namespace Ombi.Core.Engine
allRequests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase) allRequests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase)
? allRequests.OrderBy(x => prop.GetValue(x)).ToList() ? allRequests.OrderBy(x => prop.GetValue(x)).ToList()
: allRequests.OrderByDescending(x => prop.GetValue(x)).ToList(); : allRequests.OrderByDescending(x => prop.GetValue(x)).ToList();
await FillAdditionalFields(shouldHide, allRequests); await CheckForSubscription(shouldHide, allRequests);
// Make sure we do not show duplicate child requests // Make sure we do not show duplicate child requests
allRequests = allRequests.DistinctBy(x => x.ParentRequest.Title).ToList(); allRequests = allRequests.DistinctBy(x => x.ParentRequest.Title).ToList();
@ -554,7 +551,7 @@ namespace Ombi.Core.Engine
allRequests = await TvRepository.GetLite().ToListAsync(); allRequests = await TvRepository.GetLite().ToListAsync();
} }
await FillAdditionalFields(shouldHide, allRequests); await CheckForSubscription(shouldHide, allRequests);
return allRequests; return allRequests;
} }
@ -573,7 +570,7 @@ namespace Ombi.Core.Engine
request = await TvRepository.Get().Where(x => x.Id == requestId).FirstOrDefaultAsync(); request = await TvRepository.Get().Where(x => x.Id == requestId).FirstOrDefaultAsync();
} }
await FillAdditionalFields(shouldHide, new List<TvRequests>{request}); await CheckForSubscription(shouldHide, new List<TvRequests>{request});
return request; return request;
} }
@ -627,7 +624,7 @@ namespace Ombi.Core.Engine
allRequests = await TvRepository.GetChild().Include(x => x.SeasonRequests).Where(x => x.ParentRequestId == tvId).ToListAsync(); allRequests = await TvRepository.GetChild().Include(x => x.SeasonRequests).Where(x => x.ParentRequestId == tvId).ToListAsync();
} }
await FillAdditionalFields(shouldHide, allRequests); await CheckForSubscription(shouldHide, allRequests);
return allRequests; return allRequests;
} }
@ -646,7 +643,7 @@ namespace Ombi.Core.Engine
} }
var results = await allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToListAsync(); var results = await allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToListAsync();
await FillAdditionalFields(shouldHide, results); await CheckForSubscription(shouldHide, results);
return results; return results;
} }
@ -696,8 +693,6 @@ namespace Ombi.Core.Engine
ErrorMessage = "Child Request does not exist" ErrorMessage = "Child Request does not exist"
}; };
} }
request.MarkedAsApproved = DateTime.Now;
request.Approved = true; request.Approved = true;
request.Denied = false; request.Denied = false;
@ -869,20 +864,14 @@ namespace Ombi.Core.Engine
} }
} }
private async Task FillAdditionalFields(HideResult shouldHide, List<TvRequests> x) private async Task CheckForSubscription(HideResult shouldHide, List<TvRequests> x)
{ {
foreach (var tvRequest in x) foreach (var tvRequest in x)
{ {
await FillAdditionalFields(shouldHide, tvRequest.ChildRequests); await CheckForSubscription(shouldHide, tvRequest.ChildRequests);
} }
} }
private async Task FillAdditionalFields(HideResult shouldHide, List<ChildRequests> childRequests)
{
await CheckForSubscription(shouldHide, childRequests);
CheckForPlayed(shouldHide, childRequests);
}
private async Task CheckForSubscription(HideResult shouldHide, List<ChildRequests> childRequests) private async Task CheckForSubscription(HideResult shouldHide, List<ChildRequests> childRequests)
{ {
var sub = _subscriptionRepository.GetAll(); var sub = _subscriptionRepository.GetAll();
@ -907,59 +896,6 @@ namespace Ombi.Core.Engine
} }
} }
private class EpisodeKey
{
public int SeasonNumber;
public int EpisodeNumber;
}
private void CheckForPlayed(HideResult shouldHide, List<ChildRequests> childRequests)
{
var theMovieDbIds = childRequests.Select(x => x.Id);
foreach (var request in childRequests)
{
var requestedEpisodes = GetEpisodesKeys(request);
var playedEpisodes = _userPlayedEpisodeRepository
.GetAll()
.Where(x => x.TheMovieDbId == request.Id && x.UserId == request.RequestedUserId)
.AsEnumerable()
.Join(requestedEpisodes,
played => new { played.SeasonNumber, played.EpisodeNumber },
requested => new { requested.SeasonNumber, requested.EpisodeNumber },
(played, requested) => new { played });
var playedCount = playedEpisodes.Count();
var toWatchCount = requestedEpisodes.Count();
if (playedCount == 0 || toWatchCount == 0)
{
request.RequestedUserPlayedProgress = 0;
}
else
{
request.RequestedUserPlayedProgress = 100 * playedCount / toWatchCount;
}
}
}
private List<EpisodeKey> GetEpisodesKeys(ChildRequests request)
{
List<EpisodeKey> result = new List<EpisodeKey>();
foreach(var season in request.SeasonRequests)
{
foreach(var episode in season.Episodes)
{
result.Add(new EpisodeKey
{
SeasonNumber = season.SeasonNumber,
EpisodeNumber = episode.EpisodeNumber
});
}
}
return result;
}
private async Task<RequestEngineResult> AddExistingRequest(ChildRequests newRequest, TvRequests existingRequest, string requestOnBehalf, int rootFolder, int qualityProfile) private async Task<RequestEngineResult> AddExistingRequest(ChildRequests newRequest, TvRequests existingRequest, string requestOnBehalf, int rootFolder, int qualityProfile)
{ {
// Add the child // Add the child

View file

@ -1,6 +1,5 @@
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.VisualBasic;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;

View file

@ -200,14 +200,19 @@ namespace Ombi.Core.Engine.V2
public async Task<IEnumerable<SearchMovieViewModel>> NowPlayingMovies(int currentPosition, int amountToLoad) public async Task<IEnumerable<SearchMovieViewModel>> NowPlayingMovies(int currentPosition, int amountToLoad)
{ {
var langCode = await DefaultLanguageCode(null); var langCode = await DefaultLanguageCode(null);
var isOldTrendingSourceEnabled = await _feature.FeatureEnabled(FeatureNames.OldTrendingSource);
var pages = PaginationHelper.GetNextPages(currentPosition, amountToLoad, _theMovieDbMaxPageItems); var pages = PaginationHelper.GetNextPages(currentPosition, amountToLoad, _theMovieDbMaxPageItems);
var results = new List<MovieDbSearchResult>(); var results = new List<MovieDbSearchResult>();
foreach (var pagesToLoad in pages) 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, var apiResult = await Cache.GetOrAddAsync(nameof(NowPlayingMovies) + pagesToLoad.Page + langCode,
() => MovieApi.TrendingMovies(langCode, pagesToLoad.Page), DateTimeOffset.Now.AddHours(12)); search, DateTimeOffset.Now.AddHours(12));
results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take)); results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take));
} }
return await TransformMovieResultsToResponse(results); return await TransformMovieResultsToResponse(results);

View file

@ -138,13 +138,17 @@ namespace Ombi.Core.Engine.V2
public async Task<IEnumerable<SearchTvShowViewModel>> Trending(int currentlyLoaded, int amountToLoad) public async Task<IEnumerable<SearchTvShowViewModel>> Trending(int currentlyLoaded, int amountToLoad)
{ {
var langCode = await DefaultLanguageCode(null); var langCode = await DefaultLanguageCode(null);
var isOldTrendingSourceEnabled = await _feature.FeatureEnabled(FeatureNames.OldTrendingSource);
var pages = PaginationHelper.GetNextPages(currentlyLoaded, amountToLoad, ResultLimit); var pages = PaginationHelper.GetNextPages(currentlyLoaded, amountToLoad, ResultLimit);
var results = new List<MovieDbSearchResult>(); var results = new List<MovieDbSearchResult>();
foreach (var pagesToLoad in pages) 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, var apiResult = await Cache.GetOrAddAsync(nameof(Trending) + langCode + pagesToLoad.Page,
() => _movieApi.TrendingTv(langCode, pagesToLoad.Page), DateTimeOffset.Now.AddHours(12)); search, DateTimeOffset.Now.AddHours(12));
results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take)); results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take));
} }

View file

@ -1,67 +0,0 @@
using System;
using System.Text;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal;
using Ombi.Core.Models;
using Polly;
using Pomelo.EntityFrameworkCore.MySql.Storage.Internal;
namespace Ombi.Core.Helpers;
public static class DatabaseConfigurationSetup
{
public static void ConfigurePostgres(DbContextOptionsBuilder options, PerDatabaseConfiguration config)
{
options.UseNpgsql(config.ConnectionString, b =>
{
b.EnableRetryOnFailure();
}).ReplaceService<ISqlGenerationHelper, NpgsqlCaseInsensitiveSqlGenerationHelper>();
}
public static void ConfigureMySql(DbContextOptionsBuilder options, PerDatabaseConfiguration config)
{
if (string.IsNullOrEmpty(config.ConnectionString))
{
throw new ArgumentNullException("ConnectionString for the MySql/Mariadb database is empty");
}
options.UseMySql(config.ConnectionString, GetServerVersion(config.ConnectionString), b =>
{
//b.CharSetBehavior(Pomelo.EntityFrameworkCore.MySql.Infrastructure.CharSetBehavior.NeverAppend); // ##ISSUE, link to migrations?
b.EnableRetryOnFailure();
});
}
private static ServerVersion GetServerVersion(string connectionString)
{
// Workaround Windows bug, that can lead to the following exception:
//
// MySqlConnector.MySqlException (0x80004005): SSL Authentication Error
// ---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
// ---> System.ComponentModel.Win32Exception (0x8009030F): The message or signature supplied for verification has been altered
//
// See https://github.com/dotnet/runtime/issues/17005#issuecomment-305848835
//
// Also workaround for the fact, that ServerVersion.AutoDetect() does not use any retrying strategy.
ServerVersion serverVersion = null;
#pragma warning disable EF1001
var retryPolicy = Policy.Handle<Exception>(exception => MySqlTransientExceptionDetector.ShouldRetryOn(exception))
#pragma warning restore EF1001
.WaitAndRetry(3, (count, context) => TimeSpan.FromMilliseconds(count * 250));
serverVersion = retryPolicy.Execute(() => serverVersion = ServerVersion.AutoDetect(connectionString));
return serverVersion;
}
public class NpgsqlCaseInsensitiveSqlGenerationHelper : NpgsqlSqlGenerationHelper
{
const string EFMigrationsHisory = "__EFMigrationsHistory";
public NpgsqlCaseInsensitiveSqlGenerationHelper(RelationalSqlGenerationHelperDependencies dependencies)
: base(dependencies) { }
public override string DelimitIdentifier(string identifier) =>
base.DelimitIdentifier(identifier == EFMigrationsHisory ? identifier : identifier.ToLower());
public override void DelimitIdentifier(StringBuilder builder, string identifier)
=> base.DelimitIdentifier(builder, identifier == EFMigrationsHisory ? identifier : identifier.ToLower());
}
}

View file

@ -1,10 +0,0 @@
namespace Ombi.Core.Helpers;
public class FileSystem : IFileSystem
{
public bool FileExists(string path)
{
return System.IO.File.Exists(path);
}
// Implement other file system operations as needed
}

View file

@ -1,7 +0,0 @@
namespace Ombi.Core.Helpers;
public interface IFileSystem
{
bool FileExists(string path);
// Add other file system operations as needed
}

View file

@ -1,40 +0,0 @@
using System.IO;
namespace Ombi.Core.Models;
public class DatabaseConfiguration
{
public const string SqliteDatabase = "Sqlite";
public DatabaseConfiguration()
{
}
public DatabaseConfiguration(string defaultSqlitePath)
{
OmbiDatabase = new PerDatabaseConfiguration(SqliteDatabase, $"Data Source={Path.Combine(defaultSqlitePath, "Ombi.db")}");
SettingsDatabase = new PerDatabaseConfiguration(SqliteDatabase, $"Data Source={Path.Combine(defaultSqlitePath, "OmbiSettings.db")}");
ExternalDatabase = new PerDatabaseConfiguration(SqliteDatabase, $"Data Source={Path.Combine(defaultSqlitePath, "OmbiExternal.db")}");
}
public PerDatabaseConfiguration OmbiDatabase { get; set; }
public PerDatabaseConfiguration SettingsDatabase { get; set; }
public PerDatabaseConfiguration ExternalDatabase { get; set; }
}
public class PerDatabaseConfiguration
{
public PerDatabaseConfiguration(string type, string connectionString)
{
Type = type;
ConnectionString = connectionString;
}
// Used in Deserialization
public PerDatabaseConfiguration()
{
}
public string Type { get; set; }
public string ConnectionString { get; set; }
}

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>
@ -13,8 +13,8 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AutoMapper" Version="12.0.0" /> <PackageReference Include="AutoMapper" Version="12.0.0" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.0" /> <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.5" /> <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="6.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.5" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.9" />
<PackageReference Include="MusicBrainzAPI" Version="2.5.0" /> <PackageReference Include="MusicBrainzAPI" Version="2.5.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="System.Diagnostics.Process" Version="4.3.0" /> <PackageReference Include="System.Diagnostics.Process" Version="4.3.0" />

View file

@ -36,7 +36,7 @@ namespace Ombi.Core.Rule.Rules.Request
{ {
if (obj is MovieRequests movie) if (obj is MovieRequests movie)
{ {
await ApproveMovie(movie); await Check4K(movie);
} }
else else
{ {
@ -45,14 +45,10 @@ namespace Ombi.Core.Rule.Rules.Request
return Success(); return Success();
} }
if (obj.RequestType == RequestType.Movie) if (obj.RequestType == RequestType.Movie && await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveMovie))
{ {
var movie = (MovieRequests)obj; var movie = (MovieRequests)obj;
var autoApproveRole = movie.Is4kRequest ? OmbiRoles.AutoApprove4KMovie : OmbiRoles.AutoApproveMovie; await Check4K(movie);
if (await _manager.IsInRoleAsync(user, autoApproveRole))
{
await ApproveMovie(movie);
}
} }
if (obj.RequestType == RequestType.TvShow && await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveTv)) if (obj.RequestType == RequestType.TvShow && await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveTv))
obj.Approved = true; obj.Approved = true;
@ -61,7 +57,7 @@ namespace Ombi.Core.Rule.Rules.Request
return Success(); // We don't really care, we just don't set the obj to approve return Success(); // We don't really care, we just don't set the obj to approve
} }
private async Task ApproveMovie(MovieRequests movie) private async Task Check4K(MovieRequests movie)
{ {
var featureEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests); var featureEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests);
if (movie.Is4kRequest && featureEnabled) if (movie.Is4kRequest && featureEnabled)

View file

@ -36,14 +36,22 @@ namespace Ombi.Core.Rule.Rules.Request
if (obj.RequestType == RequestType.Movie) if (obj.RequestType == RequestType.Movie)
{ {
var movie = (MovieRequests)obj; var movie = (MovieRequests)obj;
var hasAutoApprove = await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveMovie);
var requestRole = movie.Is4kRequest ? OmbiRoles.Request4KMovie : OmbiRoles.RequestMovie; if (await _manager.IsInRoleAsync(user, OmbiRoles.RequestMovie) || hasAutoApprove)
var autoApproveRole = movie.Is4kRequest ? OmbiRoles.AutoApprove4KMovie : OmbiRoles.AutoApproveMovie; {
if (movie.Is4kRequest && !hasAutoApprove)
if (await _manager.IsInRoleAsync(user, requestRole) || await _manager.IsInRoleAsync(user, autoApproveRole)) {
var has4kPermission = await _manager.IsInRoleAsync(user, OmbiRoles.Request4KMovie);
if (has4kPermission)
{ {
return Success(); return Success();
} }
}
else
{
return Success();
}
}
return Fail(ErrorCode.NoPermissionsRequestMovie, "You do not have permissions to Request a Movie"); return Fail(ErrorCode.NoPermissionsRequestMovie, "You do not have permissions to Request a Movie");
} }

View file

@ -69,7 +69,7 @@ namespace Ombi.Core.Senders
} }
if (radarrSettings.Enabled) if (radarrSettings.Enabled)
{ {
return await SendToRadarr(model, radarrSettings, is4K); return await SendToRadarr(model, radarrSettings);
} }
var dogSettings = await _dogNzbSettings.GetSettingsAsync(); var dogSettings = await _dogNzbSettings.GetSettingsAsync();
@ -133,7 +133,7 @@ namespace Ombi.Core.Senders
return await _dogNzbApi.AddMovie(settings.ApiKey, id); return await _dogNzbApi.AddMovie(settings.ApiKey, id);
} }
private async Task<SenderResult> SendToRadarr(MovieRequests model, RadarrSettings settings, bool is4k) private async Task<SenderResult> SendToRadarr(MovieRequests model, RadarrSettings settings)
{ {
var qualityToUse = int.Parse(settings.DefaultQualityProfile); var qualityToUse = int.Parse(settings.DefaultQualityProfile);
@ -141,23 +141,6 @@ namespace Ombi.Core.Senders
var profiles = await _userProfiles.GetAll().FirstOrDefaultAsync(x => x.UserId == model.RequestedUserId); var profiles = await _userProfiles.GetAll().FirstOrDefaultAsync(x => x.UserId == model.RequestedUserId);
if (profiles != null) if (profiles != null)
{
if (is4k)
{
if (profiles.Radarr4KRootPath > 0)
{
var tempPath = await RadarrRootPath(profiles.Radarr4KRootPath, settings);
if (tempPath.HasValue())
{
rootFolderPath = tempPath;
}
}
if (profiles.Radarr4KQualityProfile > 0)
{
qualityToUse = profiles.Radarr4KQualityProfile;
}
}
else
{ {
if (profiles.RadarrRootPath > 0) if (profiles.RadarrRootPath > 0)
{ {
@ -172,7 +155,6 @@ namespace Ombi.Core.Senders
qualityToUse = profiles.RadarrQualityProfile; qualityToUse = profiles.RadarrQualityProfile;
} }
} }
}
var tags = new List<int>(); var tags = new List<int>();
if (settings.Tag.HasValue) if (settings.Tag.HasValue)
@ -182,11 +164,8 @@ namespace Ombi.Core.Senders
if (settings.SendUserTags) if (settings.SendUserTags)
{ {
var userTag = await GetOrCreateTag(model, settings); var userTag = await GetOrCreateTag(model, settings);
if (userTag != null)
{
tags.Add(userTag.id); tags.Add(userTag.id);
} }
}
// Overrides on the request take priority // Overrides on the request take priority
if (model.QualityOverride > 0) if (model.QualityOverride > 0)
@ -201,9 +180,7 @@ namespace Ombi.Core.Senders
List<MovieResponse> movies; List<MovieResponse> movies;
// Check if the movie already exists? Since it could be unmonitored // Check if the movie already exists? Since it could be unmonitored
// Get the appropriate Radarr instance settings for existence check movies = await _radarrV3Api.GetMovies(settings.ApiKey, settings.FullUri);
var existenceCheckSettings = is4k ? await _radarr4KSettings.GetSettingsAsync() : settings;
movies = await _radarrV3Api.GetMovies(existenceCheckSettings.ApiKey, existenceCheckSettings.FullUri);
var existingMovie = movies.FirstOrDefault(x => x.tmdbId == model.TheMovieDbId); var existingMovie = movies.FirstOrDefault(x => x.tmdbId == model.TheMovieDbId);
if (existingMovie == null) if (existingMovie == null)
@ -251,12 +228,6 @@ namespace Ombi.Core.Senders
private async Task<Tag> GetOrCreateTag(MovieRequests model, RadarrSettings s) private async Task<Tag> GetOrCreateTag(MovieRequests model, RadarrSettings s)
{ {
if (model.RequestedUser == null)
{
_log.LogWarning("Cannot create tag - RequestedUser is null for movie request {MovieTitle}", model.Title);
return null;
}
var tagName = model.RequestedUser.UserName; var tagName = model.RequestedUser.UserName;
// Does tag exist? // Does tag exist?

View file

@ -1,9 +1,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.VisualBasic;
using Ombi.Api.DogNzb;
using Ombi.Api.DogNzb.Models;
using Ombi.Api.SickRage; using Ombi.Api.SickRage;
using Ombi.Api.SickRage.Models; using Ombi.Api.SickRage.Models;
using Ombi.Api.Sonarr; using Ombi.Api.Sonarr;
@ -19,13 +23,15 @@ namespace Ombi.Core.Senders
{ {
public class TvSender : ITvSender public class TvSender : ITvSender
{ {
public TvSender(ISonarrV3Api sonarrV3Api, ILogger<TvSender> log, ISettingsService<SonarrSettings> sonarrSettings, public TvSender(ISonarrApi sonarrApi, ISonarrV3Api sonarrV3Api, ILogger<TvSender> log, ISettingsService<SonarrSettings> sonarrSettings,
ISettingsService<SickRageSettings> srSettings, ISettingsService<DogNzbSettings> dog, IDogNzbApi dogApi, ISettingsService<SickRageSettings> srSettings,
ISickRageApi srApi, IRepository<UserQualityProfiles> userProfiles, IRepository<RequestQueue> requestQueue, INotificationHelper notify) ISickRageApi srApi, IRepository<UserQualityProfiles> userProfiles, IRepository<RequestQueue> requestQueue, INotificationHelper notify)
{ {
SonarrApi = sonarrV3Api; SonarrApi = sonarrV3Api;
Logger = log; Logger = log;
SonarrSettings = sonarrSettings; SonarrSettings = sonarrSettings;
DogNzbSettings = dog;
DogNzbApi = dogApi;
SickRageSettings = srSettings; SickRageSettings = srSettings;
SickRageApi = srApi; SickRageApi = srApi;
UserQualityProfiles = userProfiles; UserQualityProfiles = userProfiles;
@ -34,9 +40,11 @@ namespace Ombi.Core.Senders
} }
private ISonarrV3Api SonarrApi { get; } private ISonarrV3Api SonarrApi { get; }
private IDogNzbApi DogNzbApi { get; }
private ISickRageApi SickRageApi { get; } private ISickRageApi SickRageApi { get; }
private ILogger<TvSender> Logger { get; } private ILogger<TvSender> Logger { get; }
private ISettingsService<SonarrSettings> SonarrSettings { get; } private ISettingsService<SonarrSettings> SonarrSettings { get; }
private ISettingsService<DogNzbSettings> DogNzbSettings { get; }
private ISettingsService<SickRageSettings> SickRageSettings { get; } private ISettingsService<SickRageSettings> SickRageSettings { get; }
private IRepository<UserQualityProfiles> UserQualityProfiles { get; } private IRepository<UserQualityProfiles> UserQualityProfiles { get; }
private readonly IRepository<RequestQueue> _requestQueueRepository; private readonly IRepository<RequestQueue> _requestQueueRepository;
@ -59,7 +67,23 @@ namespace Ombi.Core.Senders
}; };
} }
} }
var dog = await DogNzbSettings.GetSettingsAsync();
if (dog.Enabled)
{
var result = await SendToDogNzb(model, dog);
if (!result.Failure)
{
return new SenderResult
{
Sent = true,
Success = true
};
}
return new SenderResult
{
Message = result.ErrorMessage
};
}
var sr = await SickRageSettings.GetSettingsAsync(); var sr = await SickRageSettings.GetSettingsAsync();
if (sr.Enabled) if (sr.Enabled)
{ {
@ -113,6 +137,12 @@ namespace Ombi.Core.Senders
}; };
} }
private async Task<DogNzbAddResult> SendToDogNzb(ChildRequests model, DogNzbSettings settings)
{
var id = model.ParentRequest.ExternalProviderId;
return await DogNzbApi.AddTvShow(settings.ApiKey, id.ToString());
}
/// <summary> /// <summary>
/// Send the request to Sonarr to process /// Send the request to Sonarr to process
/// </summary> /// </summary>
@ -133,14 +163,7 @@ namespace Ombi.Core.Senders
string seriesType; string seriesType;
int? tagToUse = null; int? tagToUse = null;
Logger.LogInformation("Starting SendToSonarr for series {Title} (TvDbId: {TvDbId})", model.ParentRequest.Title, model.ParentRequest.TvDbId);
Logger.LogInformation("Series type: {SeriesType}", model.SeriesType);
var profiles = await UserQualityProfiles.GetAll().FirstOrDefaultAsync(x => x.UserId == model.RequestedUserId); var profiles = await UserQualityProfiles.GetAll().FirstOrDefaultAsync(x => x.UserId == model.RequestedUserId);
if (profiles != null)
{
Logger.LogInformation("Found user quality profile for user {UserId}", model.RequestedUserId);
}
if (model.SeriesType == SeriesType.Anime) if (model.SeriesType == SeriesType.Anime)
{ {
@ -148,10 +171,8 @@ namespace Ombi.Core.Senders
// For some reason, if we haven't got one use the first root folder in Sonarr // For some reason, if we haven't got one use the first root folder in Sonarr
if (!int.TryParse(s.RootPathAnime, out int animePath)) if (!int.TryParse(s.RootPathAnime, out int animePath))
{ {
Logger.LogWarning("Failed to parse RootPathAnime: {RootPathAnime}, falling back to main root path", s.RootPathAnime);
animePath = int.Parse(s.RootPath); // Set it to the main root folder if we have no anime folder. animePath = int.Parse(s.RootPath); // Set it to the main root folder if we have no anime folder.
} }
Logger.LogInformation("Using anime path ID: {AnimePath}", animePath);
rootFolderPath = await GetSonarrRootPath(animePath, s); rootFolderPath = await GetSonarrRootPath(animePath, s);
languageProfileId = s.LanguageProfileAnime > 0 ? s.LanguageProfileAnime : s.LanguageProfile; languageProfileId = s.LanguageProfileAnime > 0 ? s.LanguageProfileAnime : s.LanguageProfile;
@ -163,7 +184,6 @@ namespace Ombi.Core.Senders
{ {
if (profiles.SonarrRootPathAnime > 0) if (profiles.SonarrRootPathAnime > 0)
{ {
Logger.LogInformation("Using user's anime root path override: {RootPath}", profiles.SonarrRootPathAnime);
rootFolderPath = await GetSonarrRootPath(profiles.SonarrRootPathAnime, s); rootFolderPath = await GetSonarrRootPath(profiles.SonarrRootPathAnime, s);
} }
if (profiles.SonarrQualityProfileAnime > 0) if (profiles.SonarrQualityProfileAnime > 0)
@ -179,13 +199,11 @@ namespace Ombi.Core.Senders
int.TryParse(s.QualityProfile, out qualityToUse); int.TryParse(s.QualityProfile, out qualityToUse);
// Get the root path from the rootfolder selected. // Get the root path from the rootfolder selected.
// For some reason, if we haven't got one use the first root folder in Sonarr // For some reason, if we haven't got one use the first root folder in Sonarr
Logger.LogInformation("Using standard path ID: {RootPath}", s.RootPath);
rootFolderPath = await GetSonarrRootPath(int.Parse(s.RootPath), s); rootFolderPath = await GetSonarrRootPath(int.Parse(s.RootPath), s);
if (profiles != null) if (profiles != null)
{ {
if (profiles.SonarrRootPath > 0) if (profiles.SonarrRootPath > 0)
{ {
Logger.LogInformation("Using user's standard root path override: {RootPath}", profiles.SonarrRootPath);
rootFolderPath = await GetSonarrRootPath(profiles.SonarrRootPath, s); rootFolderPath = await GetSonarrRootPath(profiles.SonarrRootPath, s);
} }
if (profiles.SonarrQualityProfile > 0) if (profiles.SonarrQualityProfile > 0)
@ -198,23 +216,31 @@ namespace Ombi.Core.Senders
} }
// Overrides on the request take priority // Overrides on the request take priority
if (model.ParentRequest.QualityOverride.HasValue && model.ParentRequest.QualityOverride.Value > 0) if (model.ParentRequest.QualityOverride.HasValue)
{ {
qualityToUse = model.ParentRequest.QualityOverride.Value; var qualityOverride = model.ParentRequest.QualityOverride.Value;
if (qualityOverride > 0)
{
qualityToUse = qualityOverride;
}
}
if (model.ParentRequest.RootFolder.HasValue)
{
var rootfolderOverride = model.ParentRequest.RootFolder.Value;
if (rootfolderOverride > 0)
{
rootFolderPath = await GetSonarrRootPath(rootfolderOverride, s);
}
} }
if (model.ParentRequest.RootFolder.HasValue && model.ParentRequest.RootFolder.Value > 0) if (model.ParentRequest.LanguageProfile.HasValue)
{ {
Logger.LogInformation("Using request root folder override: {RootFolder}", model.ParentRequest.RootFolder.Value); var languageProfile = model.ParentRequest.LanguageProfile.Value;
rootFolderPath = await GetSonarrRootPath(model.ParentRequest.RootFolder.Value, s); if (languageProfile > 0)
}
if (model.ParentRequest.LanguageProfile.HasValue && model.ParentRequest.LanguageProfile.Value > 0)
{ {
languageProfileId = model.ParentRequest.LanguageProfile.Value; languageProfileId = languageProfile;
}
} }
Logger.LogInformation("Final root folder path: {RootFolderPath}", rootFolderPath);
try try
{ {
@ -398,10 +424,9 @@ namespace Ombi.Core.Senders
await SonarrApi.MonitorEpisode(epToUnmonitored.Select(x => x.id).ToArray(), false, s.ApiKey, s.FullUri); await SonarrApi.MonitorEpisode(epToUnmonitored.Select(x => x.id).ToArray(), false, s.ApiKey, s.FullUri);
} }
}
// Now update the episodes that need updating // Now update the episodes that need updating
await SonarrApi.MonitorEpisode(episodesToUpdate.Select(x => x.id).ToArray(), true, s.ApiKey, s.FullUri); await SonarrApi.MonitorEpisode(episodesToUpdate.Where(x => x.seasonNumber == season.SeasonNumber).Select(x => x.id).ToArray(), true, s.ApiKey, s.FullUri);
}
if (!s.AddOnly) if (!s.AddOnly)
{ {
@ -535,36 +560,17 @@ namespace Ombi.Core.Senders
private async Task<string> GetSonarrRootPath(int pathId, SonarrSettings sonarrSettings) private async Task<string> GetSonarrRootPath(int pathId, SonarrSettings sonarrSettings)
{ {
Logger.LogInformation("Getting Sonarr root path for ID: {PathId}", pathId);
var rootFoldersResult = await SonarrApi.GetRootFolders(sonarrSettings.ApiKey, sonarrSettings.FullUri); var rootFoldersResult = await SonarrApi.GetRootFolders(sonarrSettings.ApiKey, sonarrSettings.FullUri);
if (rootFoldersResult == null || !rootFoldersResult.Any())
{
Logger.LogError("No root folders returned from Sonarr API");
return string.Empty;
}
Logger.LogInformation("Found {Count} root folders in Sonarr", rootFoldersResult.Count());
foreach (var folder in rootFoldersResult)
{
Logger.LogDebug("Root folder - ID: {Id}, Path: {Path}", folder.id, folder.path);
}
if (pathId == 0) if (pathId == 0)
{ {
var defaultPath = rootFoldersResult.FirstOrDefault()?.path; return rootFoldersResult.FirstOrDefault().path;
Logger.LogInformation("Using first root folder as default: {Path}", defaultPath);
return defaultPath;
} }
var matchingFolder = rootFoldersResult.FirstOrDefault(r => r.id == pathId); foreach (var r in rootFoldersResult?.Where(r => r.id == pathId))
if (matchingFolder != null)
{ {
Logger.LogInformation("Found matching root folder for ID {PathId}: {Path}", pathId, matchingFolder.path); return r.path;
return matchingFolder.path;
} }
Logger.LogError("No matching root folder found for ID: {PathId}", pathId);
return string.Empty; return string.Empty;
} }
} }

View file

@ -1,69 +0,0 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Ombi.Core.Helpers;
using Ombi.Core.Models;
using Ombi.Helpers;
namespace Ombi.Core.Services;
public class DatabaseConfigurationService : IDatabaseConfigurationService
{
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
public DatabaseConfigurationService(
ILogger<DatabaseConfigurationService> logger,
IFileSystem fileSystem)
{
_logger = logger;
_fileSystem = fileSystem;
}
public async Task<bool> ConfigureDatabase(string databaseType, string connectionString, CancellationToken token)
{
var i = StartupSingleton.Instance;
if (string.IsNullOrEmpty(i.StoragePath))
{
i.StoragePath = string.Empty;
}
var databaseFileLocation = Path.Combine(i.StoragePath, "database.json");
if (_fileSystem.FileExists(databaseFileLocation))
{
var error = $"The database file at '{databaseFileLocation}' already exists";
_logger.LogError(error);
return false;
}
var configuration = new DatabaseConfiguration
{
ExternalDatabase = new PerDatabaseConfiguration(databaseType, connectionString),
OmbiDatabase = new PerDatabaseConfiguration(databaseType, connectionString),
SettingsDatabase = new PerDatabaseConfiguration(databaseType, connectionString)
};
var json = JsonConvert.SerializeObject(configuration, Formatting.Indented);
_logger.LogInformation("Writing database configuration to file");
try
{
await File.WriteAllTextAsync(databaseFileLocation, json, token);
}
catch (Exception e)
{
_logger.LogError(e, "Failed to write database configuration to file");
return false;
}
_logger.LogInformation("Database configuration written to file");
return true;
}
}

View file

@ -1,11 +0,0 @@
using System.Threading;
using System.Threading.Tasks;
namespace Ombi.Core.Services;
public interface IDatabaseConfigurationService
{
const string MySqlDatabase = "MySQL";
const string PostgresDatabase = "Postgres";
Task<bool> ConfigureDatabase(string databaseType, string connectionString, CancellationToken token);
}

View file

@ -107,7 +107,6 @@ namespace Ombi.DependencyInjection
services.AddTransient<IMusicSender, MusicSender>(); services.AddTransient<IMusicSender, MusicSender>();
services.AddTransient<IMassEmailSender, MassEmailSender>(); services.AddTransient<IMassEmailSender, MassEmailSender>();
services.AddTransient<IPlexOAuthManager, PlexOAuthManager>(); services.AddTransient<IPlexOAuthManager, PlexOAuthManager>();
services.AddTransient<IPlexTokenKeepAliveService, PlexTokenKeepAliveService>();
services.AddTransient<IVoteEngine, VoteEngine>(); services.AddTransient<IVoteEngine, VoteEngine>();
services.AddTransient<IDemoMovieSearchEngine, DemoMovieSearchEngine>(); services.AddTransient<IDemoMovieSearchEngine, DemoMovieSearchEngine>();
services.AddTransient<IDemoTvSearchEngine, DemoTvSearchEngine>(); services.AddTransient<IDemoTvSearchEngine, DemoTvSearchEngine>();
@ -198,8 +197,6 @@ namespace Ombi.DependencyInjection
services.AddScoped<IEmbyContentRepository, EmbyContentRepository>(); services.AddScoped<IEmbyContentRepository, EmbyContentRepository>();
services.AddScoped<IJellyfinContentRepository, JellyfinContentRepository>(); services.AddScoped<IJellyfinContentRepository, JellyfinContentRepository>();
services.AddScoped<INotificationTemplatesRepository, NotificationTemplatesRepository>(); services.AddScoped<INotificationTemplatesRepository, NotificationTemplatesRepository>();
services.AddScoped<IUserPlayedMovieRepository, UserPlayedMovieRepository>();
services.AddScoped<IUserPlayedEpisodeRepository, UserPlayedEpisodeRepository>();
services.AddScoped<ITvRequestRepository, TvRequestRepository>(); services.AddScoped<ITvRequestRepository, TvRequestRepository>();
services.AddScoped<IMovieRequestRepository, MovieRequestRepository>(); services.AddScoped<IMovieRequestRepository, MovieRequestRepository>();
@ -237,8 +234,6 @@ namespace Ombi.DependencyInjection
services.AddScoped<IFeatureService, FeatureService>(); services.AddScoped<IFeatureService, FeatureService>();
services.AddTransient<IRecentlyRequestedService, RecentlyRequestedService>(); services.AddTransient<IRecentlyRequestedService, RecentlyRequestedService>();
services.AddTransient<IPlexService, PlexService>(); services.AddTransient<IPlexService, PlexService>();
services.AddSingleton<IFileSystem, FileSystem>();
services.AddSingleton<IDatabaseConfigurationService, DatabaseConfigurationService>();
} }
public static void RegisterJobs(this IServiceCollection services) public static void RegisterJobs(this IServiceCollection services)
@ -249,7 +244,6 @@ namespace Ombi.DependencyInjection
services.AddTransient<IPlexContentSync, PlexContentSync>(); services.AddTransient<IPlexContentSync, PlexContentSync>();
services.AddTransient<IPlexWatchlistImport, PlexWatchlistImport>(); services.AddTransient<IPlexWatchlistImport, PlexWatchlistImport>();
services.AddTransient<IEmbyContentSync, EmbyContentSync>(); services.AddTransient<IEmbyContentSync, EmbyContentSync>();
services.AddTransient<IEmbyPlayedSync, EmbyPlayedSync>();
services.AddTransient<IEmbyEpisodeSync, EmbyEpisodeSync>(); services.AddTransient<IEmbyEpisodeSync, EmbyEpisodeSync>();
services.AddTransient<IEmbyAvaliabilityChecker, EmbyAvaliabilityChecker>(); services.AddTransient<IEmbyAvaliabilityChecker, EmbyAvaliabilityChecker>();
services.AddTransient<IJellyfinContentSync, JellyfinContentSync>(); services.AddTransient<IJellyfinContentSync, JellyfinContentSync>();

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>
@ -11,9 +11,10 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="8.0.5" /> <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="6.0.9" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" /> <PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -1,5 +1,8 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.Extensions.Diagnostics.HealthChecks;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;

View file

@ -1,9 +1,17 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.Extensions.Diagnostics.HealthChecks;
using Ombi.Api.CouchPotato; using Ombi.Api.CouchPotato;
using Ombi.Api.Emby;
using Ombi.Api.Emby.Models;
using Ombi.Api.Jellyfin;
using Ombi.Api.Jellyfin.Models;
using Ombi.Api.Plex;
using Ombi.Api.Plex.Models.Status;
using Ombi.Core.Settings; using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External;
using Ombi.Settings.Settings.Models.External; using Ombi.Settings.Settings.Models.External;
using System; using System;
using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;

View file

@ -2,6 +2,8 @@
using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.Extensions.Diagnostics.HealthChecks;
using Ombi.Api.Emby; using Ombi.Api.Emby;
using Ombi.Api.Emby.Models; using Ombi.Api.Emby.Models;
using Ombi.Api.Plex;
using Ombi.Api.Plex.Models.Status;
using Ombi.Core.Settings; using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External; using Ombi.Core.Settings.Models.External;
using System; using System;

View file

@ -2,6 +2,8 @@
using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.Extensions.Diagnostics.HealthChecks;
using Ombi.Api.Jellyfin; using Ombi.Api.Jellyfin;
using Ombi.Api.Jellyfin.Models; using Ombi.Api.Jellyfin.Models;
using Ombi.Api.Plex;
using Ombi.Api.Plex.Models.Status;
using Ombi.Core.Settings; using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External; using Ombi.Core.Settings.Models.External;
using System; using System;

View file

@ -1,9 +1,18 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.Extensions.Diagnostics.HealthChecks;
using Ombi.Api.CouchPotato;
using Ombi.Api.Emby;
using Ombi.Api.Emby.Models;
using Ombi.Api.Jellyfin;
using Ombi.Api.Jellyfin.Models;
using Ombi.Api.Plex;
using Ombi.Api.Plex.Models.Status;
using Ombi.Api.SickRage; using Ombi.Api.SickRage;
using Ombi.Core.Settings; using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External;
using Ombi.Settings.Settings.Models.External; using Ombi.Settings.Settings.Models.External;
using System; using System;
using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;

View file

@ -1,5 +1,8 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Ombi.HealthChecks.Checks; using Ombi.HealthChecks.Checks;
using System;
using System.Collections.Generic;
namespace Ombi.HealthChecks namespace Ombi.HealthChecks
{ {

View file

@ -1,12 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<Configurations>Debug;Release;NonUiBuild</Configurations> <Configurations>Debug;Release;NonUiBuild</Configurations>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AspNetCore.HealthChecks.Network" Version="6.0.4" /> <PackageReference Include="AspNetCore.HealthChecks.Network" Version="6.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="2.2.0" />
<PackageReference Include="System.Collections" Version="4.3.0" /> <PackageReference Include="System.Collections" Version="4.3.0" />
</ItemGroup> </ItemGroup>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
@ -10,9 +10,9 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="nunit" Version="3.13.3" /> <PackageReference Include="nunit" Version="3.13.3" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" /> <PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" /> <PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.2" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -14,7 +14,6 @@
IssueResolved = 9, IssueResolved = 9,
IssueComment = 10, IssueComment = 10,
Newsletter = 11, Newsletter = 11,
PartiallyAvailable = 12, PartiallyAvailable = 12
PlexWatchlistTokenExpired = 13
} }
} }

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>
@ -11,13 +11,13 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="EasyCrypto" Version="4.6.0" /> <PackageReference Include="EasyCrypto" Version="4.5.0" />
<PackageReference Include="LazyCache.AspNetCore" Version="2.4.0" /> <PackageReference Include="LazyCache.AspNetCore" Version="2.4.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Nito.AsyncEx" Version="5.1.2" /> <PackageReference Include="Nito.AsyncEx" Version="5.1.2" />
<PackageReference Include="Quartz" Version="3.6.2" /> <PackageReference Include="Quartz" Version="3.5.0" />
<PackageReference Include="System.Security.Claims" Version="4.3.0" /> <PackageReference Include="System.Security.Claims" Version="4.3.0" />
</ItemGroup> </ItemGroup>

View file

@ -2,7 +2,7 @@
{ {
public static class OmbiRoles public static class OmbiRoles
{ {
// DONT FORGET TO ADD TO IDENTITYCONTROLLER.CREATEROLES! // DONT FORGET TO ADD TO IDENTITYCONTROLLER.CREATEROLES AND THE UI!
public const string Admin = nameof(Admin); public const string Admin = nameof(Admin);
public const string AutoApproveMovie = nameof(AutoApproveMovie); public const string AutoApproveMovie = nameof(AutoApproveMovie);
@ -17,6 +17,5 @@
public const string ManageOwnRequests = nameof(ManageOwnRequests); public const string ManageOwnRequests = nameof(ManageOwnRequests);
public const string EditCustomPage = nameof(EditCustomPage); public const string EditCustomPage = nameof(EditCustomPage);
public const string Request4KMovie = nameof(Request4KMovie); public const string Request4KMovie = nameof(Request4KMovie);
public const string AutoApprove4KMovie = nameof(AutoApprove4KMovie);
} }
} }

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<Configurations>Debug;Release;NonUiBuild</Configurations> <Configurations>Debug;Release;NonUiBuild</Configurations>
</PropertyGroup> </PropertyGroup>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>

View file

@ -118,39 +118,39 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="NewAlbums" xml:space="preserve"> <data name="NewAlbums" xml:space="preserve">
<value>Novos álbuns</value> <value>New Albums</value>
</data> </data>
<data name="NewMovies" xml:space="preserve"> <data name="NewMovies" xml:space="preserve">
<value>Novos filmes</value> <value>New Movies</value>
</data> </data>
<data name="NewTV" xml:space="preserve"> <data name="NewTV" xml:space="preserve">
<value>Novas séries</value> <value>New TV</value>
</data> </data>
<data name="GenresLabel" xml:space="preserve"> <data name="GenresLabel" xml:space="preserve">
<value>Gêneros:</value> <value>Gêneros:</value>
</data> </data>
<data name="AlbumTypeLabel" xml:space="preserve"> <data name="AlbumTypeLabel" xml:space="preserve">
<value>Tipo:</value> <value>Type:</value>
</data> </data>
<data name="SeasonLabel" xml:space="preserve"> <data name="SeasonLabel" xml:space="preserve">
<value>Temporadas:</value> <value>Temporada:</value>
</data> </data>
<data name="EpisodesLabel" xml:space="preserve"> <data name="EpisodesLabel" xml:space="preserve">
<value>Episódios:</value> <value>Episodes:</value>
</data> </data>
<data name="PoweredBy" xml:space="preserve"> <data name="PoweredBy" xml:space="preserve">
<value>Distribuído por</value> <value>Powered by</value>
</data> </data>
<data name="Unsubscribe" xml:space="preserve"> <data name="Unsubscribe" xml:space="preserve">
<value>Cancelar subscrição</value> <value>Unsubscribe</value>
</data> </data>
<data name="Album" xml:space="preserve"> <data name="Album" xml:space="preserve">
<value>Álbum</value> <value>Album</value>
</data> </data>
<data name="Movie" xml:space="preserve"> <data name="Movie" xml:space="preserve">
<value>Filmes</value> <value>Movie</value>
</data> </data>
<data name="TvShow" xml:space="preserve"> <data name="TvShow" xml:space="preserve">
<value>Séries</value> <value>TV Show</value>
</data> </data>
</root> </root>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion> <AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion> <FileVersion>3.0.0.0</FileVersion>
<Version></Version> <Version></Version>

View file

@ -12,9 +12,12 @@ namespace Ombi.Notifications.Templates
{ {
if (string.IsNullOrEmpty(_templateLocation)) if (string.IsNullOrEmpty(_templateLocation))
{ {
//_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "net6.0", "Templates", #if DEBUG
// "BasicTemplate.html"); _templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "net6.0", "Templates",
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "Templates", "BasicTemplate.html"); "BasicTemplate.html");
#else
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "Templates","BasicTemplate.html");
#endif
} }
return _templateLocation; return _templateLocation;
} }
@ -40,8 +43,7 @@ namespace Ombi.Notifications.Templates
return sb.ToString(); return sb.ToString();
} }
private string GetPosterContent(string imgsrc, string url) private string GetPosterContent(string imgsrc, string url) {
{
string posterContent; string posterContent;
if (string.IsNullOrEmpty(imgsrc)) if (string.IsNullOrEmpty(imgsrc))

Some files were not shown because too many files have changed in this diff Show more