mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-30 19:40:05 -07:00
commit
ae17abdd8d
206 changed files with 3570 additions and 1344 deletions
10
.github/workflows/build.yml
vendored
10
.github/workflows/build.yml
vendored
|
@ -3,6 +3,7 @@ name: CI Build
|
|||
on:
|
||||
push:
|
||||
branches: [ develop, master ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-ui:
|
||||
|
@ -38,7 +39,7 @@ jobs:
|
|||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: '5.0.x'
|
||||
dotnet-version: '6.0.x'
|
||||
|
||||
- name: Nuget Cache
|
||||
uses: actions/cache@v2
|
||||
|
@ -67,6 +68,7 @@ jobs:
|
|||
uses: TriPSs/conventional-changelog-action@v3
|
||||
with:
|
||||
version-file: 'version.json'
|
||||
release-count: 40
|
||||
skip-on-empty: 'false'
|
||||
git-message: 'chore(release): :rocket: {version}'
|
||||
|
||||
|
@ -102,6 +104,12 @@ jobs:
|
|||
format: tar.gz
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: '6.0.x'
|
||||
- uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: '5.0.x'
|
||||
|
||||
- name: Nuget Cache
|
||||
uses: actions/cache@v2
|
||||
|
|
5
.github/workflows/cypress.yml
vendored
5
.github/workflows/cypress.yml
vendored
|
@ -7,6 +7,7 @@ on:
|
|||
branches: [ develop ]
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
automation-tests:
|
||||
|
@ -18,7 +19,7 @@ jobs:
|
|||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 5.0.x
|
||||
dotnet-version: 6.0.x
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
|
@ -38,7 +39,7 @@ jobs:
|
|||
|
||||
- name: Start Backend
|
||||
run: |
|
||||
nohup dotnet run -p ./src/Ombi -- --host http://*:3577 &
|
||||
nohup dotnet run --project ./src/Ombi -- --host http://*:3577 &
|
||||
- name: Start Frontend
|
||||
run: |
|
||||
nohup yarn --cwd ./src/Ombi/ClientApp start &
|
||||
|
|
6
.github/workflows/pr.yml
vendored
6
.github/workflows/pr.yml
vendored
|
@ -3,6 +3,7 @@ name: PR Build
|
|||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-ui:
|
||||
|
@ -31,7 +32,7 @@ jobs:
|
|||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: '5.0.x'
|
||||
dotnet-version: '6.0.x'
|
||||
|
||||
- name: Nuget Cache
|
||||
uses: actions/cache@v2
|
||||
|
@ -89,6 +90,9 @@ jobs:
|
|||
format: tar.gz
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: '6.0.x'
|
||||
|
||||
- name: Nuget Cache
|
||||
uses: actions/cache@v2
|
||||
|
|
320
CHANGELOG.md
320
CHANGELOG.md
|
@ -1,3 +1,248 @@
|
|||
## [4.10.1](https://github.com/Ombi-app/Ombi/compare/v4.10.0...v4.10.1) (2022-01-22)
|
||||
|
||||
|
||||
|
||||
## [4.3.3](https://github.com/Ombi-app/Ombi/compare/v4.3.2...v4.3.3) (2021-11-05)
|
||||
|
||||
|
||||
|
||||
# [4.10.0](https://github.com/Ombi-app/Ombi/compare/v4.9.2...v4.10.0) (2022-01-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **notifications:** :sparkles: Send new request email notifications to power users ([#4462](https://github.com/Ombi-app/Ombi/issues/4462)) ([10cc0c0](https://github.com/Ombi-app/Ombi/commit/10cc0c0951f13221179516f8ff5c44dbecc9a0fd))
|
||||
|
||||
|
||||
|
||||
## [4.9.2](https://github.com/Ombi-app/Ombi/compare/v4.9.1...v4.9.2) (2022-01-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* :bug: Add UI for Emby recently added cronjob settings ([#4469](https://github.com/Ombi-app/Ombi/issues/4469)) ([7d47bbe](https://github.com/Ombi-app/Ombi/commit/7d47bbe92204855bf75d70b8fa548f9c3f3612bc))
|
||||
* **sonarr:** :bug: Fixed an issue where we could attempt to add a series to sonarr before sonarr has got all the metadata [#4459](https://github.com/Ombi-app/Ombi/issues/4459) ([5c691dc](https://github.com/Ombi-app/Ombi/commit/5c691dc98437a4cd24560ff625414fe05dd22f89))
|
||||
* **wizard:** :bug: Fixed the issue where the Application Url wasn't validated in the wizard ([33b8d11](https://github.com/Ombi-app/Ombi/commit/33b8d1111a1c6663d8c0bbd912be4660da7d013f)), closes [#4417](https://github.com/Ombi-app/Ombi/issues/4417)
|
||||
|
||||
|
||||
|
||||
## [4.9.1](https://github.com/Ombi-app/Ombi/compare/v4.9.0...v4.9.1) (2022-01-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **discover:** 🌐 Localize episodes names in TV details ([#4467](https://github.com/Ombi-app/Ombi/issues/4467)) [skip ci] ([35806ea](https://github.com/Ombi-app/Ombi/commit/35806ea2d2c866d628cf08577026a02ab04e49d9))
|
||||
* **email-notifications:** :bug: Fixed the issue where legacy requests were showing broken poster images [#4452](https://github.com/Ombi-app/Ombi/issues/4452) ([0ece2fd](https://github.com/Ombi-app/Ombi/commit/0ece2fd6e0eb01e0b7d4d2a01e1a276c7a9c5a51))
|
||||
* **emby/jellyfin:** :bug: A more reliable Emby and Jellyfin sync [skip ci] ([ad677fa](https://github.com/Ombi-app/Ombi/commit/ad677fa02eb75633014e9c9791c21ed2d6a23229))
|
||||
|
||||
|
||||
|
||||
# [4.9.0](https://github.com/Ombi-app/Ombi/compare/v4.8.1...v4.9.0) (2022-01-05)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **customization:** :sparkles: Added possibility for custom favicons ([40af659](https://github.com/Ombi-app/Ombi/commit/40af6593b668d4712327c18f92f5b7b5a0a65e26))
|
||||
|
||||
|
||||
|
||||
## [4.8.1](https://github.com/Ombi-app/Ombi/compare/v4.8.0...v4.8.1) (2022-01-04)
|
||||
|
||||
|
||||
|
||||
# [4.8.0](https://github.com/Ombi-app/Ombi/compare/v4.7.11...v4.8.0) (2021-12-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **auto-delete:** :bug: We now also auto delete music requests, this was previously missing ([9fe1f8e](https://github.com/Ombi-app/Ombi/commit/9fe1f8e988aa31d36e7a685ae19f72d9c8414dc0))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **details:** :sparkles: Added the notify button back into the details pages for requests ([8b33cdc](https://github.com/Ombi-app/Ombi/commit/8b33cdccef83db8794414b247438214b00860fac))
|
||||
|
||||
|
||||
|
||||
## [4.7.11](https://github.com/Ombi-app/Ombi/compare/v4.7.10...v4.7.11) (2021-12-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **availability-rules:** :bug: Show the 'Requested' button when a show has all of the episodes marked as requested ([cb7ecf6](https://github.com/Ombi-app/Ombi/commit/cb7ecf684ac3ab204f329a28baecfd4f6cd408f7))
|
||||
|
||||
|
||||
|
||||
## [4.7.10](https://github.com/Ombi-app/Ombi/compare/v4.7.9...v4.7.10) (2021-12-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **discover:** :bug: Fixed an issue where monitored movies in radarr were not correctly represented on the search results ([75b15bc](https://github.com/Ombi-app/Ombi/commit/75b15bc7cba21f0a14a18c8e64fd52482f5c6325))
|
||||
|
||||
|
||||
|
||||
## [4.7.9](https://github.com/Ombi-app/Ombi/compare/v4.7.8...v4.7.9) (2021-12-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **sonarr:** :bug: Fixed an issue where we were sometimes incorrectly setting the state of episodes that are already monitored in sonarr ([fd1acb8](https://github.com/Ombi-app/Ombi/commit/fd1acb88cbc5e73f91b7f81e6e28ee06d66b277e))
|
||||
|
||||
|
||||
|
||||
## [4.7.8](https://github.com/Ombi-app/Ombi/compare/v4.7.7...v4.7.8) (2021-12-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **notifications:** :bug: Fixed the DenyReason sometimes not appearing in the notification message [#4409](https://github.com/Ombi-app/Ombi/issues/4409) ([209e311](https://github.com/Ombi-app/Ombi/commit/209e31175c95f6ee8909d878d45bf8269a9842d9))
|
||||
* **oauth:** :lock: Fixed the issue where some users running their browsers in a different language could not open the Plex OAuth window ([d5404ea](https://github.com/Ombi-app/Ombi/commit/d5404eaad7837010d6e4563cd8f7a1009231d362)), closes [#4408](https://github.com/Ombi-app/Ombi/issues/4408)
|
||||
* **translations:** 🌐 New translations from Crowdin ([5cfb76c](https://github.com/Ombi-app/Ombi/commit/5cfb76cad7a25eed8b452bf9c01cef8c32804369))
|
||||
|
||||
|
||||
|
||||
## [4.7.7](https://github.com/Ombi-app/Ombi/compare/v4.7.6...v4.7.7) (2021-12-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **notifications:** 🐛 Do not notify user upon auto approval of a TV show ([#4432](https://github.com/Ombi-app/Ombi/issues/4432)) ([3ad3bdd](https://github.com/Ombi-app/Ombi/commit/3ad3bddd8313d607ee2a39a51a92e61a3673082c)), closes [#4431](https://github.com/Ombi-app/Ombi/issues/4431)
|
||||
* **translations:** 🌐 New translations from Crowdin ([8943a97](https://github.com/Ombi-app/Ombi/commit/8943a978bf459eaeb496d50c61c4d1506c727366))
|
||||
|
||||
|
||||
|
||||
## [4.7.6](https://github.com/Ombi-app/Ombi/compare/v4.7.5...v4.7.6) (2021-12-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **user-management:** :bug: Fixed an issue where you couldn't 'unset' a users custom quality and root folders ([bae96af](https://github.com/Ombi-app/Ombi/commit/bae96af17f50a80ae3ade235a5ef68d5d2dc12ba))
|
||||
|
||||
|
||||
|
||||
## [4.7.5](https://github.com/Ombi-app/Ombi/compare/v4.7.4...v4.7.5) (2021-11-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **notifications:** fixed an error that could happen when Ombi sends out a issue notification ([7442dcf](https://github.com/Ombi-app/Ombi/commit/7442dcf59da5d2190cc3087b10402e85bcfcf83b))
|
||||
* **translations:** 🌐 Fix incorrect text translation reference RequestedByOn ([#4420](https://github.com/Ombi-app/Ombi/issues/4420)) ([202d155](https://github.com/Ombi-app/Ombi/commit/202d155493c29a6ddd4c5507186bf376a28f4c1d))
|
||||
* **translations:** 🌐 New translations from Crowdin ([473c172](https://github.com/Ombi-app/Ombi/commit/473c1724922515fe376e0b2058ac391807c923f2))
|
||||
|
||||
|
||||
|
||||
## [4.7.4](https://github.com/Ombi-app/Ombi/compare/v4.7.3...v4.7.4) (2021-11-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **availability-rules:** :bug: Fixed a small issue where some shows would not appear as Available even know they had no future unaired episodes listed ([914b096](https://github.com/Ombi-app/Ombi/commit/914b096781c9b73292a533a010a5dd05ecfd0aac))
|
||||
* **emby:** :bug: Fixed an issue where we were not properly syncing episodes ([75529dd](https://github.com/Ombi-app/Ombi/commit/75529dd972c5102f3c5234a2acf6fe664a1bcfad))
|
||||
|
||||
|
||||
|
||||
## [4.7.3](https://github.com/Ombi-app/Ombi/compare/v4.7.2...v4.7.3) (2021-11-23)
|
||||
|
||||
|
||||
|
||||
## [4.7.2](https://github.com/Ombi-app/Ombi/compare/v4.7.1...v4.7.2) (2021-11-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **request-list:** :bug: Fixed an issue where the bulk delete would not work for movie requests ([4b540fb](https://github.com/Ombi-app/Ombi/commit/4b540fb45bcc389664f0953159802288d005db9f))
|
||||
|
||||
|
||||
|
||||
## [4.7.1](https://github.com/Ombi-app/Ombi/compare/v4.7.0...v4.7.1) (2021-11-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **emby:** :bug: Fixed an issue where we slightly broke the full sync ([332d934](https://github.com/Ombi-app/Ombi/commit/332d9344d002a5ffd5aeac516c7441dcdec52248))
|
||||
|
||||
|
||||
|
||||
# [4.7.0](https://github.com/Ombi-app/Ombi/compare/v4.6.5...v4.7.0) (2021-11-19)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **emby:** :sparkles: Added a emby recently added sync! ([a0e1406](https://github.com/Ombi-app/Ombi/commit/a0e14068f4bc457f8a4a565de71707a8f16c803c))
|
||||
|
||||
|
||||
|
||||
## [4.6.5](https://github.com/Ombi-app/Ombi/compare/v4.6.4...v4.6.5) (2021-11-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **issues:** :bug: Added the issue category to the issue 'cards' [#4403](https://github.com/Ombi-app/Ombi/issues/4403) ([a3739f3](https://github.com/Ombi-app/Ombi/commit/a3739f375c49f48e34da12f0a74e4e068f12ab40))
|
||||
* **issues:** :bug: Added the issues back to the details page for TV Shows ([0225000](https://github.com/Ombi-app/Ombi/commit/02250000c08a253e57d8a0a855c2d30b8a1e5baa))
|
||||
* **issues:** :bug: Fixed an issue where you couldn't navigate to the details page from TV issues ([1a2825b](https://github.com/Ombi-app/Ombi/commit/1a2825bf3839b891b16e1dde4030afe53efe090e))
|
||||
* **issues:** :bug: Fixed where we did not show the poster when an issue is raised for media we do not have a request for [#4402](https://github.com/Ombi-app/Ombi/issues/4402) ([15e37b5](https://github.com/Ombi-app/Ombi/commit/15e37b532a83097dbdf1a9fea3eead7d0e211898))
|
||||
|
||||
|
||||
|
||||
## [4.6.4](https://github.com/Ombi-app/Ombi/compare/v4.6.3...v4.6.4) (2021-11-12)
|
||||
|
||||
|
||||
|
||||
## [4.6.3](https://github.com/Ombi-app/Ombi/compare/v4.6.2...v4.6.3) (2021-11-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **discover:** :bug: Display TV + movies on actor page in user language ([#4395](https://github.com/Ombi-app/Ombi/issues/4395)) ([fe635c7](https://github.com/Ombi-app/Ombi/commit/fe635c7106bc487ff879bdc8a73bab16cb389b97))
|
||||
* **permissions:** :bug: Improved the security around the role "Manage Own Requests" ([#4397](https://github.com/Ombi-app/Ombi/issues/4397)) ([334a32b](https://github.com/Ombi-app/Ombi/commit/334a32bca42f90198d9b720d2bdb710a583be47f)), closes [#4391](https://github.com/Ombi-app/Ombi/issues/4391)
|
||||
* **search:** Fixed some cases where search wouldn't work correctly ([#4398](https://github.com/Ombi-app/Ombi/issues/4398)) ([4410790](https://github.com/Ombi-app/Ombi/commit/4410790bc096826bc11554098f846e3acb59589a))
|
||||
|
||||
|
||||
|
||||
## [4.6.2](https://github.com/Ombi-app/Ombi/compare/v4.6.1...v4.6.2) (2021-11-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **discover:** TV shows now display on the Actor Pages ([#4388](https://github.com/Ombi-app/Ombi/issues/4388)) ([6b716e7](https://github.com/Ombi-app/Ombi/commit/6b716e722076e3d1e6bf2097c5263645d5ea9edf))
|
||||
|
||||
|
||||
|
||||
## [4.6.1](https://github.com/Ombi-app/Ombi/compare/v4.6.0...v4.6.1) (2021-11-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* :bug: Fixed the MySQL issue after .net 6 upgrade [#4393](https://github.com/Ombi-app/Ombi/issues/4393) ([fea7ff0](https://github.com/Ombi-app/Ombi/commit/fea7ff05139e9ff50c8097fa5389b4ef9ad21a15))
|
||||
* **translations:** 🌐 New translations from Crowdin [skip ci] ([c6acb45](https://github.com/Ombi-app/Ombi/commit/c6acb45f8d3f371c0b4024c4272849d0d0cc867f))
|
||||
* **translations:** 🌐 New translations from Crowdin [skip ci] ([18c220a](https://github.com/Ombi-app/Ombi/commit/18c220a0cd0d19e45a07d0c319da2b9512778a8a))
|
||||
|
||||
|
||||
|
||||
# [4.6.0](https://github.com/Ombi-app/Ombi/compare/v4.4.0...v4.6.0) (2021-11-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* :sparkles: Upgrade Ombi to .NET 6 ([#4390](https://github.com/Ombi-app/Ombi/issues/4390)) ([719eb7d](https://github.com/Ombi-app/Ombi/commit/719eb7dbe37b3a72d264e2f670067518eef70694)), closes [#4392](https://github.com/Ombi-app/Ombi/issues/4392)
|
||||
|
||||
|
||||
|
||||
# [4.4.0](https://github.com/Ombi-app/Ombi/compare/v4.3.3...v4.4.0) (2021-11-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **request-list:** :bug: Fixed an issue where the request options were not appearing for Music requests ([c0406a2](https://github.com/Ombi-app/Ombi/commit/c0406a2ddebafb03d98ed25cdf7d89dc9a600c7d))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **mass-email:** :sparkles: Added the ability to configure the Mass Email, we can now send BCC and we are less likely to be rate limited when not using bcc [#4377](https://github.com/Ombi-app/Ombi/issues/4377) ([ca655ae](https://github.com/Ombi-app/Ombi/commit/ca655ae57042dec44106a2f2ef5ba2e6f1019ee4))
|
||||
|
||||
|
||||
|
||||
## [4.3.3](https://github.com/Ombi-app/Ombi/compare/v4.3.2...v4.3.3) (2021-11-05)
|
||||
|
||||
|
||||
|
@ -60,3 +305,78 @@
|
|||
|
||||
|
||||
|
||||
## [4.2.12](https://github.com/Ombi-app/Ombi/compare/v4.2.11...v4.2.12) (2021-10-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **newsletter:** :bug: Fixed a few small bugs in the newsletter ([21dba4c](https://github.com/Ombi-app/Ombi/commit/21dba4c524b98b9f2b883d97e7e13329425a8762))
|
||||
* **translations:** 🌐 New translations en.json from Crowdin [skip ci] ([52eda6a](https://github.com/Ombi-app/Ombi/commit/52eda6ab917a73842bc02b0d8e0c442e564ca8f0))
|
||||
* **translations:** 🌐 New translations en.json from Crowdin [skip ci] ([1095d52](https://github.com/Ombi-app/Ombi/commit/1095d524962648a1e427f0bcd8105fa734dd5b60))
|
||||
|
||||
|
||||
|
||||
## [4.2.11](https://github.com/Ombi-app/Ombi/compare/v4.2.10...v4.2.11) (2021-10-18)
|
||||
|
||||
|
||||
|
||||
## [4.2.10](https://github.com/Ombi-app/Ombi/compare/v4.2.9...v4.2.10) (2021-10-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* :bug: Really really fix it this time? ([543d36e](https://github.com/Ombi-app/Ombi/commit/543d36e5615341bc8378cac377b843a3dbc1ef99))
|
||||
|
||||
|
||||
|
||||
## [4.2.9](https://github.com/Ombi-app/Ombi/compare/v4.2.8...v4.2.9) (2021-10-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* :fire: Really fix the base url issue this time ([9f36923](https://github.com/Ombi-app/Ombi/commit/9f36923c51bfabf9cb026f2da14f9947050af0d9))
|
||||
|
||||
|
||||
|
||||
## [4.2.8](https://github.com/Ombi-app/Ombi/compare/v4.2.7...v4.2.8) (2021-10-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* :adhesive_bandage: See if this fixes the proxy issue ([74d1aca](https://github.com/Ombi-app/Ombi/commit/74d1acae499707a7e21401f53eb2bb90c5bb9cfa))
|
||||
* :bug: Fixed Ombi not writing the baseUrl correctly ([e9cc8b6](https://github.com/Ombi-app/Ombi/commit/e9cc8b6fe71d3e10c1a901e70227989b3362afe3))
|
||||
|
||||
|
||||
|
||||
## [4.2.7](https://github.com/Ombi-app/Ombi/compare/v4.2.6...v4.2.7) (2021-10-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* :bug: Fixed the issue parsing TheMovieDB dates. They have broken something... ([6e397e0](https://github.com/Ombi-app/Ombi/commit/6e397e02e95f894a92e8bf02428efdcac1275b31))
|
||||
|
||||
|
||||
|
||||
## [4.2.6](https://github.com/Ombi-app/Ombi/compare/v4.2.5...v4.2.6) (2021-10-14)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* :zap: Use ngxs store for the whole customization section of the app ([97b493d](https://github.com/Ombi-app/Ombi/commit/97b493d869feee59d360b484a6c59388a2aead1f))
|
||||
|
||||
|
||||
|
||||
## [4.2.5](https://github.com/Ombi-app/Ombi/compare/v4.2.4...v4.2.5) (2021-10-14)
|
||||
|
||||
|
||||
|
||||
## [4.2.4](https://github.com/Ombi-app/Ombi/compare/v4.2.3...v4.2.4) (2021-10-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **#4344:** :bug: Fixed an issue where we errored on Plex Episode Scan ([cd5532f](https://github.com/Ombi-app/Ombi/commit/cd5532fa8f7ebbfaf942841398672bafb9a405d4))
|
||||
* **#4345:** :bug: Fixed the issue where denied requests we not appearing correctly ([5a2f652](https://github.com/Ombi-app/Ombi/commit/5a2f652a28f5699dd667afef8dde129817e53392))
|
||||
|
||||
|
||||
|
||||
|
|
41
README.md
41
README.md
|
@ -18,7 +18,7 @@ Don't worry, it's grandma friendly, and more importantly; has wife approval cert
|
|||
|
||||
| Service | Stable | Develop
|
||||
|----------|:---------------------------:|:----------------------------:|
|
||||
| Build Status | [](https://github.com/Ombi-app/Ombi/actions/workflows/build.yml) | [](https://github.com/Ombi-app/Ombi/actions/workflows/build.yml) | [](https://dev.azure.com/tidusjar/Ombi/_build/latest?definitionId=18&branchName=feature%2Fv4)
|
||||
| Build Status | [](https://github.com/Ombi-app/Ombi/actions/workflows/build.yml) | [](https://github.com/Ombi-app/Ombi/actions/workflows/build.yml) | [](https://dev.azure.com/tidusjar/Ombi/_build/latest?definitionId=18&branchName=feature%2Fv4)
|
||||
| Download |[](https://github.com/Ombi-app/Ombi/releases) | [](https://ci.appveyor.com/project/tidusjar/requestplex/branch/develop/artifacts) | [](https://github.com/ombi-app/ombi/releases) |
|
||||
|
||||
# Feature Requests
|
||||
|
@ -135,6 +135,13 @@ Here are some of the features Ombi has:
|
|||
<sub><b>Matt Jeanes</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/sephrat">
|
||||
<img src="https://avatars.githubusercontent.com/u/34862846?v=4" width="50;" alt="sephrat"/>
|
||||
<br />
|
||||
<sub><b>Sephrat</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/bernarden">
|
||||
<img src="https://avatars.githubusercontent.com/u/12289537?v=4" width="50;" alt="bernarden"/>
|
||||
|
@ -148,15 +155,15 @@ Here are some of the features Ombi has:
|
|||
<br />
|
||||
<sub><b>Dhruv Bhavsar</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/joshuaboniface">
|
||||
<img src="https://avatars.githubusercontent.com/u/4031396?v=4" width="50;" alt="joshuaboniface"/>
|
||||
<br />
|
||||
<sub><b>Joshua M. Boniface</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/bruvv">
|
||||
<img src="https://avatars.githubusercontent.com/u/3063928?v=4" width="50;" alt="bruvv"/>
|
||||
|
@ -164,13 +171,6 @@ Here are some of the features Ombi has:
|
|||
<sub><b>Bruvv</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/sephrat">
|
||||
<img src="https://avatars.githubusercontent.com/u/34862846?v=4" width="50;" alt="sephrat"/>
|
||||
<br />
|
||||
<sub><b>Sephrat</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/louis-lau">
|
||||
<img src="https://avatars.githubusercontent.com/u/1346804?v=4" width="50;" alt="louis-lau"/>
|
||||
|
@ -222,10 +222,10 @@ Here are some of the features Ombi has:
|
|||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/stefangross">
|
||||
<img src="https://avatars.githubusercontent.com/u/8499989?v=4" width="50;" alt="stefangross"/>
|
||||
<a href="https://github.com/steffokeffo">
|
||||
<img src="https://avatars.githubusercontent.com/u/8499989?v=4" width="50;" alt="steffokeffo"/>
|
||||
<br />
|
||||
<sub><b>Stefangross</b></sub>
|
||||
<sub><b>Steffokeffo</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
|
@ -730,6 +730,13 @@ Here are some of the features Ombi has:
|
|||
<sub><b>M4tta</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/maartenheebink">
|
||||
<img src="https://avatars.githubusercontent.com/u/28894544?v=4" width="50;" alt="maartenheebink"/>
|
||||
<br />
|
||||
<sub><b>Maartenheebink</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/masterhuck">
|
||||
<img src="https://avatars.githubusercontent.com/u/4671442?v=4" width="50;" alt="masterhuck"/>
|
||||
|
@ -750,15 +757,15 @@ Here are some of the features Ombi has:
|
|||
<br />
|
||||
<sub><b>Tdorsey</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/thegame3202">
|
||||
<img src="https://avatars.githubusercontent.com/u/22148848?v=4" width="50;" alt="thegame3202"/>
|
||||
<br />
|
||||
<sub><b>Mike</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/zobe123">
|
||||
<img src="https://avatars.githubusercontent.com/u/13840542?v=4" width="50;" alt="zobe123"/>
|
||||
|
|
17
makefile
Normal file
17
makefile
Normal file
|
@ -0,0 +1,17 @@
|
|||
backend:
|
||||
cd src/Ombi && dotnet watch run -- --host http://*:3577
|
||||
|
||||
frontend:
|
||||
cd src/Ombi/ClientApp && yarn start
|
||||
|
||||
install-frontend:
|
||||
cd src/Ombi/ClientApp && yarn
|
||||
|
||||
install-frontend-tests:
|
||||
cd tests && yarn
|
||||
|
||||
frontend-tests:
|
||||
cd tests && npx cypress run
|
||||
|
||||
backend-tests:
|
||||
cd src/Ombi.Core.Tests && dotnet test
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
using Newtonsoft.Json;
|
||||
using Ombi.Api.Emby.Models;
|
||||
using Ombi.Api.Emby.Models.Media;
|
||||
using Ombi.Api.Emby.Models.Media.Tv;
|
||||
using Ombi.Api.Emby.Models.Movie;
|
||||
using Ombi.Helpers;
|
||||
|
@ -124,22 +120,36 @@ namespace Ombi.Api.Emby
|
|||
return response;
|
||||
}
|
||||
|
||||
|
||||
public async Task<EmbyItemContainer<EmbyMovie>> GetAllMovies(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri)
|
||||
{
|
||||
return await GetAll<EmbyMovie>("Movie", apiKey, userId, baseUri, true, startIndex, count, parentIdFilder);
|
||||
}
|
||||
|
||||
public async Task<EmbyItemContainer<EmbyMovie>> RecentlyAddedMovies(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri)
|
||||
{
|
||||
return await RecentlyAdded<EmbyMovie>("Movie", apiKey, userId, baseUri, true, startIndex, count, parentIdFilder);
|
||||
}
|
||||
|
||||
public async Task<EmbyItemContainer<EmbyEpisodes>> GetAllEpisodes(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri)
|
||||
{
|
||||
return await GetAll<EmbyEpisodes>("Episode", apiKey, userId, baseUri, false, startIndex, count, parentIdFilder);
|
||||
}
|
||||
|
||||
public async Task<EmbyItemContainer<EmbyEpisodes>> RecentlyAddedEpisodes(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri)
|
||||
{
|
||||
return await RecentlyAdded<EmbyEpisodes>("Episode", apiKey, userId, baseUri, false, startIndex, count, parentIdFilder);
|
||||
}
|
||||
|
||||
public async Task<EmbyItemContainer<EmbySeries>> GetAllShows(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri)
|
||||
{
|
||||
return await GetAll<EmbySeries>("Series", apiKey, userId, baseUri, false, startIndex, count, parentIdFilder);
|
||||
}
|
||||
|
||||
public async Task<EmbyItemContainer<EmbySeries>> RecentlyAddedShows(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri)
|
||||
{
|
||||
return await RecentlyAdded<EmbySeries>("Series", apiKey, userId, baseUri, false, startIndex, count, parentIdFilder);
|
||||
}
|
||||
|
||||
public async Task<SeriesInformation> GetSeriesInformation(string mediaId, string apiKey, string userId, string baseUrl)
|
||||
{
|
||||
return await GetInformation<SeriesInformation>(mediaId, apiKey, userId, baseUrl);
|
||||
|
@ -154,6 +164,31 @@ namespace Ombi.Api.Emby
|
|||
return await GetInformation<EpisodeInformation>(mediaId, apiKey, userId, baseUrl);
|
||||
}
|
||||
|
||||
private async Task<EmbyItemContainer<T>> RecentlyAdded<T>(string type, string apiKey, string userId, string baseUri, bool includeOverview, int startIndex, int count, string parentIdFilder = default)
|
||||
{
|
||||
var request = new Request($"emby/users/{userId}/items", baseUri, HttpMethod.Get);
|
||||
|
||||
request.AddQueryString("Recursive", true.ToString());
|
||||
request.AddQueryString("IncludeItemTypes", type);
|
||||
request.AddQueryString("Fields", includeOverview ? "ProviderIds,Overview" : "ProviderIds");
|
||||
request.AddQueryString("startIndex", startIndex.ToString());
|
||||
request.AddQueryString("limit", count.ToString());
|
||||
request.AddQueryString("sortBy", "DateCreated");
|
||||
request.AddQueryString("SortOrder", "Descending");
|
||||
if (!string.IsNullOrEmpty(parentIdFilder))
|
||||
{
|
||||
request.AddQueryString("ParentId", parentIdFilder);
|
||||
}
|
||||
|
||||
request.AddQueryString("IsVirtualItem", "False");
|
||||
|
||||
AddHeaders(request, apiKey);
|
||||
|
||||
|
||||
var obj = await Api.Request<EmbyItemContainer<T>>(request);
|
||||
return obj;
|
||||
}
|
||||
|
||||
private async Task<T> GetInformation<T>(string mediaId, string apiKey, string userId, string baseUrl)
|
||||
{
|
||||
var request = new Request($"emby/users/{userId}/items/{mediaId}", baseUrl, HttpMethod.Get);
|
||||
|
|
|
@ -29,5 +29,8 @@ namespace Ombi.Api.Emby
|
|||
Task<MovieInformation> GetMovieInformation(string mediaId, string apiKey, string userId, string baseUrl);
|
||||
Task<EpisodeInformation> GetEpisodeInformation(string mediaId, string apiKey, string userId, string baseUrl);
|
||||
Task<PublicInfo> GetPublicInformation(string baseUrl);
|
||||
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<EmbySeries>> RecentlyAddedShows(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
@ -11,7 +11,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
@ -13,7 +13,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
|
|
@ -66,6 +66,8 @@ namespace Ombi.Api
|
|||
startingTag = builder.Query.Contains("?") ? "&" : "?";
|
||||
}
|
||||
|
||||
value = Uri.EscapeDataString(value);
|
||||
|
||||
builder.Query = hasQuery
|
||||
? $"{builder.Query}{startingTag}{parameter}={value}"
|
||||
: $"{startingTag}{parameter}={value}";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
@ -11,8 +11,8 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="Polly" Version="7.1.0" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoFixture" Version="4.11.0" />
|
||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
|
||||
<PackageReference Include="Moq" Version="4.15.1" />
|
||||
<PackageReference Include="Moq.AutoMock" Version="3.0.0" />
|
||||
<PackageReference Include="Nunit" Version="3.12.0" />
|
||||
|
|
|
@ -130,5 +130,76 @@ namespace Ombi.Core.Tests.Rule.Search
|
|||
Assert.False(search.Approved);
|
||||
Assert.False(search.Requested);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ShouldBeFullyAvailable_NoFutureAiredEpisodes_NoRequest()
|
||||
{
|
||||
var search = new SearchTvShowViewModel()
|
||||
{
|
||||
Id = 999,
|
||||
SeasonRequests = new List<SeasonRequests>
|
||||
{
|
||||
new SeasonRequests
|
||||
{
|
||||
Episodes = new List<EpisodeRequests>
|
||||
{
|
||||
new EpisodeRequests
|
||||
{
|
||||
Available = true,
|
||||
AirDate = new System.DateTime(2020,01,01)
|
||||
},
|
||||
new EpisodeRequests
|
||||
{
|
||||
Available = true,
|
||||
AirDate = new System.DateTime(2020,01,02)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
var result = await Rule.Execute(search);
|
||||
|
||||
Assert.True(result.Success);
|
||||
Assert.That(search.FullyAvailable, Is.True);
|
||||
Assert.That(search.PartlyAvailable, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ShouldBeFullyAvailable_AndPartly_FutureAiredEpisodes_NoRequest()
|
||||
{
|
||||
var search = new SearchTvShowViewModel()
|
||||
{
|
||||
Id = 999,
|
||||
SeasonRequests = new List<SeasonRequests>
|
||||
{
|
||||
new SeasonRequests
|
||||
{
|
||||
Episodes = new List<EpisodeRequests>
|
||||
{
|
||||
new EpisodeRequests
|
||||
{
|
||||
Available = true,
|
||||
AirDate = new System.DateTime(2020,01,01)
|
||||
},
|
||||
new EpisodeRequests
|
||||
{
|
||||
Available = true,
|
||||
AirDate = new System.DateTime(2020,01,02)
|
||||
},
|
||||
new EpisodeRequests
|
||||
{
|
||||
Available = true,
|
||||
AirDate = new System.DateTime(2029,01,02)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
var result = await Rule.Execute(search);
|
||||
|
||||
Assert.True(result.Success);
|
||||
Assert.That(search.FullyAvailable, Is.True);
|
||||
Assert.That(search.PartlyAvailable, Is.True);
|
||||
}
|
||||
}
|
||||
}
|
228
src/Ombi.Core.Tests/Senders/MassEmailSenderTests.cs
Normal file
228
src/Ombi.Core.Tests/Senders/MassEmailSenderTests.cs
Normal file
|
@ -0,0 +1,228 @@
|
|||
using Microsoft.Extensions.Logging;
|
||||
using MockQueryable.Moq;
|
||||
using Moq;
|
||||
using Moq.AutoMock;
|
||||
using NUnit.Framework;
|
||||
using Ombi.Core.Authentication;
|
||||
using Ombi.Core.Models;
|
||||
using Ombi.Core.Senders;
|
||||
using Ombi.Notifications;
|
||||
using Ombi.Notifications.Models;
|
||||
using Ombi.Settings.Settings.Models.Notifications;
|
||||
using Ombi.Store.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ombi.Core.Tests.Senders
|
||||
{
|
||||
[TestFixture]
|
||||
public class MassEmailSenderTests
|
||||
{
|
||||
|
||||
private MassEmailSender _subject;
|
||||
private AutoMocker _mocker;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_mocker = new AutoMocker();
|
||||
_subject = _mocker.CreateInstance<MassEmailSender>();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task SendMassEmail_SingleUser()
|
||||
{
|
||||
var model = new MassEmailModel
|
||||
{
|
||||
Body = "Test",
|
||||
Subject = "Subject",
|
||||
Users = new List<OmbiUser>
|
||||
{
|
||||
new OmbiUser
|
||||
{
|
||||
Id = "a"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_mocker.Setup<OmbiUserManager, IQueryable<OmbiUser>>(x => x.Users).Returns(new List<OmbiUser>
|
||||
{
|
||||
new OmbiUser
|
||||
{
|
||||
Id = "a",
|
||||
Email = "Test@test.com"
|
||||
}
|
||||
}.AsQueryable().BuildMock().Object);
|
||||
|
||||
var result = await _subject.SendMassEmail(model);
|
||||
|
||||
_mocker.Verify<IEmailProvider>(x => x.SendAdHoc(It.Is<NotificationMessage>(m => m.Subject == model.Subject
|
||||
&& m.Message == model.Body
|
||||
&& m.To == "Test@test.com"), It.IsAny<EmailNotificationSettings>()), Times.Once);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task SendMassEmail_MultipleUsers()
|
||||
{
|
||||
var model = new MassEmailModel
|
||||
{
|
||||
Body = "Test",
|
||||
Subject = "Subject",
|
||||
Users = new List<OmbiUser>
|
||||
{
|
||||
new OmbiUser
|
||||
{
|
||||
Id = "a"
|
||||
},
|
||||
new OmbiUser
|
||||
{
|
||||
Id = "b"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_mocker.Setup<OmbiUserManager, IQueryable<OmbiUser>>(x => x.Users).Returns(new List<OmbiUser>
|
||||
{
|
||||
new OmbiUser
|
||||
{
|
||||
Id = "a",
|
||||
Email = "Test@test.com"
|
||||
},
|
||||
new OmbiUser
|
||||
{
|
||||
Id = "b",
|
||||
Email = "b@test.com"
|
||||
}
|
||||
}.AsQueryable().BuildMock().Object);
|
||||
|
||||
var result = await _subject.SendMassEmail(model);
|
||||
|
||||
_mocker.Verify<IEmailProvider>(x => x.SendAdHoc(It.Is<NotificationMessage>(m => m.Subject == model.Subject
|
||||
&& m.Message == model.Body
|
||||
&& m.To == "Test@test.com"), It.IsAny<EmailNotificationSettings>()), Times.Once);
|
||||
_mocker.Verify<IEmailProvider>(x => x.SendAdHoc(It.Is<NotificationMessage>(m => m.Subject == model.Subject
|
||||
&& m.Message == model.Body
|
||||
&& m.To == "b@test.com"), It.IsAny<EmailNotificationSettings>()), Times.Once);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task SendMassEmail_UserNoEmail()
|
||||
{
|
||||
var model = new MassEmailModel
|
||||
{
|
||||
Body = "Test",
|
||||
Subject = "Subject",
|
||||
Users = new List<OmbiUser>
|
||||
{
|
||||
new OmbiUser
|
||||
{
|
||||
Id = "a"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_mocker.Setup<OmbiUserManager, IQueryable<OmbiUser>>(x => x.Users).Returns(new List<OmbiUser>
|
||||
{
|
||||
new OmbiUser
|
||||
{
|
||||
Id = "a",
|
||||
}
|
||||
}.AsQueryable().BuildMock().Object);
|
||||
|
||||
var result = await _subject.SendMassEmail(model);
|
||||
_mocker.Verify<ILogger<MassEmailSender>>(
|
||||
x => x.Log(
|
||||
LogLevel.Information,
|
||||
It.IsAny<EventId>(),
|
||||
It.IsAny<It.IsAnyType>(),
|
||||
It.IsAny<Exception>(),
|
||||
It.IsAny<Func<It.IsAnyType, Exception, string>>()),
|
||||
Times.Once);
|
||||
|
||||
_mocker.Verify<IEmailProvider>(x => x.SendAdHoc(It.IsAny<NotificationMessage>(), It.IsAny<EmailNotificationSettings>()), Times.Never);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task SendMassEmail_Bcc()
|
||||
{
|
||||
var model = new MassEmailModel
|
||||
{
|
||||
Body = "Test",
|
||||
Subject = "Subject",
|
||||
Bcc = true,
|
||||
Users = new List<OmbiUser>
|
||||
{
|
||||
new OmbiUser
|
||||
{
|
||||
Id = "a"
|
||||
},
|
||||
new OmbiUser
|
||||
{
|
||||
Id = "b"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_mocker.Setup<OmbiUserManager, IQueryable<OmbiUser>>(x => x.Users).Returns(new List<OmbiUser>
|
||||
{
|
||||
new OmbiUser
|
||||
{
|
||||
Id = "a",
|
||||
Email = "Test@test.com"
|
||||
},
|
||||
new OmbiUser
|
||||
{
|
||||
Id = "b",
|
||||
Email = "b@test.com"
|
||||
}
|
||||
}.AsQueryable().BuildMock().Object);
|
||||
|
||||
var result = await _subject.SendMassEmail(model);
|
||||
|
||||
_mocker.Verify<IEmailProvider>(x => x.SendAdHoc(It.Is<NotificationMessage>(m => m.Subject == model.Subject
|
||||
&& m.Message == model.Body
|
||||
&& m.Other["bcc"] == "Test@test.com,b@test.com"), It.IsAny<EmailNotificationSettings>()), Times.Once);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task SendMassEmail_Bcc_NoEmails()
|
||||
{
|
||||
var model = new MassEmailModel
|
||||
{
|
||||
Body = "Test",
|
||||
Subject = "Subject",
|
||||
Bcc = true,
|
||||
Users = new List<OmbiUser>
|
||||
{
|
||||
new OmbiUser
|
||||
{
|
||||
Id = "a"
|
||||
},
|
||||
new OmbiUser
|
||||
{
|
||||
Id = "b"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_mocker.Setup<OmbiUserManager, IQueryable<OmbiUser>>(x => x.Users).Returns(new List<OmbiUser>
|
||||
{
|
||||
new OmbiUser
|
||||
{
|
||||
Id = "a",
|
||||
},
|
||||
new OmbiUser
|
||||
{
|
||||
Id = "b",
|
||||
}
|
||||
}.AsQueryable().BuildMock().Object);
|
||||
|
||||
var result = await _subject.SendMassEmail(model);
|
||||
|
||||
_mocker.Verify<IEmailProvider>(x => x.SendAdHoc(It.IsAny<NotificationMessage>(), It.IsAny<EmailNotificationSettings>()), Times.Never);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -78,6 +78,32 @@ namespace Ombi.Core.Engine
|
|||
return _dbTv;
|
||||
}
|
||||
|
||||
protected async Task<RequestEngineResult> CheckCanManageRequest(BaseRequest request) {
|
||||
var errorResult = new RequestEngineResult {
|
||||
Result = false,
|
||||
ErrorCode = ErrorCode.NoPermissions
|
||||
};
|
||||
var successResult = new RequestEngineResult { Result = true };
|
||||
|
||||
// Admins can always manage requests
|
||||
var isAdmin = await IsInRole(OmbiRoles.PowerUser) || await IsInRole(OmbiRoles.Admin);
|
||||
if (isAdmin) {
|
||||
return successResult;
|
||||
}
|
||||
|
||||
// Users with 'ManageOwnRequests' can only manage their own requests
|
||||
var canManageOwnRequests = await IsInRole(OmbiRoles.ManageOwnRequests);
|
||||
if (!canManageOwnRequests) {
|
||||
return errorResult;
|
||||
}
|
||||
var isRequestedBySameUser = ( await GetUser() ).Id == request.RequestedUser?.Id;
|
||||
if (isRequestedBySameUser) {
|
||||
return successResult;
|
||||
}
|
||||
|
||||
return errorResult;
|
||||
}
|
||||
|
||||
public RequestCountModel RequestCount()
|
||||
{
|
||||
var movieQuery = MovieRepository.GetAll();
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace Ombi.Core.Engine
|
|||
Task<int> GetTotal();
|
||||
Task<RequestEngineResult> MarkAvailable(int modelId);
|
||||
Task<RequestEngineResult> MarkUnavailable(int modelId);
|
||||
Task RemoveAlbumRequest(int requestId);
|
||||
Task<RequestEngineResult> RemoveAlbumRequest(int requestId);
|
||||
Task<RequestEngineResult> RequestAlbum(MusicAlbumRequestViewModel model);
|
||||
Task<IEnumerable<AlbumRequest>> SearchAlbumRequest(string search);
|
||||
Task<bool> UserHasRequest(string userId);
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Ombi.Core.Engine.Interfaces
|
|||
Task<IEnumerable<MovieRequests>> SearchMovieRequest(string search);
|
||||
Task<RequestEngineResult> RequestCollection(int collectionId, CancellationToken cancellationToken);
|
||||
|
||||
Task RemoveMovieRequest(int requestId);
|
||||
Task<RequestEngineResult> RemoveMovieRequest(int requestId);
|
||||
Task RemoveAllMovieRequests();
|
||||
Task<MovieRequests> GetRequest(int requestId);
|
||||
Task<MovieRequests> UpdateMovieRequest(MovieRequests request);
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace Ombi.Core.Engine.Interfaces
|
|||
Task<TvRequests> UpdateTvRequest(TvRequests request);
|
||||
Task<IEnumerable<ChildRequests>> GetAllChldren(int tvId);
|
||||
Task<ChildRequests> UpdateChildRequest(ChildRequests request);
|
||||
Task RemoveTvChild(int requestId);
|
||||
Task<RequestEngineResult> RemoveTvChild(int requestId);
|
||||
Task<RequestEngineResult> ApproveChildRequest(int id);
|
||||
Task<IEnumerable<TvRequests>> GetRequestsLite();
|
||||
Task UpdateQualityProfile(int requestId, int profileId);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Ombi.Api.TheMovieDb.Models;
|
||||
using Ombi.Core.Models.Search;
|
||||
using Ombi.Core.Models.Search.V2;
|
||||
|
||||
|
@ -10,6 +11,7 @@ namespace Ombi.Core
|
|||
{
|
||||
Task<SearchFullInfoTvShowViewModel> GetShowInformation(string tvdbid, CancellationToken token);
|
||||
Task<SearchFullInfoTvShowViewModel> GetShowByRequest(int requestId, CancellationToken token);
|
||||
Task<ActorCredits> GetTvByActor(int actorId, string langCode);
|
||||
Task<IEnumerable<StreamingData>> GetStreamInformation(int movieDbId, CancellationToken cancellationToken);
|
||||
Task<IEnumerable<SearchTvShowViewModel>> Popular(int currentlyLoaded, int amountToLoad, string langCustomCode = null);
|
||||
Task<IEnumerable<SearchTvShowViewModel>> Anticipated(int currentlyLoaded, int amountToLoad);
|
||||
|
|
|
@ -527,11 +527,12 @@ namespace Ombi.Core.Engine
|
|||
|
||||
request.Denied = true;
|
||||
request.DeniedReason = denyReason;
|
||||
// We are denying a request
|
||||
await NotificationHelper.Notify(request, NotificationType.RequestDeclined);
|
||||
await MovieRepository.Update(request);
|
||||
await _mediaCacheService.Purge();
|
||||
|
||||
// We are denying a request
|
||||
await NotificationHelper.Notify(request, NotificationType.RequestDeclined);
|
||||
|
||||
return new RequestEngineResult
|
||||
{
|
||||
Result = true,
|
||||
|
@ -654,11 +655,20 @@ namespace Ombi.Core.Engine
|
|||
/// </summary>
|
||||
/// <param name="requestId">The request identifier.</param>
|
||||
/// <returns></returns>
|
||||
public async Task RemoveMovieRequest(int requestId)
|
||||
public async Task<RequestEngineResult> RemoveMovieRequest(int requestId)
|
||||
{
|
||||
var request = await MovieRepository.GetAll().FirstOrDefaultAsync(x => x.Id == requestId);
|
||||
|
||||
var result = await CheckCanManageRequest(request);
|
||||
if (result.IsError)
|
||||
return result;
|
||||
|
||||
await MovieRepository.Delete(request);
|
||||
await _mediaCacheService.Purge();
|
||||
return new RequestEngineResult
|
||||
{
|
||||
Result = true,
|
||||
};
|
||||
}
|
||||
|
||||
public async Task RemoveAllMovieRequests()
|
||||
|
|
|
@ -404,10 +404,20 @@ namespace Ombi.Core.Engine
|
|||
/// </summary>
|
||||
/// <param name="requestId">The request identifier.</param>
|
||||
/// <returns></returns>
|
||||
public async Task RemoveAlbumRequest(int requestId)
|
||||
public async Task<RequestEngineResult> RemoveAlbumRequest(int requestId)
|
||||
{
|
||||
var request = await MusicRepository.GetAll().FirstOrDefaultAsync(x => x.Id == requestId);
|
||||
|
||||
var result = await CheckCanManageRequest(request);
|
||||
if (result.IsError)
|
||||
return result;
|
||||
|
||||
await MusicRepository.Delete(request);
|
||||
|
||||
return new RequestEngineResult
|
||||
{
|
||||
Result = true,
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<bool> UserHasRequest(string userId)
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace Ombi.Core.Engine
|
|||
{
|
||||
public bool Result { get; set; }
|
||||
public string Message { get; set; }
|
||||
public bool IsError => !string.IsNullOrEmpty(ErrorMessage);
|
||||
public bool IsError => ( !string.IsNullOrEmpty(ErrorMessage) || ErrorCode != null );
|
||||
public string ErrorMessage { get; set; }
|
||||
public ErrorCode? ErrorCode { get; set; }
|
||||
public int RequestId { get; set; }
|
||||
|
|
|
@ -710,7 +710,11 @@ namespace Ombi.Core.Engine
|
|||
|
||||
if (request.Approved)
|
||||
{
|
||||
await NotificationHelper.Notify(request, NotificationType.RequestApproved);
|
||||
var canNotify = await RunSpecificRule(request, SpecificRules.CanSendNotification, string.Empty);
|
||||
if (canNotify.Success)
|
||||
{
|
||||
await NotificationHelper.Notify(request, NotificationType.RequestApproved);
|
||||
}
|
||||
// Autosend
|
||||
await TvSender.Send(request);
|
||||
}
|
||||
|
@ -749,10 +753,14 @@ namespace Ombi.Core.Engine
|
|||
return request;
|
||||
}
|
||||
|
||||
public async Task RemoveTvChild(int requestId)
|
||||
public async Task<RequestEngineResult> RemoveTvChild(int requestId)
|
||||
{
|
||||
var request = await TvRepository.GetChild().FirstOrDefaultAsync(x => x.Id == requestId);
|
||||
|
||||
var result = await CheckCanManageRequest(request);
|
||||
if (result.IsError)
|
||||
return result;
|
||||
|
||||
TvRepository.Db.ChildRequests.Remove(request);
|
||||
var all = TvRepository.Db.TvRequests.Include(x => x.ChildRequests);
|
||||
var parent = all.FirstOrDefault(x => x.Id == request.ParentRequestId);
|
||||
|
@ -766,6 +774,11 @@ namespace Ombi.Core.Engine
|
|||
|
||||
await TvRepository.Db.SaveChangesAsync();
|
||||
await _mediaCacheService.Purge();
|
||||
|
||||
return new RequestEngineResult
|
||||
{
|
||||
Result = true,
|
||||
};
|
||||
}
|
||||
|
||||
public async Task RemoveTvRequest(int requestId)
|
||||
|
@ -948,7 +961,11 @@ namespace Ombi.Core.Engine
|
|||
if (model.Approved)
|
||||
{
|
||||
// Autosend
|
||||
await NotificationHelper.Notify(model, NotificationType.RequestApproved);
|
||||
var canNotify = await RunSpecificRule(model, SpecificRules.CanSendNotification, string.Empty);
|
||||
if (canNotify.Success)
|
||||
{
|
||||
await NotificationHelper.Notify(model, NotificationType.RequestApproved);
|
||||
}
|
||||
var result = await TvSender.Send(model);
|
||||
if (result.Success)
|
||||
{
|
||||
|
|
|
@ -323,6 +323,7 @@ namespace Ombi.Core.Engine.V2
|
|||
|
||||
public async Task<ActorCredits> GetMoviesByActor(int actorId, string langCode)
|
||||
{
|
||||
langCode = await DefaultLanguageCode(langCode);
|
||||
var result = await Cache.GetOrAddAsync(nameof(GetMoviesByActor) + actorId + langCode,
|
||||
() => MovieApi.GetActorMovieCredits(actorId, langCode), DateTimeOffset.Now.AddHours(12));
|
||||
// Later we run this through the rules engine
|
||||
|
|
|
@ -89,7 +89,7 @@ namespace Ombi.Core.Engine.V2
|
|||
|
||||
foreach (var tvSeason in show.seasons.Where(x => x.season_number != 0)) // skip the first season
|
||||
{
|
||||
var seasonEpisodes = (await _movieApi.GetSeasonEpisodes(show.id, tvSeason.season_number, token));
|
||||
var seasonEpisodes = (await _movieApi.GetSeasonEpisodes(show.id, tvSeason.season_number, token, langCode));
|
||||
|
||||
MapSeasons(mapped.SeasonRequests, tvSeason, seasonEpisodes);
|
||||
}
|
||||
|
@ -147,6 +147,13 @@ namespace Ombi.Core.Engine.V2
|
|||
return await processed;
|
||||
}
|
||||
|
||||
public async Task<ActorCredits> GetTvByActor(int actorId, string langCode)
|
||||
{
|
||||
langCode = await DefaultLanguageCode(langCode);
|
||||
var result = await Cache.GetOrAddAsync(nameof(GetTvByActor) + actorId + langCode,
|
||||
() => _movieApi.GetActorTvCredits(actorId, langCode), DateTimeOffset.Now.AddHours(12));
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<StreamingData>> GetStreamInformation(int movieDbId, CancellationToken cancellationToken)
|
||||
{
|
||||
|
|
|
@ -35,6 +35,8 @@ namespace Ombi.Core.Models
|
|||
public string Subject { get; set; }
|
||||
public string Body { get; set; }
|
||||
|
||||
public bool Bcc { get; set; }
|
||||
|
||||
public List<OmbiUser> Users { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
@ -13,8 +13,8 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper" Version="10.0.0" />
|
||||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.0" />
|
||||
<PackageReference Include="MusicBrainzAPI" Version="2.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="System.Diagnostics.Process" Version="4.3.0" />
|
||||
|
|
|
@ -85,11 +85,18 @@ namespace Ombi.Core.Rule.Rules.Search
|
|||
{
|
||||
request.FullyAvailable = true;
|
||||
}
|
||||
if (request.SeasonRequests.Any() && request.SeasonRequests.All(x => x.Episodes.Any(e => e.Available && e.AirDate > DateTime.MinValue)))
|
||||
if (request.SeasonRequests.Any() && request.SeasonRequests.All(x => x.Episodes.Any(e => e.Available && e.AirDate > DateTime.MinValue && e.AirDate <= DateTime.UtcNow)))
|
||||
{
|
||||
request.PartlyAvailable = true;
|
||||
}
|
||||
|
||||
var hasUnairedRequests = request.SeasonRequests.Any() && request.SeasonRequests.All(x => x.Episodes.Any(e => e.AirDate >= DateTime.UtcNow));
|
||||
|
||||
if (request.FullyAvailable)
|
||||
{
|
||||
request.PartlyAvailable = hasUnairedRequests;
|
||||
}
|
||||
|
||||
return Success();
|
||||
}
|
||||
if (obj.Type == RequestType.Album)
|
||||
|
|
|
@ -25,7 +25,9 @@
|
|||
// ************************************************************************/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
@ -64,6 +66,63 @@ namespace Ombi.Core.Senders
|
|||
var customization = await _customizationService.GetSettingsAsync();
|
||||
var email = await _emailService.GetSettingsAsync();
|
||||
var messagesSent = new List<Task>();
|
||||
if (model.Bcc)
|
||||
{
|
||||
await SendBccMails(model, customization, email, messagesSent);
|
||||
}
|
||||
else
|
||||
{
|
||||
await SendIndividualEmails(model, customization, email, messagesSent);
|
||||
}
|
||||
|
||||
await Task.WhenAll(messagesSent);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task SendBccMails(MassEmailModel model, CustomizationSettings customization, EmailNotificationSettings email, List<Task> messagesSent)
|
||||
{
|
||||
var resolver = new NotificationMessageResolver();
|
||||
var curlys = new NotificationMessageCurlys();
|
||||
|
||||
var validUsers = new List<OmbiUser>();
|
||||
foreach (var user in model.Users)
|
||||
{
|
||||
var fullUser = await _userManager.Users.FirstOrDefaultAsync(x => x.Id == user.Id);
|
||||
if (!fullUser.Email.HasValue())
|
||||
{
|
||||
_log.LogInformation("User {0} has no email, cannot send mass email to this user", fullUser.UserName);
|
||||
continue;
|
||||
}
|
||||
|
||||
validUsers.Add(fullUser);
|
||||
}
|
||||
|
||||
if (!validUsers.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var firstUser = validUsers.FirstOrDefault();
|
||||
|
||||
var bccAddress = string.Join(',', validUsers.Select(x => x.Email));
|
||||
curlys.Setup(firstUser, customization);
|
||||
var template = new NotificationTemplates() { Message = model.Body, Subject = model.Subject };
|
||||
var content = resolver.ParseMessage(template, curlys);
|
||||
var msg = new NotificationMessage
|
||||
{
|
||||
Message = content.Message,
|
||||
Subject = content.Subject,
|
||||
Other = new Dictionary<string, string> { { "bcc", bccAddress } }
|
||||
};
|
||||
|
||||
messagesSent.Add(_email.SendAdHoc(msg, email));
|
||||
}
|
||||
|
||||
private async Task SendIndividualEmails(MassEmailModel model, CustomizationSettings customization, EmailNotificationSettings email, List<Task> messagesSent)
|
||||
{
|
||||
var resolver = new NotificationMessageResolver();
|
||||
var curlys = new NotificationMessageCurlys();
|
||||
foreach (var user in model.Users)
|
||||
{
|
||||
var fullUser = await _userManager.Users.FirstOrDefaultAsync(x => x.Id == user.Id);
|
||||
|
@ -72,8 +131,6 @@ namespace Ombi.Core.Senders
|
|||
_log.LogInformation("User {0} has no email, cannot send mass email to this user", fullUser.UserName);
|
||||
continue;
|
||||
}
|
||||
var resolver = new NotificationMessageResolver();
|
||||
var curlys = new NotificationMessageCurlys();
|
||||
curlys.Setup(fullUser, customization);
|
||||
var template = new NotificationTemplates() { Message = model.Body, Subject = model.Subject };
|
||||
var content = resolver.ParseMessage(template, curlys);
|
||||
|
@ -83,13 +140,19 @@ namespace Ombi.Core.Senders
|
|||
To = fullUser.Email,
|
||||
Subject = content.Subject
|
||||
};
|
||||
messagesSent.Add(_email.SendAdHoc(msg, email));
|
||||
messagesSent.Add(DelayEmail(msg, email));
|
||||
_log.LogInformation("Sent mass email to user {0} @ {1}", fullUser.UserName, fullUser.Email);
|
||||
}
|
||||
}
|
||||
|
||||
await Task.WhenAll(messagesSent);
|
||||
|
||||
return true;
|
||||
/// <summary>
|
||||
/// This will add a 2 second delay, this is to help with concurrent connection limits
|
||||
/// <see href="https://github.com/Ombi-app/Ombi/issues/4377"/>
|
||||
/// </summary>
|
||||
private async Task DelayEmail(NotificationMessage msg, EmailNotificationSettings email)
|
||||
{
|
||||
await Task.Delay(2000);
|
||||
await _email.SendAdHoc(msg, email);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -309,6 +309,22 @@ namespace Ombi.Core.Senders
|
|||
|
||||
private async Task SendToSonarr(ChildRequests model, SonarrSeries result, SonarrSettings s)
|
||||
{
|
||||
// Check to ensure we have the all the seasons, ensure the Sonarr metadata has grabbed all the data
|
||||
Season existingSeason = null;
|
||||
foreach (var season in model.SeasonRequests)
|
||||
{
|
||||
var attempt = 0;
|
||||
existingSeason = result.seasons.FirstOrDefault(x => x.seasonNumber == season.SeasonNumber);
|
||||
while (existingSeason == null && attempt < 5)
|
||||
{
|
||||
attempt++;
|
||||
Logger.LogInformation("There was no season numer {0} in Sonarr for title {1}. Will try again as the metadata did not get created", season.SeasonNumber, model.ParentRequest.Title);
|
||||
result = await SonarrApi.GetSeriesById(result.id, s.ApiKey, s.FullUri);
|
||||
existingSeason = result.seasons.FirstOrDefault(x => x.seasonNumber == season.SeasonNumber);
|
||||
await Task.Delay(500);
|
||||
}
|
||||
}
|
||||
|
||||
var episodesToUpdate = new List<Episode>();
|
||||
// Ok, now let's sort out the episodes.
|
||||
|
||||
|
@ -327,24 +343,20 @@ namespace Ombi.Core.Senders
|
|||
await Task.Delay(500);
|
||||
}
|
||||
|
||||
var seriesChanges = false;
|
||||
|
||||
foreach (var req in model.SeasonRequests)
|
||||
foreach (var season in model.SeasonRequests)
|
||||
{
|
||||
foreach (var ep in req.Episodes)
|
||||
foreach (var ep in season.Episodes)
|
||||
{
|
||||
var sonarrEp = sonarrEpList.FirstOrDefault(x =>
|
||||
x.episodeNumber == ep.EpisodeNumber && x.seasonNumber == req.SeasonNumber);
|
||||
x.episodeNumber == ep.EpisodeNumber && x.seasonNumber == season.SeasonNumber);
|
||||
if (sonarrEp != null && !sonarrEp.monitored)
|
||||
{
|
||||
sonarrEp.monitored = true;
|
||||
episodesToUpdate.Add(sonarrEp);
|
||||
}
|
||||
}
|
||||
}
|
||||
var seriesChanges = false;
|
||||
|
||||
foreach (var season in model.SeasonRequests)
|
||||
{
|
||||
var sonarrEpisodeList = sonarrEpList.Where(x => x.seasonNumber == season.SeasonNumber).ToList();
|
||||
var sonarrEpCount = sonarrEpisodeList.Count;
|
||||
var ourRequestCount = season.Episodes.Count;
|
||||
|
@ -356,15 +368,7 @@ namespace Ombi.Core.Senders
|
|||
//// NOTE, not sure if needed since ombi ui displays future episodes anyway...
|
||||
//ourEpisodes.AddRange(unairedEpisodes);
|
||||
//var distinctEpisodes = ourEpisodes.Distinct().ToList();
|
||||
//var missingEpisodes = Enumerable.Range(distinctEpisodes.Min(), distinctEpisodes.Count).Except(distinctEpisodes);
|
||||
|
||||
var existingSeason =
|
||||
result.seasons.FirstOrDefault(x => x.seasonNumber == season.SeasonNumber);
|
||||
if (existingSeason == null)
|
||||
{
|
||||
Logger.LogError("There was no season numer {0} in Sonarr for title {1}", season.SeasonNumber, model.ParentRequest.Title);
|
||||
continue;
|
||||
}
|
||||
//var missingEpisodes = Enumerable.Range(distinctEpisodes.Min(), distinctEpisodes.Count).Except(distinctEpisodes);
|
||||
|
||||
|
||||
if (sonarrEpCount == ourRequestCount /*|| !missingEpisodes.Any()*/)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
@ -11,10 +11,10 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="nunit" Version="3.11.0" />
|
||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
public class JobDataKeys
|
||||
{
|
||||
public const string RecentlyAddedSearch = "recentlyAddedSearch";
|
||||
public const string EmbyRecentlyAddedSearch = nameof(EmbyRecentlyAddedSearch);
|
||||
public const string NotificationOptions = nameof(NotificationOptions);
|
||||
}
|
||||
}
|
|
@ -6,16 +6,6 @@ namespace Ombi.Helpers
|
|||
{
|
||||
public static class LinqHelpers
|
||||
{
|
||||
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
|
||||
{
|
||||
HashSet<TKey> knownKeys = new HashSet<TKey>();
|
||||
foreach (TSource source1 in source)
|
||||
{
|
||||
if (knownKeys.Add(keySelector(source1)))
|
||||
yield return source1;
|
||||
}
|
||||
}
|
||||
|
||||
public static HashSet<T> ToHashSet<T>(
|
||||
this IEnumerable<T> source,
|
||||
IEqualityComparer<T> comparer = null)
|
||||
|
|
|
@ -53,17 +53,18 @@ namespace Ombi.Helpers
|
|||
_memoryCache.Set(CacheKey, mediaServiceCache);
|
||||
}
|
||||
|
||||
public async Task Purge()
|
||||
public Task Purge()
|
||||
{
|
||||
var keys = _memoryCache.Get<List<string>>(CacheKey);
|
||||
if (keys == null)
|
||||
{
|
||||
return;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
foreach (var key in keys)
|
||||
{
|
||||
base.Remove(key);
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
18
src/Ombi.Helpers/NotificationSubstitues.cs
Normal file
18
src/Ombi.Helpers/NotificationSubstitues.cs
Normal file
|
@ -0,0 +1,18 @@
|
|||
namespace Ombi.Helpers
|
||||
{
|
||||
public static class NotificationSubstitues
|
||||
{
|
||||
public const string Title = nameof(Title);
|
||||
public const string IssueDescription = nameof(IssueDescription);
|
||||
public const string IssueCategory = nameof(IssueCategory);
|
||||
public const string IssueStatus = nameof(IssueStatus);
|
||||
public const string IssueSubject = nameof(IssueSubject);
|
||||
public const string IssueUser = nameof(IssueUser);
|
||||
public const string IssueUserAlias = nameof(IssueUserAlias);
|
||||
public const string RequestType = nameof(RequestType);
|
||||
public const string PosterPath = nameof(PosterPath);
|
||||
public const string NewIssueComment = nameof(NewIssueComment);
|
||||
public const string IssueId = nameof(IssueId);
|
||||
public const string AdminComment = nameof(AdminComment);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
@ -13,8 +13,8 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="EasyCrypto" Version="3.3.2" />
|
||||
<PackageReference Include="LazyCache.AspNetCore" Version="2.1.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="Nito.AsyncEx" Version="5.1.0" />
|
||||
<PackageReference Include="Quartz" Version="3.1.0" />
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace Ombi.Notifications.Templates
|
|||
if (string.IsNullOrEmpty(_templateLocation))
|
||||
{
|
||||
#if DEBUG
|
||||
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "net5.0", "Templates",
|
||||
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "net6.0", "Templates",
|
||||
"BasicTemplate.html");
|
||||
#else
|
||||
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "Templates","BasicTemplate.html");
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace Ombi.Notifications.Templates
|
|||
if (string.IsNullOrEmpty(_templateLocation))
|
||||
{
|
||||
#if DEBUG
|
||||
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "net5.0", "Templates", "NewsletterTemplate.html");
|
||||
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "net6.0", "Templates", "NewsletterTemplate.html");
|
||||
#else
|
||||
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "Templates", "NewsletterTemplate.html");
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
|
|
@ -76,6 +76,7 @@ namespace Ombi.Notifications.Tests
|
|||
{ "IssueUser", "User" },
|
||||
{ "IssueUserAlias", "alias" },
|
||||
{ "RequestType", "Movie" },
|
||||
{ "PosterPath", "aaaaa" }
|
||||
}
|
||||
};
|
||||
var req = F.Build<MovieRequests>()
|
||||
|
@ -94,6 +95,39 @@ namespace Ombi.Notifications.Tests
|
|||
Assert.That("Movie", Is.EqualTo(sut.Type));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IssueNotificationTests_NoRequest()
|
||||
{
|
||||
var notificationOptions = new NotificationOptions
|
||||
{
|
||||
Substitutes = new Dictionary<string, string>
|
||||
{
|
||||
{ "IssueDescription", "Desc" },
|
||||
{ "IssueCategory", "Cat" },
|
||||
{ "IssueStatus", "state" },
|
||||
{ "IssueSubject", "sub" },
|
||||
{ "NewIssueComment", "a" },
|
||||
{ "IssueUser", "User" },
|
||||
{ "IssueUserAlias", "alias" },
|
||||
{ "RequestType", "Movie" },
|
||||
{ "PosterPath", "aaaaa" }
|
||||
}
|
||||
};
|
||||
|
||||
var customization = new CustomizationSettings();
|
||||
var userPrefs = new UserNotificationPreferences();
|
||||
sut.Setup(notificationOptions, (MovieRequests)null, customization, userPrefs);
|
||||
|
||||
Assert.That("Desc", Is.EqualTo(sut.IssueDescription));
|
||||
Assert.That("Cat", Is.EqualTo(sut.IssueCategory));
|
||||
Assert.That("state", Is.EqualTo(sut.IssueStatus));
|
||||
Assert.That("a", Is.EqualTo(sut.NewIssueComment));
|
||||
Assert.That("User", Is.EqualTo(sut.UserName));
|
||||
Assert.That("alias", Is.EqualTo(sut.Alias));
|
||||
Assert.That("Movie", Is.EqualTo(sut.Type));
|
||||
Assert.That("https://image.tmdb.org/t/p/w300/aaaaa", Is.EqualTo(sut.PosterImage));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MovieNotificationUserPreferences()
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
|||
<PackageReference Include="Nunit" Version="3.11.0" />
|
||||
<PackageReference Include="NUnit.ConsoleRunner" Version="3.9.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
|
||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
|
||||
<packagereference Include="Microsoft.NET.Test.Sdk" Version="16.8.0"></packagereference>
|
||||
<PackageReference Include="Moq" Version="4.10.0" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Ombi.Api.Discord;
|
||||
using Ombi.Api.Discord.Models;
|
||||
|
@ -21,8 +22,8 @@ namespace Ombi.Notifications.Agents
|
|||
public DiscordNotification(IDiscordApi api, ISettingsService<DiscordNotificationSettings> sn,
|
||||
ILogger<DiscordNotification> log, INotificationTemplatesRepository r,
|
||||
IMovieRequestRepository m, ITvRequestRepository t, ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub, IMusicRequestRepository music,
|
||||
IRepository<UserNotificationPreferences> userPref)
|
||||
: base(sn, r, m, t, s, log, sub, music, userPref)
|
||||
IRepository<UserNotificationPreferences> userPref, UserManager<OmbiUser> um)
|
||||
: base(sn, r, m, t, s, log, sub, music, userPref, um)
|
||||
{
|
||||
Api = api;
|
||||
Logger = log;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using MailKit.Net.Smtp;
|
||||
|
@ -22,7 +23,7 @@ namespace Ombi.Notifications.Agents
|
|||
{
|
||||
public EmailNotification(ISettingsService<EmailNotificationSettings> settings, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, IEmailProvider prov, ISettingsService<CustomizationSettings> c,
|
||||
ILogger<EmailNotification> log, UserManager<OmbiUser> um, IRepository<RequestSubscription> sub, IMusicRequestRepository music,
|
||||
IRepository<UserNotificationPreferences> userPref) : base(settings, r, m, t, c, log, sub, music, userPref)
|
||||
IRepository<UserNotificationPreferences> userPref) : base(settings, r, m, t, c, log, sub, music, userPref, um)
|
||||
{
|
||||
EmailProvider = prov;
|
||||
Logger = log;
|
||||
|
@ -114,7 +115,15 @@ namespace Ombi.Notifications.Agents
|
|||
var plaintext = await LoadPlainTextMessage(NotificationType.NewRequest, model, settings);
|
||||
message.Other.Add("PlainTextBody", plaintext);
|
||||
|
||||
await Send(message, settings);
|
||||
foreach (var recipient in (await GetPrivilegedUsers()).DistinctBy(x => x.Email))
|
||||
{
|
||||
if (recipient.Email.IsNullOrEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
message.To = recipient.Email;
|
||||
await Send(message, settings);
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task NewIssue(NotificationOptions model, EmailNotificationSettings settings)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Ombi.Api.Gotify;
|
||||
using Ombi.Core.Settings;
|
||||
|
@ -17,7 +18,7 @@ namespace Ombi.Notifications.Agents
|
|||
{
|
||||
public GotifyNotification(IGotifyApi api, ISettingsService<GotifySettings> sn, ILogger<GotifyNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
|
||||
ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub, IMusicRequestRepository music,
|
||||
IRepository<UserNotificationPreferences> userPref) : base(sn, r, m, t, s, log, sub, music, userPref)
|
||||
IRepository<UserNotificationPreferences> userPref, UserManager<OmbiUser> um) : base(sn, r, m, t, s, log, sub, music, userPref, um)
|
||||
{
|
||||
Api = api;
|
||||
Logger = log;
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace Ombi.Notifications.Agents
|
|||
public LegacyMobileNotification(IOneSignalApi api, ISettingsService<MobileNotificationSettings> sn, ILogger<LegacyMobileNotification> log, INotificationTemplatesRepository r,
|
||||
IMovieRequestRepository m, ITvRequestRepository t, ISettingsService<CustomizationSettings> s, IRepository<NotificationUserId> notification,
|
||||
UserManager<OmbiUser> um, IRepository<RequestSubscription> sub, IMusicRequestRepository music, IRepository<Issues> issueRepository,
|
||||
IRepository<UserNotificationPreferences> userPref) : base(sn, r, m, t, s, log, sub, music, userPref)
|
||||
IRepository<UserNotificationPreferences> userPref) : base(sn, r, m, t, s, log, sub, music, userPref, um)
|
||||
{
|
||||
_api = api;
|
||||
_logger = log;
|
||||
|
@ -59,7 +59,7 @@ namespace Ombi.Notifications.Agents
|
|||
};
|
||||
|
||||
// Get admin devices
|
||||
var playerIds = await GetAdmins(NotificationType.NewRequest);
|
||||
var playerIds = await GetPrivilegedUsersPlayerIds();
|
||||
await Send(playerIds, notification, settings, model, true);
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ namespace Ombi.Notifications.Agents
|
|||
};
|
||||
|
||||
// Get admin devices
|
||||
var playerIds = await GetAdmins(NotificationType.Issue);
|
||||
var playerIds = await GetAdmins();
|
||||
await Send(playerIds, notification, settings, model);
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ namespace Ombi.Notifications.Agents
|
|||
else
|
||||
{
|
||||
// Send to admin
|
||||
var playerIds = await GetAdmins(NotificationType.IssueComment);
|
||||
var playerIds = await GetAdmins();
|
||||
await Send(playerIds, notification, settings, model);
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ namespace Ombi.Notifications.Agents
|
|||
};
|
||||
|
||||
// Get admin devices
|
||||
var playerIds = await GetAdmins(NotificationType.Test);
|
||||
var playerIds = await GetAdmins();
|
||||
await Send(playerIds, notification, settings, model);
|
||||
}
|
||||
|
||||
|
@ -241,15 +241,25 @@ namespace Ombi.Notifications.Agents
|
|||
await Send(playerIds, notification, settings, model);
|
||||
}
|
||||
|
||||
private async Task<List<string>> GetAdmins(NotificationType type)
|
||||
private async Task<List<string>> GetAdmins()
|
||||
{
|
||||
var adminUsers = (await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin)).Select(x => x.Id).ToList();
|
||||
return await GetNotificationRecipients(await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin));
|
||||
}
|
||||
private async Task<List<string>> GetPrivilegedUsersPlayerIds()
|
||||
{
|
||||
return await GetNotificationRecipients(await GetPrivilegedUsers());
|
||||
}
|
||||
|
||||
private async Task<List<string>> GetNotificationRecipients(IEnumerable<OmbiUser> users)
|
||||
{
|
||||
|
||||
var adminUsers = users.Select(x => x.Id).ToList();
|
||||
var notificationUsers = _notifications.GetAll().Include(x => x.User).Where(x => adminUsers.Contains(x.UserId));
|
||||
var playerIds = await notificationUsers.Select(x => x.PlayerId).ToListAsync();
|
||||
if (!playerIds.Any())
|
||||
{
|
||||
_logger.LogInformation(
|
||||
$"there are no admins to send a notification for {type}, for agent {NotificationAgent.Mobile}");
|
||||
$"there are no users to send a notification for agent {NotificationAgent.Mobile}");
|
||||
return null;
|
||||
}
|
||||
return playerIds;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Ombi.Api.Mattermost;
|
||||
using Ombi.Api.Mattermost.Models;
|
||||
|
@ -19,7 +20,7 @@ namespace Ombi.Notifications.Agents
|
|||
{
|
||||
public MattermostNotification(IMattermostApi api, ISettingsService<MattermostNotificationSettings> sn, ILogger<MattermostNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
|
||||
ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub, IMusicRequestRepository music,
|
||||
IRepository<UserNotificationPreferences> userPref) : base(sn, r, m, t, s, log, sub, music, userPref)
|
||||
IRepository<UserNotificationPreferences> userPref, UserManager<OmbiUser> um) : base(sn, r, m, t, s, log, sub, music, userPref, um)
|
||||
{
|
||||
Api = api;
|
||||
Logger = log;
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace Ombi.Notifications.Agents
|
|||
public MobileNotification(ICloudMobileNotification api, ISettingsService<MobileNotificationSettings> sn, ILogger<MobileNotification> log, INotificationTemplatesRepository r,
|
||||
IMovieRequestRepository m, ITvRequestRepository t, ISettingsService<CustomizationSettings> s, IRepository<MobileDevices> notification,
|
||||
UserManager<OmbiUser> um, IRepository<RequestSubscription> sub, IMusicRequestRepository music, IRepository<Issues> issueRepository,
|
||||
IRepository<UserNotificationPreferences> userPref) : base(sn, r, m, t, s, log, sub, music, userPref)
|
||||
IRepository<UserNotificationPreferences> userPref) : base(sn, r, m, t, s, log, sub, music, userPref, um)
|
||||
{
|
||||
_api = api;
|
||||
_logger = log;
|
||||
|
@ -62,7 +62,7 @@ namespace Ombi.Notifications.Agents
|
|||
};
|
||||
|
||||
// Get admin devices
|
||||
var playerIds = await GetAdmins(NotificationType.NewRequest);
|
||||
var playerIds = await GetPrivilegedUsersPlayerIds();
|
||||
await Send(playerIds, notification, settings, model, true);
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ namespace Ombi.Notifications.Agents
|
|||
};
|
||||
|
||||
// Get admin devices
|
||||
var playerIds = await GetAdmins(NotificationType.Issue);
|
||||
var playerIds = await GetAdmins();
|
||||
await Send(playerIds, notification, settings, model);
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@ namespace Ombi.Notifications.Agents
|
|||
else
|
||||
{
|
||||
// Send to admin
|
||||
var playerIds = await GetAdmins(NotificationType.IssueComment);
|
||||
var playerIds = await GetAdmins();
|
||||
await Send(playerIds, notification, settings, model);
|
||||
}
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ namespace Ombi.Notifications.Agents
|
|||
};
|
||||
|
||||
// Get admin devices
|
||||
var playerIds = await GetAdmins(NotificationType.Test);
|
||||
var playerIds = await GetAdmins();
|
||||
await Send(playerIds, notification, settings, model);
|
||||
}
|
||||
|
||||
|
@ -279,15 +279,25 @@ namespace Ombi.Notifications.Agents
|
|||
await Send(playerIds, notification, settings, model);
|
||||
}
|
||||
|
||||
private async Task<List<string>> GetAdmins(NotificationType type)
|
||||
private async Task<List<string>> GetAdmins()
|
||||
{
|
||||
var adminUsers = (await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin)).Select(x => x.Id).ToList();
|
||||
return await GetNotificationRecipients(await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin));
|
||||
}
|
||||
private async Task<List<string>> GetPrivilegedUsersPlayerIds()
|
||||
{
|
||||
return await GetNotificationRecipients(await GetPrivilegedUsers());
|
||||
}
|
||||
|
||||
private async Task<List<string>> GetNotificationRecipients(IEnumerable<OmbiUser> users)
|
||||
{
|
||||
|
||||
var adminUsers = users.Select(x => x.Id).ToList();
|
||||
var notificationUsers = _notifications.GetAll().Include(x => x.User).Where(x => adminUsers.Contains(x.UserId));
|
||||
var playerIds = await notificationUsers.Select(x => x.Token).ToListAsync();
|
||||
if (!playerIds.Any())
|
||||
{
|
||||
_logger.LogInformation(
|
||||
$"there are no admins to send a notification for {type}, for agent {NotificationAgent.Mobile}");
|
||||
$"there are no users to send a notification for agent {NotificationAgent.Mobile}");
|
||||
return null;
|
||||
}
|
||||
return playerIds;
|
||||
|
@ -377,7 +387,7 @@ namespace Ombi.Notifications.Agents
|
|||
};
|
||||
|
||||
// Get admin devices
|
||||
var playerIds = await GetAdmins(NotificationType.PartiallyAvailable);
|
||||
var playerIds = await GetAdmins();
|
||||
await Send(playerIds, notification, settings, model, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Ombi.Api.Pushbullet;
|
||||
using Ombi.Core.Settings;
|
||||
|
@ -17,7 +18,7 @@ namespace Ombi.Notifications.Agents
|
|||
{
|
||||
public PushbulletNotification(IPushbulletApi api, ISettingsService<PushbulletSettings> sn, ILogger<PushbulletNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
|
||||
ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub, IMusicRequestRepository music,
|
||||
IRepository<UserNotificationPreferences> userPref) : base(sn, r, m, t, s, log, sub, music, userPref)
|
||||
IRepository<UserNotificationPreferences> userPref, UserManager<OmbiUser> um) : base(sn, r, m, t, s, log, sub, music, userPref, um)
|
||||
{
|
||||
Api = api;
|
||||
Logger = log;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Ombi.Api.Pushbullet;
|
||||
using Ombi.Api.Pushover;
|
||||
|
@ -18,7 +19,7 @@ namespace Ombi.Notifications.Agents
|
|||
{
|
||||
public PushoverNotification(IPushoverApi api, ISettingsService<PushoverSettings> sn, ILogger<PushoverNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
|
||||
ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub, IMusicRequestRepository music,
|
||||
IRepository<UserNotificationPreferences> userPref) : base(sn, r, m, t, s, log, sub, music, userPref)
|
||||
IRepository<UserNotificationPreferences> userPref, UserManager<OmbiUser> um) : base(sn, r, m, t, s, log, sub, music, userPref, um)
|
||||
{
|
||||
Api = api;
|
||||
Logger = log;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Ombi.Api.Slack;
|
||||
using Ombi.Api.Slack.Models;
|
||||
|
@ -18,7 +19,7 @@ namespace Ombi.Notifications.Agents
|
|||
{
|
||||
public SlackNotification(ISlackApi api, ISettingsService<SlackNotificationSettings> sn, ILogger<SlackNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
|
||||
ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub, IMusicRequestRepository music,
|
||||
IRepository<UserNotificationPreferences> userPref) : base(sn, r, m, t, s, log, sub, music, userPref)
|
||||
IRepository<UserNotificationPreferences> userPref, UserManager<OmbiUser> um) : base(sn, r, m, t, s, log, sub, music, userPref, um)
|
||||
{
|
||||
Api = api;
|
||||
Logger = log;
|
||||
|
|
|
@ -10,6 +10,7 @@ using Ombi.Store.Entities;
|
|||
using Ombi.Store.Repository;
|
||||
using Ombi.Store.Repository.Requests;
|
||||
using Ombi.Api.Telegram;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
|
||||
namespace Ombi.Notifications.Agents
|
||||
{
|
||||
|
@ -19,7 +20,7 @@ namespace Ombi.Notifications.Agents
|
|||
INotificationTemplatesRepository r, IMovieRequestRepository m,
|
||||
ITvRequestRepository t, ISettingsService<CustomizationSettings> s
|
||||
, IRepository<RequestSubscription> sub, IMusicRequestRepository music,
|
||||
IRepository<UserNotificationPreferences> userPref) : base(sn, r, m, t,s,log, sub, music, userPref)
|
||||
IRepository<UserNotificationPreferences> userPref, UserManager<OmbiUser> um) : base(sn, r, m, t,s,log, sub, music, userPref, um)
|
||||
{
|
||||
Api = api;
|
||||
Logger = log;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Ombi.Api.Webhook;
|
||||
using Ombi.Core.Settings;
|
||||
|
@ -18,7 +19,7 @@ namespace Ombi.Notifications.Agents
|
|||
{
|
||||
public WebhookNotification(IWebhookApi api, ISettingsService<WebhookSettings> sn, ILogger<WebhookNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
|
||||
ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub, IMusicRequestRepository music,
|
||||
IRepository<UserNotificationPreferences> userPref) : base(sn, r, m, t, s, log, sub, music, userPref)
|
||||
IRepository<UserNotificationPreferences> userPref, UserManager<OmbiUser> um) : base(sn, r, m, t, s, log, sub, music, userPref, um)
|
||||
{
|
||||
Api = api;
|
||||
Logger = log;
|
||||
|
|
|
@ -10,6 +10,7 @@ using Ombi.Store.Entities;
|
|||
using Ombi.Store.Repository;
|
||||
using Ombi.Store.Repository.Requests;
|
||||
using Ombi.Api.Twilio;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
|
||||
namespace Ombi.Notifications.Agents
|
||||
{
|
||||
|
@ -19,7 +20,7 @@ namespace Ombi.Notifications.Agents
|
|||
INotificationTemplatesRepository r, IMovieRequestRepository m,
|
||||
ITvRequestRepository t, ISettingsService<CustomizationSettings> s
|
||||
, IRepository<RequestSubscription> sub, IMusicRequestRepository music,
|
||||
IRepository<UserNotificationPreferences> userPref) : base(sn, r, m, t,s,log, sub, music, userPref)
|
||||
IRepository<UserNotificationPreferences> userPref, UserManager<OmbiUser> um) : base(sn, r, m, t,s,log, sub, music, userPref, um)
|
||||
{
|
||||
Api = api;
|
||||
Logger = log;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Ombi.Core.Settings;
|
||||
|
@ -19,7 +21,7 @@ namespace Ombi.Notifications
|
|||
{
|
||||
protected BaseNotification(ISettingsService<T> settings, INotificationTemplatesRepository templateRepo, IMovieRequestRepository movie, ITvRequestRepository tv,
|
||||
ISettingsService<CustomizationSettings> customization, ILogger<BaseNotification<T>> log, IRepository<RequestSubscription> sub, IMusicRequestRepository album,
|
||||
IRepository<UserNotificationPreferences> notificationUserPreferences)
|
||||
IRepository<UserNotificationPreferences> notificationUserPreferences, UserManager<OmbiUser> um)
|
||||
{
|
||||
Settings = settings;
|
||||
TemplateRepository = templateRepo;
|
||||
|
@ -30,6 +32,7 @@ namespace Ombi.Notifications
|
|||
_log = log;
|
||||
AlbumRepository = album;
|
||||
UserNotificationPreferences = notificationUserPreferences;
|
||||
_userManager = um;
|
||||
Settings.ClearCache();
|
||||
}
|
||||
|
||||
|
@ -43,6 +46,7 @@ namespace Ombi.Notifications
|
|||
protected IRepository<UserNotificationPreferences> UserNotificationPreferences { get; set; }
|
||||
private ISettingsService<CustomizationSettings> CustomizationSettings { get; }
|
||||
private readonly ILogger<BaseNotification<T>> _log;
|
||||
private readonly UserManager<OmbiUser> _userManager;
|
||||
|
||||
|
||||
protected ChildRequests TvRequest { get; set; }
|
||||
|
@ -210,6 +214,13 @@ namespace Ombi.Notifications
|
|||
.FirstOrDefault(x => x.Agent == agent && x.UserId == userId);
|
||||
}
|
||||
|
||||
protected async Task<IEnumerable<OmbiUser>> GetPrivilegedUsers()
|
||||
{
|
||||
IEnumerable<OmbiUser> recipients = await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin);
|
||||
recipients = recipients.Concat(await _userManager.GetUsersInRoleAsync(OmbiRoles.PowerUser));
|
||||
return recipients;
|
||||
}
|
||||
|
||||
private NotificationMessageContent Parse(NotificationOptions model, NotificationTemplates template, NotificationAgent agent)
|
||||
{
|
||||
var resolver = new NotificationMessageResolver();
|
||||
|
|
|
@ -64,7 +64,20 @@ namespace Ombi.Notifications
|
|||
MessageId = messageId
|
||||
};
|
||||
message.From.Add(new MailboxAddress(string.IsNullOrEmpty(settings.SenderName) ? settings.SenderAddress : settings.SenderName, settings.SenderAddress));
|
||||
message.To.Add(new MailboxAddress(model.To, model.To));
|
||||
if (model.To.HasValue())
|
||||
{
|
||||
message.To.Add(new MailboxAddress(model.To, model.To));
|
||||
}
|
||||
|
||||
// Check for BCC
|
||||
if (model.Other.TryGetValue("bcc", out var bcc))
|
||||
{
|
||||
var bccList = bcc.Split(',', StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var item in bccList)
|
||||
{
|
||||
message.Bcc.Add(new MailboxAddress(item, item));
|
||||
}
|
||||
}
|
||||
|
||||
using (var client = new SmtpClient())
|
||||
{
|
||||
|
|
|
@ -39,7 +39,22 @@ namespace Ombi.Notifications
|
|||
Year = req?.ReleaseDate.Year.ToString();
|
||||
Overview = req?.Overview;
|
||||
AdditionalInformation = opts?.AdditionalInformation ?? string.Empty;
|
||||
PosterImage = $"https://image.tmdb.org/t/p/w300/{req?.PosterPath?.TrimStart('/') ?? string.Empty}";
|
||||
|
||||
var img = req?.PosterPath ?? string.Empty;
|
||||
if (img.HasValue())
|
||||
{
|
||||
if (img.StartsWith("http"))
|
||||
{
|
||||
// This means it's a legacy request from when we used TvMaze as a provider.
|
||||
// The poster url is the fully qualified address, so just use it
|
||||
PosterImage = img;
|
||||
}
|
||||
else
|
||||
{
|
||||
PosterImage =
|
||||
$"https://image.tmdb.org/t/p/w300/{img?.TrimStart('/') ?? string.Empty}";
|
||||
}
|
||||
}
|
||||
CalculateRequestStatus(req);
|
||||
}
|
||||
|
||||
|
@ -53,8 +68,21 @@ namespace Ombi.Notifications
|
|||
Year = req?.ParentRequest?.ReleaseDate.Year.ToString();
|
||||
Overview = req?.ParentRequest?.Overview;
|
||||
AdditionalInformation = opts.AdditionalInformation;
|
||||
PosterImage =
|
||||
$"https://image.tmdb.org/t/p/w300/{req?.ParentRequest?.PosterPath?.TrimStart('/') ?? string.Empty}";
|
||||
var img = req?.ParentRequest?.PosterPath ?? string.Empty;
|
||||
if (img.HasValue())
|
||||
{
|
||||
if (img.StartsWith("http"))
|
||||
{
|
||||
// This means it's a legacy request from when we used TvMaze as a provider.
|
||||
// The poster url is the fully qualified address, so just use it
|
||||
PosterImage = img;
|
||||
}
|
||||
else
|
||||
{
|
||||
PosterImage =
|
||||
$"https://image.tmdb.org/t/p/w300/{img?.TrimStart('/') ?? string.Empty}";
|
||||
}
|
||||
}
|
||||
|
||||
// Generate episode list.
|
||||
StringBuilder epSb = new StringBuilder();
|
||||
|
@ -94,16 +122,24 @@ namespace Ombi.Notifications
|
|||
|
||||
private void LoadIssues(NotificationOptions opts)
|
||||
{
|
||||
IssueDescription = opts.Substitutes.TryGetValue("IssueDescription", out string val) ? val : string.Empty;
|
||||
IssueCategory = opts.Substitutes.TryGetValue("IssueCategory", out val) ? val : string.Empty;
|
||||
IssueStatus = opts.Substitutes.TryGetValue("IssueStatus", out val) ? val : string.Empty;
|
||||
IssueSubject = opts.Substitutes.TryGetValue("IssueSubject", out val) ? val : string.Empty;
|
||||
NewIssueComment = opts.Substitutes.TryGetValue("NewIssueComment", out val) ? val : string.Empty;
|
||||
UserName = opts.Substitutes.TryGetValue("IssueUser", out val) ? val : string.Empty;
|
||||
Alias = opts.Substitutes.TryGetValue("IssueUserAlias", out val) ? val : string.Empty;
|
||||
Type = opts.Substitutes.TryGetValue("RequestType", out val) && Enum.TryParse(val, out RequestType type)
|
||||
IssueDescription = opts.Substitutes.TryGetValue(NotificationSubstitues.IssueDescription, out string val) ? val : string.Empty;
|
||||
IssueCategory = opts.Substitutes.TryGetValue(NotificationSubstitues.IssueCategory, out val) ? val : string.Empty;
|
||||
IssueStatus = opts.Substitutes.TryGetValue(NotificationSubstitues.IssueStatus, out val) ? val : string.Empty;
|
||||
IssueSubject = opts.Substitutes.TryGetValue(NotificationSubstitues.IssueSubject, out val) ? val : string.Empty;
|
||||
NewIssueComment = opts.Substitutes.TryGetValue(NotificationSubstitues.NewIssueComment, out val) ? val : string.Empty;
|
||||
UserName = opts.Substitutes.TryGetValue(NotificationSubstitues.IssueUser, out val) ? val : string.Empty;
|
||||
Alias = opts.Substitutes.TryGetValue(NotificationSubstitues.IssueUserAlias, out val) ? val : string.Empty;
|
||||
Type = opts.Substitutes.TryGetValue(NotificationSubstitues.RequestType, out val) && Enum.TryParse(val, out RequestType type)
|
||||
? HumanizeReturnType(type)
|
||||
: string.Empty;
|
||||
if (opts.Substitutes.TryGetValue(NotificationSubstitues.PosterPath, out val) && val.HasValue())
|
||||
{
|
||||
PosterImage = $"https://image.tmdb.org/t/p/w300/{val.TrimStart('/')}";
|
||||
}
|
||||
else
|
||||
{
|
||||
PosterImage = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadCommon(BaseRequest req, CustomizationSettings s, UserNotificationPreferences pref, NotificationOptions opts)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
|||
<PackageReference Include="Moq" Version="4.15.1" />
|
||||
<PackageReference Include="Moq.AutoMock" Version="0.4.0" />
|
||||
<PackageReference Include="Nunit" Version="3.11.0" />
|
||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
|
||||
<PackageReference Include="NUnit.ConsoleRunner" Version="3.9.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
|
||||
<packagereference Include="Microsoft.NET.Test.Sdk" Version="16.11.0"></packagereference>
|
||||
|
|
|
@ -5,6 +5,8 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Ombi.Api.Emby;
|
||||
using Ombi.Api.Emby.Models;
|
||||
using Ombi.Api.Emby.Models.Media.Tv;
|
||||
using Ombi.Api.Emby.Models.Movie;
|
||||
using Ombi.Core.Settings;
|
||||
using Ombi.Core.Settings.Models.External;
|
||||
|
@ -36,24 +38,33 @@ namespace Ombi.Schedule.Jobs.Emby
|
|||
private readonly IEmbyContentRepository _repo;
|
||||
private readonly IHubContext<NotificationHub> _notification;
|
||||
|
||||
private const int AmountToTake = 100;
|
||||
|
||||
private IEmbyApi Api { get; set; }
|
||||
|
||||
public async Task Execute(IJobExecutionContext job)
|
||||
public async Task Execute(IJobExecutionContext context)
|
||||
{
|
||||
JobDataMap dataMap = context.JobDetail.JobDataMap;
|
||||
var recentlyAddedSearch = false;
|
||||
if (dataMap.TryGetValue(JobDataKeys.EmbyRecentlyAddedSearch, out var recentlyAddedObj))
|
||||
{
|
||||
recentlyAddedSearch = Convert.ToBoolean(recentlyAddedObj);
|
||||
}
|
||||
|
||||
var embySettings = await _settings.GetSettingsAsync();
|
||||
if (!embySettings.Enable)
|
||||
return;
|
||||
|
||||
|
||||
Api = _apiFactory.CreateClient(embySettings);
|
||||
|
||||
await _notification.Clients.Clients(NotificationHub.AdminConnectionIds)
|
||||
.SendAsync(NotificationHub.NotificationEvent, "Emby Content Sync Started");
|
||||
.SendAsync(NotificationHub.NotificationEvent, recentlyAddedSearch ? "Emby Recently Added Started" : "Emby Content Sync Started");
|
||||
|
||||
foreach (var server in embySettings.Servers)
|
||||
{
|
||||
try
|
||||
{
|
||||
await StartServerCache(server, embySettings);
|
||||
await StartServerCache(server, recentlyAddedSearch);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -67,11 +78,12 @@ namespace Ombi.Schedule.Jobs.Emby
|
|||
.SendAsync(NotificationHub.NotificationEvent, "Emby Content Sync Finished");
|
||||
// Episodes
|
||||
|
||||
await OmbiQuartz.TriggerJob(nameof(IEmbyEpisodeSync), "Emby");
|
||||
|
||||
await OmbiQuartz.Scheduler.TriggerJob(new JobKey(nameof(IEmbyEpisodeSync), "Emby"), new JobDataMap(new Dictionary<string, string> { { JobDataKeys.EmbyRecentlyAddedSearch, recentlyAddedSearch.ToString() } }));
|
||||
}
|
||||
|
||||
|
||||
private async Task StartServerCache(EmbyServers server, EmbySettings settings)
|
||||
private async Task StartServerCache(EmbyServers server, bool recentlyAdded)
|
||||
{
|
||||
if (!ValidateSettings(server))
|
||||
return;
|
||||
|
@ -86,14 +98,14 @@ namespace Ombi.Schedule.Jobs.Emby
|
|||
foreach (var movieParentIdFilder in movieLibsToFilter)
|
||||
{
|
||||
_logger.LogInformation($"Scanning Lib '{movieParentIdFilder.Title}'");
|
||||
await ProcessMovies(server, movieParentIdFilder.Key);
|
||||
await ProcessMovies(server, recentlyAdded, movieParentIdFilder.Key);
|
||||
}
|
||||
|
||||
var tvLibsToFilter = server.EmbySelectedLibraries.Where(x => x.Enabled && x.CollectionType == "tvshows");
|
||||
foreach (var tvParentIdFilter in tvLibsToFilter)
|
||||
{
|
||||
_logger.LogInformation($"Scanning Lib '{tvParentIdFilter.Title}'");
|
||||
await ProcessTv(server, tvParentIdFilter.Key);
|
||||
await ProcessTv(server, recentlyAdded, tvParentIdFilter.Key);
|
||||
}
|
||||
|
||||
|
||||
|
@ -101,68 +113,74 @@ namespace Ombi.Schedule.Jobs.Emby
|
|||
foreach (var m in mixedLibs)
|
||||
{
|
||||
_logger.LogInformation($"Scanning Lib '{m.Title}'");
|
||||
await ProcessTv(server, m.Key);
|
||||
await ProcessMovies(server, m.Key);
|
||||
await ProcessTv(server, recentlyAdded, m.Key);
|
||||
await ProcessMovies(server, recentlyAdded, m.Key);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await ProcessMovies(server);
|
||||
await ProcessTv(server);
|
||||
await ProcessMovies(server, recentlyAdded);
|
||||
await ProcessTv(server, recentlyAdded);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ProcessTv(EmbyServers server, string parentId = default)
|
||||
private async Task ProcessTv(EmbyServers server, bool recentlyAdded, string parentId = default)
|
||||
{
|
||||
// TV Time
|
||||
var mediaToAdd = new HashSet<EmbyContent>();
|
||||
var tv = await Api.GetAllShows(server.ApiKey, parentId, 0, 200, server.AdministratorId, server.FullUri);
|
||||
EmbyItemContainer<EmbySeries> tv;
|
||||
if (recentlyAdded)
|
||||
{
|
||||
var recentlyAddedAmountToTake = AmountToTake / 2;
|
||||
tv = await Api.RecentlyAddedShows(server.ApiKey, parentId, 0, recentlyAddedAmountToTake, server.AdministratorId, server.FullUri);
|
||||
if (tv.TotalRecordCount > recentlyAddedAmountToTake)
|
||||
{
|
||||
tv.TotalRecordCount = recentlyAddedAmountToTake;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tv = await Api.GetAllShows(server.ApiKey, parentId, 0, AmountToTake, server.AdministratorId, server.FullUri);
|
||||
}
|
||||
var totalTv = tv.TotalRecordCount;
|
||||
var processed = 1;
|
||||
var processed = 0;
|
||||
while (processed < totalTv)
|
||||
{
|
||||
foreach (var tvShow in tv.Items)
|
||||
{
|
||||
try
|
||||
processed++;
|
||||
if (string.IsNullOrEmpty(tvShow.ProviderIds?.Tvdb))
|
||||
{
|
||||
|
||||
processed++;
|
||||
if (string.IsNullOrEmpty(tvShow.ProviderIds?.Tvdb))
|
||||
{
|
||||
_logger.LogInformation("Provider Id on tv {0} is null", tvShow.Name);
|
||||
continue;
|
||||
}
|
||||
|
||||
var existingTv = await _repo.GetByEmbyId(tvShow.Id);
|
||||
if (existingTv == null)
|
||||
{
|
||||
_logger.LogDebug("Adding new TV Show {0}", tvShow.Name);
|
||||
mediaToAdd.Add(new EmbyContent
|
||||
{
|
||||
TvDbId = tvShow.ProviderIds?.Tvdb,
|
||||
ImdbId = tvShow.ProviderIds?.Imdb,
|
||||
TheMovieDbId = tvShow.ProviderIds?.Tmdb,
|
||||
Title = tvShow.Name,
|
||||
Type = EmbyMediaType.Series,
|
||||
EmbyId = tvShow.Id,
|
||||
Url = EmbyHelper.GetEmbyMediaUrl(tvShow.Id, server?.ServerId, server.ServerHostname),
|
||||
AddedAt = DateTime.UtcNow
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogDebug("We already have TV Show {0}", tvShow.Name);
|
||||
}
|
||||
|
||||
_logger.LogInformation("Provider Id on tv {0} is null", tvShow.Name);
|
||||
continue;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
throw;
|
||||
var existingTv = await _repo.GetByEmbyId(tvShow.Id);
|
||||
if (existingTv == null)
|
||||
{
|
||||
_logger.LogDebug("Adding new TV Show {0}", tvShow.Name);
|
||||
mediaToAdd.Add(new EmbyContent
|
||||
{
|
||||
TvDbId = tvShow.ProviderIds?.Tvdb,
|
||||
ImdbId = tvShow.ProviderIds?.Imdb,
|
||||
TheMovieDbId = tvShow.ProviderIds?.Tmdb,
|
||||
Title = tvShow.Name,
|
||||
Type = EmbyMediaType.Series,
|
||||
EmbyId = tvShow.Id,
|
||||
Url = EmbyHelper.GetEmbyMediaUrl(tvShow.Id, server?.ServerId, server.ServerHostname),
|
||||
AddedAt = DateTime.UtcNow
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogDebug("We already have TV Show {0}", tvShow.Name);
|
||||
}
|
||||
}
|
||||
// Get the next batch
|
||||
tv = await Api.GetAllShows(server.ApiKey, parentId, processed, 200, server.AdministratorId, server.FullUri);
|
||||
if (!recentlyAdded)
|
||||
{
|
||||
tv = await Api.GetAllShows(server.ApiKey, parentId, processed, AmountToTake, server.AdministratorId, server.FullUri);
|
||||
}
|
||||
await _repo.AddRange(mediaToAdd);
|
||||
mediaToAdd.Clear();
|
||||
}
|
||||
|
@ -171,11 +189,25 @@ namespace Ombi.Schedule.Jobs.Emby
|
|||
await _repo.AddRange(mediaToAdd);
|
||||
}
|
||||
|
||||
private async Task ProcessMovies(EmbyServers server, string parentId = default)
|
||||
private async Task ProcessMovies(EmbyServers server, bool recentlyAdded, string parentId = default)
|
||||
{
|
||||
var movies = await Api.GetAllMovies(server.ApiKey, parentId, 0, 200, server.AdministratorId, server.FullUri);
|
||||
EmbyItemContainer<EmbyMovie> movies;
|
||||
if (recentlyAdded)
|
||||
{
|
||||
var recentlyAddedAmountToTake = AmountToTake / 2;
|
||||
movies = await Api.RecentlyAddedMovies(server.ApiKey, parentId, 0, recentlyAddedAmountToTake, server.AdministratorId, server.FullUri);
|
||||
// Setting this so we don't attempt to grab more than we need
|
||||
if (movies.TotalRecordCount > recentlyAddedAmountToTake)
|
||||
{
|
||||
movies.TotalRecordCount = recentlyAddedAmountToTake;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
movies = await Api.GetAllMovies(server.ApiKey, parentId, 0, AmountToTake, server.AdministratorId, server.FullUri);
|
||||
}
|
||||
var totalCount = movies.TotalRecordCount;
|
||||
var processed = 1;
|
||||
var processed = 0;
|
||||
var mediaToAdd = new HashSet<EmbyContent>();
|
||||
while (processed < totalCount)
|
||||
{
|
||||
|
@ -189,22 +221,24 @@ namespace Ombi.Schedule.Jobs.Emby
|
|||
{
|
||||
await ProcessMovies(item, mediaToAdd, server);
|
||||
}
|
||||
|
||||
processed++;
|
||||
}
|
||||
else
|
||||
{
|
||||
processed++;
|
||||
// Regular movie
|
||||
await ProcessMovies(movie, mediaToAdd, server);
|
||||
}
|
||||
|
||||
processed++;
|
||||
}
|
||||
|
||||
// Get the next batch
|
||||
movies = await Api.GetAllMovies(server.ApiKey, parentId, processed, 200, server.AdministratorId, server.FullUri);
|
||||
// Recently Added should never be checked as the TotalRecords should equal the amount to take
|
||||
if (!recentlyAdded)
|
||||
{
|
||||
movies = await Api.GetAllMovies(server.ApiKey, parentId, processed, AmountToTake, server.AdministratorId, server.FullUri);
|
||||
}
|
||||
await _repo.AddRange(mediaToAdd);
|
||||
mediaToAdd.Clear();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,8 @@ using Ombi.Store.Entities;
|
|||
using Ombi.Store.Repository;
|
||||
using Quartz;
|
||||
using Ombi.Schedule.Jobs.Ombi;
|
||||
using Ombi.Api.Emby.Models;
|
||||
using Ombi.Api.Emby.Models.Media.Tv;
|
||||
|
||||
namespace Ombi.Schedule.Jobs.Emby
|
||||
{
|
||||
|
@ -61,13 +63,22 @@ namespace Ombi.Schedule.Jobs.Emby
|
|||
private readonly IEmbyContentRepository _repo;
|
||||
private readonly IHubContext<NotificationHub> _notification;
|
||||
|
||||
private const int AmountToTake = 100;
|
||||
|
||||
private IEmbyApi Api { get; set; }
|
||||
|
||||
|
||||
public async Task Execute(IJobExecutionContext job)
|
||||
public async Task Execute(IJobExecutionContext context)
|
||||
{
|
||||
JobDataMap dataMap = context.MergedJobDataMap;
|
||||
var recentlyAddedSearch = false;
|
||||
if (dataMap.TryGetValue(JobDataKeys.EmbyRecentlyAddedSearch, out var recentlyAddedObj))
|
||||
{
|
||||
recentlyAddedSearch = Convert.ToBoolean(recentlyAddedObj);
|
||||
}
|
||||
|
||||
var settings = await _settings.GetSettingsAsync();
|
||||
|
||||
|
||||
Api = _apiFactory.CreateClient(settings);
|
||||
await _notification.Clients.Clients(NotificationHub.AdminConnectionIds)
|
||||
.SendAsync(NotificationHub.NotificationEvent, "Emby Episode Sync Started");
|
||||
|
@ -79,12 +90,12 @@ namespace Ombi.Schedule.Jobs.Emby
|
|||
foreach (var tvParentIdFilter in tvLibsToFilter)
|
||||
{
|
||||
_logger.LogInformation($"Scanning Lib for episodes '{tvParentIdFilter.Title}'");
|
||||
await CacheEpisodes(server, tvParentIdFilter.Key);
|
||||
await CacheEpisodes(server, recentlyAddedSearch, tvParentIdFilter.Key);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await CacheEpisodes(server, string.Empty);
|
||||
await CacheEpisodes(server, recentlyAddedSearch, string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,11 +105,24 @@ namespace Ombi.Schedule.Jobs.Emby
|
|||
await OmbiQuartz.TriggerJob(nameof(IRefreshMetadata), "System");
|
||||
}
|
||||
|
||||
private async Task CacheEpisodes(EmbyServers server, string parentIdFilter)
|
||||
private async Task CacheEpisodes(EmbyServers server, bool recentlyAdded, string parentIdFilter)
|
||||
{
|
||||
var allEpisodes = await Api.GetAllEpisodes(server.ApiKey, parentIdFilter, 0, 200, server.AdministratorId, server.FullUri);
|
||||
EmbyItemContainer<EmbyEpisodes> allEpisodes;
|
||||
if (recentlyAdded)
|
||||
{
|
||||
var recentlyAddedAmountToTake = AmountToTake;
|
||||
allEpisodes = await Api.RecentlyAddedEpisodes(server.ApiKey, parentIdFilter, 0, recentlyAddedAmountToTake, server.AdministratorId, server.FullUri);
|
||||
if (allEpisodes.TotalRecordCount > recentlyAddedAmountToTake)
|
||||
{
|
||||
allEpisodes.TotalRecordCount = recentlyAddedAmountToTake;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
allEpisodes = await Api.GetAllEpisodes(server.ApiKey, parentIdFilter, 0, AmountToTake, server.AdministratorId, server.FullUri);
|
||||
}
|
||||
var total = allEpisodes.TotalRecordCount;
|
||||
var processed = 1;
|
||||
var processed = 0;
|
||||
var epToAdd = new HashSet<EmbyEpisode>();
|
||||
while (processed < total)
|
||||
{
|
||||
|
@ -163,7 +187,10 @@ namespace Ombi.Schedule.Jobs.Emby
|
|||
|
||||
await _repo.AddRange(epToAdd);
|
||||
epToAdd.Clear();
|
||||
allEpisodes = await Api.GetAllEpisodes(server.ApiKey, parentIdFilter, processed, 200, server.AdministratorId, server.FullUri);
|
||||
if (!recentlyAdded)
|
||||
{
|
||||
allEpisodes = await Api.GetAllEpisodes(server.ApiKey, parentIdFilter, processed, AmountToTake, server.AdministratorId, server.FullUri);
|
||||
}
|
||||
}
|
||||
|
||||
if (epToAdd.Any())
|
||||
|
|
|
@ -118,7 +118,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin
|
|||
var mediaToAdd = new HashSet<JellyfinContent>();
|
||||
var tv = await Api.GetAllShows(server.ApiKey, parentId, 0, 200, server.AdministratorId, server.FullUri);
|
||||
var totalTv = tv.TotalRecordCount;
|
||||
var processed = 1;
|
||||
var processed = 0;
|
||||
while (processed < totalTv)
|
||||
{
|
||||
foreach (var tvShow in tv.Items)
|
||||
|
@ -177,7 +177,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin
|
|||
{
|
||||
var movies = await Api.GetAllMovies(server.ApiKey, parentId, 0, 200, server.AdministratorId, server.FullUri);
|
||||
var totalCount = movies.TotalRecordCount;
|
||||
var processed = 1;
|
||||
var processed = 0;
|
||||
var mediaToAdd = new HashSet<JellyfinContent>();
|
||||
while (processed < totalCount)
|
||||
{
|
||||
|
|
|
@ -98,7 +98,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin
|
|||
{
|
||||
var allEpisodes = await Api.GetAllEpisodes(server.ApiKey, parentIdFilter, 0, 200, server.AdministratorId, server.FullUri);
|
||||
var total = allEpisodes.TotalRecordCount;
|
||||
var processed = 1;
|
||||
var processed = 0;
|
||||
var epToAdd = new HashSet<JellyfinEpisode>();
|
||||
while (processed < total)
|
||||
{
|
||||
|
|
|
@ -16,14 +16,16 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
private readonly ISettingsService<OmbiSettings> _ombiSettings;
|
||||
private readonly IMovieRequestRepository _movieRequests;
|
||||
private readonly ITvRequestRepository _tvRequestRepository;
|
||||
private readonly IMusicRequestRepository _musicRequestRepository;
|
||||
private readonly ILogger<AutoDeleteRequests> _logger;
|
||||
|
||||
public AutoDeleteRequests(ISettingsService<OmbiSettings> ombiSettings, IMovieRequestRepository movieRequest,
|
||||
ILogger<AutoDeleteRequests> logger, ITvRequestRepository tvRequestRepository)
|
||||
ILogger<AutoDeleteRequests> logger, ITvRequestRepository tvRequestRepository, IMusicRequestRepository musicRequestRepository)
|
||||
{
|
||||
_ombiSettings = ombiSettings;
|
||||
_movieRequests = movieRequest;
|
||||
_tvRequestRepository = tvRequestRepository;
|
||||
_musicRequestRepository = _musicRequestRepository;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
@ -37,6 +39,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
var date = DateTime.UtcNow.AddDays(-settings.AutoDeleteAfterDays).Date;
|
||||
await ProcessMovieRequests(date);
|
||||
await ProcessTvRequests(date);
|
||||
await ProcessMusicRequests(date);
|
||||
}
|
||||
|
||||
private async Task ProcessMovieRequests(DateTime date)
|
||||
|
@ -66,6 +69,20 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
await _tvRequestRepository.DeleteRange(parentRequests);
|
||||
}
|
||||
|
||||
private async Task ProcessMusicRequests(DateTime date)
|
||||
{
|
||||
var requestsToDelete = await _musicRequestRepository.GetAll().Where(x => x.Available && x.MarkedAsAvailable.HasValue && x.MarkedAsAvailable.Value < date).ToListAsync();
|
||||
|
||||
_logger.LogInformation($"Deleting {requestsToDelete.Count} music requests that have now been scheduled for deletion, All available requests before {date::MM/dd/yyyy} will be deleted");
|
||||
foreach (var r in requestsToDelete)
|
||||
{
|
||||
_logger.LogInformation($"Deleting music title {r.Title} as it was approved on {r.MarkedAsApproved:MM/dd/yyyy hh:mm tt}");
|
||||
}
|
||||
|
||||
await _musicRequestRepository.DeleteRange(requestsToDelete);
|
||||
|
||||
}
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
|
|
|
@ -321,7 +321,9 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
public async Task DownloadAsync(string requestUri, string filename)
|
||||
{
|
||||
Logger.LogDebug(LoggingEvents.Updater, "Starting the DownloadAsync");
|
||||
#pragma warning disable SYSLIB0014 // Type or member is obsolete
|
||||
using (var client = new WebClient())
|
||||
#pragma warning restore SYSLIB0014 // Type or member is obsolete
|
||||
{
|
||||
await client.DownloadFileTaskAsync(requestUri, filename);
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ namespace Ombi.Schedule.Jobs.Sonarr
|
|||
|
||||
foreach (var s in ids)
|
||||
{
|
||||
if (!s.Monitored || s.EpisodeFileCount == 0) // We have files
|
||||
if (!s.Monitored && s.EpisodeFileCount == 0) // We have files
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
@ -11,10 +11,9 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Dapper" Version="1.50.2" />
|
||||
<PackageReference Include="Quartz" Version="3.1.0" />
|
||||
<PackageReference Include="Serilog" Version="2.8.0" />
|
||||
<PackageReference Include="SharpCompress" Version="0.24.0" />
|
||||
<PackageReference Include="SharpCompress" Version="0.30.0" />
|
||||
<PackageReference Include="System.Diagnostics.Process" Version="4.3.0" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.6.13" />
|
||||
<PackageReference Include="Markdig" Version="0.14.8" />
|
||||
|
|
|
@ -96,6 +96,7 @@ namespace Ombi.Schedule
|
|||
private static async Task AddEmby(JobSettings s)
|
||||
{
|
||||
await OmbiQuartz.Instance.AddJob<IEmbyContentSync>(nameof(IEmbyContentSync), "Emby", JobSettingsHelper.EmbyContent(s));
|
||||
await OmbiQuartz.Instance.AddJob<IEmbyContentSync>(nameof(IEmbyContentSync) + "RecentlyAdded", "Emby", JobSettingsHelper.EmbyRecentlyAddedSync(s), new Dictionary<string, string> { { JobDataKeys.EmbyRecentlyAddedSearch, "true" } });
|
||||
await OmbiQuartz.Instance.AddJob<IEmbyEpisodeSync>(nameof(IEmbyEpisodeSync), "Emby", null);
|
||||
await OmbiQuartz.Instance.AddJob<IEmbyAvaliabilityChecker>(nameof(IEmbyAvaliabilityChecker), "Emby", null);
|
||||
await OmbiQuartz.Instance.AddJob<IEmbyUserImporter>(nameof(IEmbyUserImporter), "Emby", JobSettingsHelper.UserImporter(s));
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup><TargetFramework>net5.0</TargetFramework>
|
||||
<PropertyGroup><TargetFramework>net6.0</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="nunit" Version="3.11.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
|
||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||
<FileVersion>3.0.0.0</FileVersion>
|
||||
<Version></Version>
|
||||
|
@ -11,7 +11,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
|
||||
<PackageReference Include="Quartz" Version="3.1.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
</ItemGroup>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue