mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-23 06:25:24 -07:00
Merge branch 'l10n_develop' of https://github.com/Ombi-app/Ombi into l10n_develop
This commit is contained in:
commit
29994f8e2b
133 changed files with 1442 additions and 459 deletions
10
.github/workflows/build.yml
vendored
10
.github/workflows/build.yml
vendored
|
@ -3,6 +3,7 @@ name: CI Build
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ develop, master ]
|
branches: [ develop, master ]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-ui:
|
build-ui:
|
||||||
|
@ -38,7 +39,7 @@ jobs:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-dotnet@v1
|
- uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: '5.0.x'
|
dotnet-version: '6.0.x'
|
||||||
|
|
||||||
- name: Nuget Cache
|
- name: Nuget Cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
|
@ -67,6 +68,7 @@ jobs:
|
||||||
uses: TriPSs/conventional-changelog-action@v3
|
uses: TriPSs/conventional-changelog-action@v3
|
||||||
with:
|
with:
|
||||||
version-file: 'version.json'
|
version-file: 'version.json'
|
||||||
|
release-count: 20
|
||||||
skip-on-empty: 'false'
|
skip-on-empty: 'false'
|
||||||
git-message: 'chore(release): :rocket: {version}'
|
git-message: 'chore(release): :rocket: {version}'
|
||||||
|
|
||||||
|
@ -102,6 +104,12 @@ jobs:
|
||||||
format: tar.gz
|
format: tar.gz
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- 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
|
- name: Nuget Cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
|
|
5
.github/workflows/cypress.yml
vendored
5
.github/workflows/cypress.yml
vendored
|
@ -7,6 +7,7 @@ on:
|
||||||
branches: [ develop ]
|
branches: [ develop ]
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 0 * * *'
|
- cron: '0 0 * * *'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
automation-tests:
|
automation-tests:
|
||||||
|
@ -18,7 +19,7 @@ jobs:
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: 5.0.x
|
dotnet-version: 6.0.x
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: '14'
|
node-version: '14'
|
||||||
|
@ -38,7 +39,7 @@ jobs:
|
||||||
|
|
||||||
- name: Start Backend
|
- name: Start Backend
|
||||||
run: |
|
run: |
|
||||||
nohup dotnet run -p ./src/Ombi -- --host http://*:3577 &
|
nohup dotnet run --project ./src/Ombi -- --host http://*:3577 &
|
||||||
- name: Start Frontend
|
- name: Start Frontend
|
||||||
run: |
|
run: |
|
||||||
nohup yarn --cwd ./src/Ombi/ClientApp start &
|
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:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, synchronize, reopened]
|
types: [opened, synchronize, reopened]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-ui:
|
build-ui:
|
||||||
|
@ -31,7 +32,7 @@ jobs:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-dotnet@v1
|
- uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: '5.0.x'
|
dotnet-version: '6.0.x'
|
||||||
|
|
||||||
- name: Nuget Cache
|
- name: Nuget Cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
|
@ -89,6 +90,9 @@ jobs:
|
||||||
format: tar.gz
|
format: tar.gz
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-dotnet@v1
|
||||||
|
with:
|
||||||
|
dotnet-version: '6.0.x'
|
||||||
|
|
||||||
- name: Nuget Cache
|
- name: Nuget Cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
|
|
131
CHANGELOG.md
131
CHANGELOG.md
|
@ -1,3 +1,61 @@
|
||||||
|
## [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.2...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.2](https://github.com/Ombi-app/Ombi/compare/v4.3.1...v4.3.2) (2021-11-02)
|
## [4.3.2](https://github.com/Ombi-app/Ombi/compare/v4.3.1...v4.3.2) (2021-11-02)
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,3 +125,76 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [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))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [4.2.3](https://github.com/Ombi-app/Ombi/compare/v4.2.2...v4.2.3) (2021-10-12)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **user-management:** :bug: Fixed an issue where the Copy users App Link did not generate the correct app link for that user ([8cafcdc](https://github.com/Ombi-app/Ombi/commit/8cafcdcc3baa85c55d75e43835b2289bbea69b0e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
22
README.md
22
README.md
|
@ -18,7 +18,7 @@ Don't worry, it's grandma friendly, and more importantly; has wife approval cert
|
||||||
|
|
||||||
| Service | Stable | Develop
|
| 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) |
|
| 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
|
# Feature Requests
|
||||||
|
@ -142,21 +142,28 @@ Here are some of the features Ombi has:
|
||||||
<sub><b>Victor Usoltsev</b></sub>
|
<sub><b>Victor Usoltsev</b></sub>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</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">
|
<td align="center">
|
||||||
<a href="https://github.com/dhruvb14">
|
<a href="https://github.com/dhruvb14">
|
||||||
<img src="https://avatars.githubusercontent.com/u/4459649?v=4" width="50;" alt="dhruvb14"/>
|
<img src="https://avatars.githubusercontent.com/u/4459649?v=4" width="50;" alt="dhruvb14"/>
|
||||||
<br />
|
<br />
|
||||||
<sub><b>Dhruv Bhavsar</b></sub>
|
<sub><b>Dhruv Bhavsar</b></sub>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td></tr>
|
||||||
|
<tr>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<a href="https://github.com/joshuaboniface">
|
<a href="https://github.com/joshuaboniface">
|
||||||
<img src="https://avatars.githubusercontent.com/u/4031396?v=4" width="50;" alt="joshuaboniface"/>
|
<img src="https://avatars.githubusercontent.com/u/4031396?v=4" width="50;" alt="joshuaboniface"/>
|
||||||
<br />
|
<br />
|
||||||
<sub><b>Joshua M. Boniface</b></sub>
|
<sub><b>Joshua M. Boniface</b></sub>
|
||||||
</a>
|
</a>
|
||||||
</td></tr>
|
</td>
|
||||||
<tr>
|
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<a href="https://github.com/bruvv">
|
<a href="https://github.com/bruvv">
|
||||||
<img src="https://avatars.githubusercontent.com/u/3063928?v=4" width="50;" alt="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>
|
<sub><b>Bruvv</b></sub>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</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">
|
<td align="center">
|
||||||
<a href="https://github.com/louis-lau">
|
<a href="https://github.com/louis-lau">
|
||||||
<img src="https://avatars.githubusercontent.com/u/1346804?v=4" width="50;" alt="louis-lau"/>
|
<img src="https://avatars.githubusercontent.com/u/1346804?v=4" width="50;" alt="louis-lau"/>
|
||||||
|
|
14
makefile
Normal file
14
makefile
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
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-tests:
|
||||||
|
cd tests && yarn
|
||||||
|
|
||||||
|
tests:
|
||||||
|
cd tests && npx cypress open
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<LangVersion>8.0</LangVersion>
|
<LangVersion>8.0</LangVersion>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<LangVersion>8.0</LangVersion>
|
<LangVersion>8.0</LangVersion>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<LangVersion>8.0</LangVersion>
|
<LangVersion>8.0</LangVersion>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<LangVersion>8.0</LangVersion>
|
<LangVersion>8.0</LangVersion>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<LangVersion>8.0</LangVersion>
|
<LangVersion>8.0</LangVersion>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<LangVersion>8.0</LangVersion>
|
<LangVersion>8.0</LangVersion>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<LangVersion>8.0</LangVersion>
|
<LangVersion>8.0</LangVersion>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<LangVersion>8.0</LangVersion>
|
<LangVersion>8.0</LangVersion>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<LangVersion>8.0</LangVersion>
|
<LangVersion>8.0</LangVersion>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<LangVersion>8.0</LangVersion>
|
<LangVersion>8.0</LangVersion>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
|
|
@ -66,6 +66,8 @@ namespace Ombi.Api
|
||||||
startingTag = builder.Query.Contains("?") ? "&" : "?";
|
startingTag = builder.Query.Contains("?") ? "&" : "?";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
value = Uri.EscapeDataString(value);
|
||||||
|
|
||||||
builder.Query = hasQuery
|
builder.Query = hasQuery
|
||||||
? $"{builder.Query}{startingTag}{parameter}={value}"
|
? $"{builder.Query}{startingTag}{parameter}={value}"
|
||||||
: $"{startingTag}{parameter}={value}";
|
: $"{startingTag}{parameter}={value}";
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
@ -11,8 +11,8 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<PackageReference Include="Polly" Version="7.1.0" />
|
<PackageReference Include="Polly" Version="7.1.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AutoFixture" Version="4.11.0" />
|
<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" Version="4.15.1" />
|
||||||
<PackageReference Include="Moq.AutoMock" Version="3.0.0" />
|
<PackageReference Include="Moq.AutoMock" Version="3.0.0" />
|
||||||
<PackageReference Include="Nunit" Version="3.12.0" />
|
<PackageReference Include="Nunit" Version="3.12.0" />
|
||||||
|
|
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;
|
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()
|
public RequestCountModel RequestCount()
|
||||||
{
|
{
|
||||||
var movieQuery = MovieRepository.GetAll();
|
var movieQuery = MovieRepository.GetAll();
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace Ombi.Core.Engine
|
||||||
Task<int> GetTotal();
|
Task<int> GetTotal();
|
||||||
Task<RequestEngineResult> MarkAvailable(int modelId);
|
Task<RequestEngineResult> MarkAvailable(int modelId);
|
||||||
Task<RequestEngineResult> MarkUnavailable(int modelId);
|
Task<RequestEngineResult> MarkUnavailable(int modelId);
|
||||||
Task RemoveAlbumRequest(int requestId);
|
Task<RequestEngineResult> RemoveAlbumRequest(int requestId);
|
||||||
Task<RequestEngineResult> RequestAlbum(MusicAlbumRequestViewModel model);
|
Task<RequestEngineResult> RequestAlbum(MusicAlbumRequestViewModel model);
|
||||||
Task<IEnumerable<AlbumRequest>> SearchAlbumRequest(string search);
|
Task<IEnumerable<AlbumRequest>> SearchAlbumRequest(string search);
|
||||||
Task<bool> UserHasRequest(string userId);
|
Task<bool> UserHasRequest(string userId);
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace Ombi.Core.Engine.Interfaces
|
||||||
Task<IEnumerable<MovieRequests>> SearchMovieRequest(string search);
|
Task<IEnumerable<MovieRequests>> SearchMovieRequest(string search);
|
||||||
Task<RequestEngineResult> RequestCollection(int collectionId, CancellationToken cancellationToken);
|
Task<RequestEngineResult> RequestCollection(int collectionId, CancellationToken cancellationToken);
|
||||||
|
|
||||||
Task RemoveMovieRequest(int requestId);
|
Task<RequestEngineResult> RemoveMovieRequest(int requestId);
|
||||||
Task RemoveAllMovieRequests();
|
Task RemoveAllMovieRequests();
|
||||||
Task<MovieRequests> GetRequest(int requestId);
|
Task<MovieRequests> GetRequest(int requestId);
|
||||||
Task<MovieRequests> UpdateMovieRequest(MovieRequests request);
|
Task<MovieRequests> UpdateMovieRequest(MovieRequests request);
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace Ombi.Core.Engine.Interfaces
|
||||||
Task<TvRequests> UpdateTvRequest(TvRequests request);
|
Task<TvRequests> UpdateTvRequest(TvRequests request);
|
||||||
Task<IEnumerable<ChildRequests>> GetAllChldren(int tvId);
|
Task<IEnumerable<ChildRequests>> GetAllChldren(int tvId);
|
||||||
Task<ChildRequests> UpdateChildRequest(ChildRequests request);
|
Task<ChildRequests> UpdateChildRequest(ChildRequests request);
|
||||||
Task RemoveTvChild(int requestId);
|
Task<RequestEngineResult> RemoveTvChild(int requestId);
|
||||||
Task<RequestEngineResult> ApproveChildRequest(int id);
|
Task<RequestEngineResult> ApproveChildRequest(int id);
|
||||||
Task<IEnumerable<TvRequests>> GetRequestsLite();
|
Task<IEnumerable<TvRequests>> GetRequestsLite();
|
||||||
Task UpdateQualityProfile(int requestId, int profileId);
|
Task UpdateQualityProfile(int requestId, int profileId);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Ombi.Api.TheMovieDb.Models;
|
||||||
using Ombi.Core.Models.Search;
|
using Ombi.Core.Models.Search;
|
||||||
using Ombi.Core.Models.Search.V2;
|
using Ombi.Core.Models.Search.V2;
|
||||||
|
|
||||||
|
@ -10,6 +11,7 @@ namespace Ombi.Core
|
||||||
{
|
{
|
||||||
Task<SearchFullInfoTvShowViewModel> GetShowInformation(string tvdbid, CancellationToken token);
|
Task<SearchFullInfoTvShowViewModel> GetShowInformation(string tvdbid, CancellationToken token);
|
||||||
Task<SearchFullInfoTvShowViewModel> GetShowByRequest(int requestId, 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<StreamingData>> GetStreamInformation(int movieDbId, CancellationToken cancellationToken);
|
||||||
Task<IEnumerable<SearchTvShowViewModel>> Popular(int currentlyLoaded, int amountToLoad, string langCustomCode = null);
|
Task<IEnumerable<SearchTvShowViewModel>> Popular(int currentlyLoaded, int amountToLoad, string langCustomCode = null);
|
||||||
Task<IEnumerable<SearchTvShowViewModel>> Anticipated(int currentlyLoaded, int amountToLoad);
|
Task<IEnumerable<SearchTvShowViewModel>> Anticipated(int currentlyLoaded, int amountToLoad);
|
||||||
|
|
|
@ -654,11 +654,20 @@ namespace Ombi.Core.Engine
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="requestId">The request identifier.</param>
|
/// <param name="requestId">The request identifier.</param>
|
||||||
/// <returns></returns>
|
/// <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 request = await MovieRepository.GetAll().FirstOrDefaultAsync(x => x.Id == requestId);
|
||||||
|
|
||||||
|
var result = await CheckCanManageRequest(request);
|
||||||
|
if (result.IsError)
|
||||||
|
return result;
|
||||||
|
|
||||||
await MovieRepository.Delete(request);
|
await MovieRepository.Delete(request);
|
||||||
await _mediaCacheService.Purge();
|
await _mediaCacheService.Purge();
|
||||||
|
return new RequestEngineResult
|
||||||
|
{
|
||||||
|
Result = true,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RemoveAllMovieRequests()
|
public async Task RemoveAllMovieRequests()
|
||||||
|
|
|
@ -404,10 +404,20 @@ namespace Ombi.Core.Engine
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="requestId">The request identifier.</param>
|
/// <param name="requestId">The request identifier.</param>
|
||||||
/// <returns></returns>
|
/// <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 request = await MusicRepository.GetAll().FirstOrDefaultAsync(x => x.Id == requestId);
|
||||||
|
|
||||||
|
var result = await CheckCanManageRequest(request);
|
||||||
|
if (result.IsError)
|
||||||
|
return result;
|
||||||
|
|
||||||
await MusicRepository.Delete(request);
|
await MusicRepository.Delete(request);
|
||||||
|
|
||||||
|
return new RequestEngineResult
|
||||||
|
{
|
||||||
|
Result = true,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> UserHasRequest(string userId)
|
public async Task<bool> UserHasRequest(string userId)
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace Ombi.Core.Engine
|
||||||
{
|
{
|
||||||
public bool Result { get; set; }
|
public bool Result { get; set; }
|
||||||
public string Message { 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 string ErrorMessage { get; set; }
|
||||||
public ErrorCode? ErrorCode { get; set; }
|
public ErrorCode? ErrorCode { get; set; }
|
||||||
public int RequestId { get; set; }
|
public int RequestId { get; set; }
|
||||||
|
|
|
@ -749,10 +749,14 @@ namespace Ombi.Core.Engine
|
||||||
return request;
|
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 request = await TvRepository.GetChild().FirstOrDefaultAsync(x => x.Id == requestId);
|
||||||
|
|
||||||
|
var result = await CheckCanManageRequest(request);
|
||||||
|
if (result.IsError)
|
||||||
|
return result;
|
||||||
|
|
||||||
TvRepository.Db.ChildRequests.Remove(request);
|
TvRepository.Db.ChildRequests.Remove(request);
|
||||||
var all = TvRepository.Db.TvRequests.Include(x => x.ChildRequests);
|
var all = TvRepository.Db.TvRequests.Include(x => x.ChildRequests);
|
||||||
var parent = all.FirstOrDefault(x => x.Id == request.ParentRequestId);
|
var parent = all.FirstOrDefault(x => x.Id == request.ParentRequestId);
|
||||||
|
@ -766,6 +770,11 @@ namespace Ombi.Core.Engine
|
||||||
|
|
||||||
await TvRepository.Db.SaveChangesAsync();
|
await TvRepository.Db.SaveChangesAsync();
|
||||||
await _mediaCacheService.Purge();
|
await _mediaCacheService.Purge();
|
||||||
|
|
||||||
|
return new RequestEngineResult
|
||||||
|
{
|
||||||
|
Result = true,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RemoveTvRequest(int requestId)
|
public async Task RemoveTvRequest(int requestId)
|
||||||
|
|
|
@ -323,6 +323,7 @@ namespace Ombi.Core.Engine.V2
|
||||||
|
|
||||||
public async Task<ActorCredits> GetMoviesByActor(int actorId, string langCode)
|
public async Task<ActorCredits> GetMoviesByActor(int actorId, string langCode)
|
||||||
{
|
{
|
||||||
|
langCode = await DefaultLanguageCode(langCode);
|
||||||
var result = await Cache.GetOrAddAsync(nameof(GetMoviesByActor) + actorId + langCode,
|
var result = await Cache.GetOrAddAsync(nameof(GetMoviesByActor) + actorId + langCode,
|
||||||
() => MovieApi.GetActorMovieCredits(actorId, langCode), DateTimeOffset.Now.AddHours(12));
|
() => MovieApi.GetActorMovieCredits(actorId, langCode), DateTimeOffset.Now.AddHours(12));
|
||||||
// Later we run this through the rules engine
|
// Later we run this through the rules engine
|
||||||
|
|
|
@ -147,6 +147,13 @@ namespace Ombi.Core.Engine.V2
|
||||||
return await processed;
|
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)
|
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 Subject { get; set; }
|
||||||
public string Body { get; set; }
|
public string Body { get; set; }
|
||||||
|
|
||||||
|
public bool Bcc { get; set; }
|
||||||
|
|
||||||
public List<OmbiUser> Users { get; set; }
|
public List<OmbiUser> Users { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
@ -13,8 +13,8 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AutoMapper" Version="10.0.0" />
|
<PackageReference Include="AutoMapper" Version="10.0.0" />
|
||||||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.0.1" />
|
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.0.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="5.0.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.0" />
|
||||||
<PackageReference Include="MusicBrainzAPI" Version="2.0.1" />
|
<PackageReference Include="MusicBrainzAPI" Version="2.0.1" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<PackageReference Include="System.Diagnostics.Process" Version="4.3.0" />
|
<PackageReference Include="System.Diagnostics.Process" Version="4.3.0" />
|
||||||
|
|
|
@ -25,7 +25,9 @@
|
||||||
// ************************************************************************/
|
// ************************************************************************/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
@ -64,6 +66,63 @@ namespace Ombi.Core.Senders
|
||||||
var customization = await _customizationService.GetSettingsAsync();
|
var customization = await _customizationService.GetSettingsAsync();
|
||||||
var email = await _emailService.GetSettingsAsync();
|
var email = await _emailService.GetSettingsAsync();
|
||||||
var messagesSent = new List<Task>();
|
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)
|
foreach (var user in model.Users)
|
||||||
{
|
{
|
||||||
var fullUser = await _userManager.Users.FirstOrDefaultAsync(x => x.Id == user.Id);
|
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);
|
_log.LogInformation("User {0} has no email, cannot send mass email to this user", fullUser.UserName);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var resolver = new NotificationMessageResolver();
|
|
||||||
var curlys = new NotificationMessageCurlys();
|
|
||||||
curlys.Setup(fullUser, customization);
|
curlys.Setup(fullUser, customization);
|
||||||
var template = new NotificationTemplates() { Message = model.Body, Subject = model.Subject };
|
var template = new NotificationTemplates() { Message = model.Body, Subject = model.Subject };
|
||||||
var content = resolver.ParseMessage(template, curlys);
|
var content = resolver.ParseMessage(template, curlys);
|
||||||
|
@ -83,13 +140,19 @@ namespace Ombi.Core.Senders
|
||||||
To = fullUser.Email,
|
To = fullUser.Email,
|
||||||
Subject = content.Subject
|
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);
|
_log.LogInformation("Sent mass email to user {0} @ {1}", fullUser.UserName, fullUser.Email);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await Task.WhenAll(messagesSent);
|
/// <summary>
|
||||||
|
/// This will add a 2 second delay, this is to help with concurrent connection limits
|
||||||
return true;
|
/// <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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
@ -11,10 +11,10 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<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.AspNetCore.Http" Version="2.2.2" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="nunit" Version="3.11.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="NUnit3TestAdapter" Version="3.13.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -6,16 +6,6 @@ namespace Ombi.Helpers
|
||||||
{
|
{
|
||||||
public static class LinqHelpers
|
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>(
|
public static HashSet<T> ToHashSet<T>(
|
||||||
this IEnumerable<T> source,
|
this IEnumerable<T> source,
|
||||||
IEqualityComparer<T> comparer = null)
|
IEqualityComparer<T> comparer = null)
|
||||||
|
|
|
@ -53,17 +53,18 @@ namespace Ombi.Helpers
|
||||||
_memoryCache.Set(CacheKey, mediaServiceCache);
|
_memoryCache.Set(CacheKey, mediaServiceCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Purge()
|
public Task Purge()
|
||||||
{
|
{
|
||||||
var keys = _memoryCache.Get<List<string>>(CacheKey);
|
var keys = _memoryCache.Get<List<string>>(CacheKey);
|
||||||
if (keys == null)
|
if (keys == null)
|
||||||
{
|
{
|
||||||
return;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
foreach (var key in keys)
|
foreach (var key in keys)
|
||||||
{
|
{
|
||||||
base.Remove(key);
|
base.Remove(key);
|
||||||
}
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
@ -13,8 +13,8 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="EasyCrypto" Version="3.3.2" />
|
<PackageReference Include="EasyCrypto" Version="3.3.2" />
|
||||||
<PackageReference Include="LazyCache.AspNetCore" Version="2.1.3" />
|
<PackageReference Include="LazyCache.AspNetCore" Version="2.1.3" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<PackageReference Include="Nito.AsyncEx" Version="5.1.0" />
|
<PackageReference Include="Nito.AsyncEx" Version="5.1.0" />
|
||||||
<PackageReference Include="Quartz" Version="3.1.0" />
|
<PackageReference Include="Quartz" Version="3.1.0" />
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<LangVersion>8.0</LangVersion>
|
<LangVersion>8.0</LangVersion>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace Ombi.Notifications.Templates
|
||||||
if (string.IsNullOrEmpty(_templateLocation))
|
if (string.IsNullOrEmpty(_templateLocation))
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "net5.0", "Templates",
|
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "net6.0", "Templates",
|
||||||
"BasicTemplate.html");
|
"BasicTemplate.html");
|
||||||
#else
|
#else
|
||||||
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "Templates","BasicTemplate.html");
|
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "Templates","BasicTemplate.html");
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace Ombi.Notifications.Templates
|
||||||
if (string.IsNullOrEmpty(_templateLocation))
|
if (string.IsNullOrEmpty(_templateLocation))
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#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
|
#else
|
||||||
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "Templates", "NewsletterTemplate.html");
|
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "Templates", "NewsletterTemplate.html");
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
<PackageReference Include="Nunit" Version="3.11.0" />
|
<PackageReference Include="Nunit" Version="3.11.0" />
|
||||||
<PackageReference Include="NUnit.ConsoleRunner" Version="3.9.0" />
|
<PackageReference Include="NUnit.ConsoleRunner" Version="3.9.0" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="3.13.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="Microsoft.NET.Test.Sdk" Version="16.8.0"></packagereference>
|
||||||
<PackageReference Include="Moq" Version="4.10.0" />
|
<PackageReference Include="Moq" Version="4.10.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -64,7 +64,20 @@ namespace Ombi.Notifications
|
||||||
MessageId = messageId
|
MessageId = messageId
|
||||||
};
|
};
|
||||||
message.From.Add(new MailboxAddress(string.IsNullOrEmpty(settings.SenderName) ? settings.SenderAddress : settings.SenderName, settings.SenderAddress));
|
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())
|
using (var client = new SmtpClient())
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
<PackageReference Include="Moq" Version="4.15.1" />
|
<PackageReference Include="Moq" Version="4.15.1" />
|
||||||
<PackageReference Include="Moq.AutoMock" Version="0.4.0" />
|
<PackageReference Include="Moq.AutoMock" Version="0.4.0" />
|
||||||
<PackageReference Include="Nunit" Version="3.11.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="NUnit.ConsoleRunner" Version="3.9.0" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
|
||||||
<packagereference Include="Microsoft.NET.Test.Sdk" Version="16.11.0"></packagereference>
|
<packagereference Include="Microsoft.NET.Test.Sdk" Version="16.11.0"></packagereference>
|
||||||
|
|
|
@ -321,7 +321,9 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
public async Task DownloadAsync(string requestUri, string filename)
|
public async Task DownloadAsync(string requestUri, string filename)
|
||||||
{
|
{
|
||||||
Logger.LogDebug(LoggingEvents.Updater, "Starting the DownloadAsync");
|
Logger.LogDebug(LoggingEvents.Updater, "Starting the DownloadAsync");
|
||||||
|
#pragma warning disable SYSLIB0014 // Type or member is obsolete
|
||||||
using (var client = new WebClient())
|
using (var client = new WebClient())
|
||||||
|
#pragma warning restore SYSLIB0014 // Type or member is obsolete
|
||||||
{
|
{
|
||||||
await client.DownloadFileTaskAsync(requestUri, filename);
|
await client.DownloadFileTaskAsync(requestUri, filename);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
@ -11,10 +11,9 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Dapper" Version="1.50.2" />
|
|
||||||
<PackageReference Include="Quartz" Version="3.1.0" />
|
<PackageReference Include="Quartz" Version="3.1.0" />
|
||||||
<PackageReference Include="Serilog" Version="2.8.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="System.Diagnostics.Process" Version="4.3.0" />
|
||||||
<PackageReference Include="HtmlAgilityPack" Version="1.6.13" />
|
<PackageReference Include="HtmlAgilityPack" Version="1.6.13" />
|
||||||
<PackageReference Include="Markdig" Version="0.14.8" />
|
<PackageReference Include="Markdig" Version="0.14.8" />
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup><TargetFramework>net5.0</TargetFramework>
|
<PropertyGroup><TargetFramework>net6.0</TargetFramework>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="nunit" Version="3.11.0" />
|
<PackageReference Include="nunit" Version="3.11.0" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="3.13.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 Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
|
||||||
<PackageReference Include="Quartz" Version="3.1.0" />
|
<PackageReference Include="Quartz" Version="3.1.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
@ -12,14 +12,14 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.0">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="5.0.0-alpha.1" />
|
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="6.0.0" />
|
||||||
<PackageReference Include="Nito.AsyncEx" Version="5.1.0" />
|
<PackageReference Include="Nito.AsyncEx" Version="5.1.0" />
|
||||||
<PackageReference Include="Polly" Version="7.1.0" />
|
<PackageReference Include="Polly" Version="7.1.0" />
|
||||||
<!--<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="1.1.9" />-->
|
<!--<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="1.1.9" />-->
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<LangVersion>8.0</LangVersion>
|
<LangVersion>8.0</LangVersion>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
|
|
||||||
|
@ -9,12 +9,12 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="5.0.0" />
|
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="6.0.0" />
|
||||||
<PackageReference Include="Moq" Version="4.10.0" />
|
<PackageReference Include="Moq" Version="4.10.0" />
|
||||||
<PackageReference Include="Nunit" Version="3.11.0" />
|
<PackageReference Include="Nunit" Version="3.11.0" />
|
||||||
<PackageReference Include="Hangfire" Version="1.7.1" />
|
<PackageReference Include="Hangfire" Version="1.7.1" />
|
||||||
<PackageReference Include="NUnit.ConsoleRunner" Version="3.9.0" />
|
<PackageReference Include="NUnit.ConsoleRunner" Version="3.9.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="NUnit3TestAdapter" Version="3.13.0" />
|
||||||
<packagereference Include="Microsoft.NET.Test.Sdk" Version="16.8.0"></packagereference>
|
<packagereference Include="Microsoft.NET.Test.Sdk" Version="16.8.0"></packagereference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -31,6 +31,7 @@ namespace Ombi.Api.TheMovieDb
|
||||||
Task<TvInfo> GetTVInfo(string themoviedbid, string langCode = "en");
|
Task<TvInfo> GetTVInfo(string themoviedbid, string langCode = "en");
|
||||||
Task<TheMovieDbContainer<ActorResult>> SearchByActor(string searchTerm, string langCode);
|
Task<TheMovieDbContainer<ActorResult>> SearchByActor(string searchTerm, string langCode);
|
||||||
Task<ActorCredits> GetActorMovieCredits(int actorId, string langCode);
|
Task<ActorCredits> GetActorMovieCredits(int actorId, string langCode);
|
||||||
|
Task<ActorCredits> GetActorTvCredits(int actorId, string langCode);
|
||||||
Task<TheMovieDbContainer<MultiSearch>> MultiSearch(string searchTerm, string languageCode, CancellationToken cancellationToken);
|
Task<TheMovieDbContainer<MultiSearch>> MultiSearch(string searchTerm, string languageCode, CancellationToken cancellationToken);
|
||||||
Task<TheMovieDbContainer<DiscoverMovies>> DiscoverMovies(string langCode, int keywordId);
|
Task<TheMovieDbContainer<DiscoverMovies>> DiscoverMovies(string langCode, int keywordId);
|
||||||
Task<FullMovieInfo> GetFullMovieInfo(int movieId, CancellationToken cancellationToken, string langCode);
|
Task<FullMovieInfo> GetFullMovieInfo(int movieId, CancellationToken cancellationToken, string langCode);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyName>Ombi.Api.TheMovieDb</AssemblyName>
|
<AssemblyName>Ombi.Api.TheMovieDb</AssemblyName>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
|
|
|
@ -139,6 +139,16 @@ namespace Ombi.Api.TheMovieDb
|
||||||
var result = await Api.Request<ActorCredits>(request);
|
var result = await Api.Request<ActorCredits>(request);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<ActorCredits> GetActorTvCredits(int actorId, string langCode)
|
||||||
|
{
|
||||||
|
var request = new Request($"person/{actorId}/tv_credits", BaseUri, HttpMethod.Get);
|
||||||
|
request.AddQueryString("api_key", ApiToken);
|
||||||
|
request.AddQueryString("language", langCode);
|
||||||
|
|
||||||
|
var result = await Api.Request<ActorCredits>(request);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<List<TvSearchResult>> SearchTv(string searchTerm, string year = default)
|
public async Task<List<TvSearchResult>> SearchTv(string searchTerm, string year = default)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RuntimeIdentifiers>win10-x64;win10-x86;osx-x64;ubuntu-x64;debian.8-x64;centos.7-x64;linux-x64;linux-arm;linux-arm64;</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win10-x64;win10-x86;osx-x64;ubuntu-x64;debian.8-x64;centos.7-x64;linux-x64;linux-arm;linux-arm64;</RuntimeIdentifiers>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
@ -13,14 +13,14 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CommandLineParser" Version="2.6.0" />
|
<PackageReference Include="CommandLineParser" Version="2.6.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="6.0.0" />
|
||||||
<PackageReference Include="Serilog" Version="2.9.0" />
|
<PackageReference Include="Serilog" Version="2.9.0" />
|
||||||
<PackageReference Include="Serilog.Extensions.Logging" Version="3.0.1" />
|
<PackageReference Include="Serilog.Extensions.Logging" Version="3.0.1" />
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
|
||||||
|
|
4
src/Ombi/.vscode/settings.json
vendored
4
src/Ombi/.vscode/settings.json
vendored
|
@ -10,13 +10,13 @@
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
"usermanagement"
|
"usermanagement"
|
||||||
],
|
],
|
||||||
"discord.enabled": true,
|
|
||||||
"conventionalCommits.scopes": [
|
"conventionalCommits.scopes": [
|
||||||
"discover",
|
"discover",
|
||||||
"request-limits",
|
"request-limits",
|
||||||
"notifications",
|
"notifications",
|
||||||
"settings",
|
"settings",
|
||||||
"user-management",
|
"user-management",
|
||||||
"newsletter"
|
"newsletter",
|
||||||
|
"mass-email"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,9 @@ import { TooltipModule } from "primeng/tooltip";
|
||||||
import { TranslateHttpLoader } from "@ngx-translate/http-loader";
|
import { TranslateHttpLoader } from "@ngx-translate/http-loader";
|
||||||
import { UnauthorizedInterceptor } from "./auth/unauthorized.interceptor";
|
import { UnauthorizedInterceptor } from "./auth/unauthorized.interceptor";
|
||||||
import { environment } from "../environments/environment";
|
import { environment } from "../environments/environment";
|
||||||
|
import { MatPaginatorIntl } from "@angular/material/paginator";
|
||||||
|
import { TranslateService } from "@ngx-translate/core";
|
||||||
|
import { MatPaginatorI18n } from "./localization/MatPaginatorI18n";
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{ path: "*", component: PageNotFoundComponent },
|
{ path: "*", component: PageNotFoundComponent },
|
||||||
|
@ -212,6 +215,10 @@ export function JwtTokenGetter() {
|
||||||
useClass: UnauthorizedInterceptor,
|
useClass: UnauthorizedInterceptor,
|
||||||
multi: true
|
multi: true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: MatPaginatorIntl, deps: [TranslateService],
|
||||||
|
useFactory: (translateService: TranslateService) => new MatPaginatorI18n(translateService).getPaginatorIntl()
|
||||||
|
},
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent],
|
bootstrap: [AppComponent],
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<div class="small-middle-container" *ngIf="actorCredits">
|
<div class="small-middle-container">
|
||||||
|
|
||||||
<div *ngIf="loadingFlag" class="row justify-content-md-center top-space loading-spinner">
|
<div *ngIf="loadingFlag" class="row justify-content-md-center top-space loading-spinner">
|
||||||
<mat-spinner [color]="'accent'"></mat-spinner>
|
<mat-spinner [color]="'accent'"></mat-spinner>
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
import { SearchV2Service } from "../../../services";
|
import { SearchV2Service } from "../../../services";
|
||||||
import { IActorCredits } from "../../../interfaces/ISearchTvResultV2";
|
import { IActorCredits, IActorCast } from "../../../interfaces/ISearchTvResultV2";
|
||||||
import { IDiscoverCardResult } from "../../interfaces";
|
import { IDiscoverCardResult } from "../../interfaces";
|
||||||
import { RequestType } from "../../../interfaces";
|
import { RequestType } from "../../../interfaces";
|
||||||
import { AuthService } from "../../../auth/auth.service";
|
import { AuthService } from "../../../auth/auth.service";
|
||||||
|
import { forkJoin } from "rxjs";
|
||||||
|
import { isEqual } from "lodash";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: "./discover-actor.component.html",
|
templateUrl: "./discover-actor.component.html",
|
||||||
|
@ -12,7 +14,6 @@ import { AuthService } from "../../../auth/auth.service";
|
||||||
})
|
})
|
||||||
export class DiscoverActorComponent {
|
export class DiscoverActorComponent {
|
||||||
public actorId: number;
|
public actorId: number;
|
||||||
public actorCredits: IActorCredits;
|
|
||||||
public loadingFlag: boolean;
|
public loadingFlag: boolean;
|
||||||
public isAdmin: boolean;
|
public isAdmin: boolean;
|
||||||
|
|
||||||
|
@ -24,24 +25,32 @@ export class DiscoverActorComponent {
|
||||||
this.route.params.subscribe((params: any) => {
|
this.route.params.subscribe((params: any) => {
|
||||||
this.actorId = params.actorId;
|
this.actorId = params.actorId;
|
||||||
this.isAdmin = this.auth.isAdmin();
|
this.isAdmin = this.auth.isAdmin();
|
||||||
this.loading();
|
this.search();
|
||||||
this.searchService.getMoviesByActor(this.actorId).subscribe(res => {
|
|
||||||
this.actorCredits = res;
|
|
||||||
this.createModel();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private createModel() {
|
private search() {
|
||||||
this.finishLoading();
|
|
||||||
this.discoverResults = [];
|
this.discoverResults = [];
|
||||||
this.actorCredits.cast.forEach(m => {
|
this.loading();
|
||||||
|
|
||||||
|
forkJoin([
|
||||||
|
this.searchService.getMoviesByActor(this.actorId),
|
||||||
|
this.searchService.getTvByActor(this.actorId)
|
||||||
|
]).subscribe(([movie, tv]) => {
|
||||||
|
this.pushDiscoverResults(movie.cast, RequestType.movie);
|
||||||
|
this.pushDiscoverResults(tv.cast, RequestType.tvShow);
|
||||||
|
this.finishLoading();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pushDiscoverResults(cast: IActorCast[], type: RequestType) {
|
||||||
|
cast.forEach(m => {
|
||||||
this.discoverResults.push({
|
this.discoverResults.push({
|
||||||
available: false,
|
available: false,
|
||||||
posterPath: m.poster_path ? `https://image.tmdb.org/t/p/w300/${m.poster_path}` : "../../../images/default_movie_poster.png",
|
posterPath: m.poster_path ? `https://image.tmdb.org/t/p/w300/${m.poster_path}` : "../../../images/default_movie_poster.png",
|
||||||
requested: false,
|
requested: false,
|
||||||
title: m.title,
|
title: m.title,
|
||||||
type: RequestType.movie,
|
type: type,
|
||||||
id: m.id,
|
id: m.id,
|
||||||
url: null,
|
url: null,
|
||||||
rating: 0,
|
rating: 0,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: "<h2>Page not found</h2>",
|
template: "<h2>{{ 'ErrorPages.NotFound' | translate }}</h2>",
|
||||||
})
|
})
|
||||||
export class PageNotFoundComponent { }
|
export class PageNotFoundComponent { }
|
||||||
|
|
|
@ -121,6 +121,7 @@ export interface IMassEmailModel {
|
||||||
subject: string;
|
subject: string;
|
||||||
body: string;
|
body: string;
|
||||||
users: IUser[];
|
users: IUser[];
|
||||||
|
bcc: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface INotificationPreferences {
|
export interface INotificationPreferences {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="container top-spacing" *ngIf="details">
|
<div class="container top-spacing" *ngIf="details">
|
||||||
|
|
||||||
<h1>Issues for {{details.title}}</h1>
|
<h1>{{ 'Issues.IssuesForTitle' | translate: { title: details.title} }}</h1>
|
||||||
<div>
|
<div>
|
||||||
<span>{{'Issues.Requested' | translate}}
|
<span>{{'Issues.Requested' | translate}}
|
||||||
<i *ngIf="!hasRequest" class="far fa-times-circle"></i>
|
<i *ngIf="!hasRequest" class="far fa-times-circle"></i>
|
||||||
|
|
34
src/Ombi/ClientApp/src/app/localization/MatPaginatorI18n.ts
Normal file
34
src/Ombi/ClientApp/src/app/localization/MatPaginatorI18n.ts
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import { MatPaginatorIntl } from '@angular/material/paginator';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
export class MatPaginatorI18n {
|
||||||
|
|
||||||
|
constructor(private translate: TranslateService) { }
|
||||||
|
|
||||||
|
getPaginatorIntl(): MatPaginatorIntl {
|
||||||
|
const paginatorIntl = new MatPaginatorIntl();
|
||||||
|
paginatorIntl.itemsPerPageLabel = this.translate.instant('Paginator.itemsPerPageLabel');
|
||||||
|
paginatorIntl.nextPageLabel = this.translate.instant('Paginator.nextPageLabel');
|
||||||
|
paginatorIntl.previousPageLabel = this.translate.instant('Paginator.previousPageLabel');
|
||||||
|
paginatorIntl.firstPageLabel = this.translate.instant('Paginator.firstPageLabel');
|
||||||
|
paginatorIntl.lastPageLabel = this.translate.instant('Paginator.lastPageLabel');
|
||||||
|
paginatorIntl.getRangeLabel = this.getRangeLabel.bind(this);
|
||||||
|
return paginatorIntl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getRangeLabel(page: number, pageSize: number, length: number): string {
|
||||||
|
if (length == 0 || pageSize == 0) {
|
||||||
|
return this.translate.instant('Paginator.rangePageLabel1', { length });
|
||||||
|
}
|
||||||
|
|
||||||
|
length = Math.max(length, 0);
|
||||||
|
|
||||||
|
const startIndex = page * pageSize;
|
||||||
|
|
||||||
|
// If the start index exceeds the list length, do not try and fix the end index to the end.
|
||||||
|
const endIndex =
|
||||||
|
startIndex < length ? Math.min(startIndex + pageSize, length) : startIndex + pageSize;
|
||||||
|
|
||||||
|
return this.translate.instant('Paginator.rangePageLabel2', { startIndex: startIndex + 1, endIndex, length });
|
||||||
|
}
|
||||||
|
}
|
|
@ -143,7 +143,7 @@
|
||||||
<div class="row" *ngIf="movie.videos?.results?.length > 0">
|
<div class="row" *ngIf="movie.videos?.results?.length > 0">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<mat-card class="mat-elevation-z8">
|
<mat-card class="mat-elevation-z8">
|
||||||
<mat-card-header>Trailers</mat-card-header>
|
<mat-card-header>{{'MediaDetails.Trailers' | translate}}</mat-card-header>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<p-carousel class="no-indicator" [numVisible]="2" [numScroll]="10" [page]="0" [value]="movie.videos?.results">
|
<p-carousel class="no-indicator" [numVisible]="2" [numScroll]="10" [page]="0" [value]="movie.videos?.results">
|
||||||
<ng-template let-result pTemplate="item">
|
<ng-template let-result pTemplate="item">
|
||||||
|
|
|
@ -104,7 +104,7 @@
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
<div class="genre-button-container" *ngIf="movie.genres">
|
<div class="genre-button-container" *ngIf="movie.genres">
|
||||||
<span class="label">{{'MediaDetails.Genres' | translate }}</span>
|
<span class="label">{{'MediaDetails.GenresLabel' | translate }}</span>
|
||||||
<div>
|
<div>
|
||||||
<mat-chip-list>
|
<mat-chip-list>
|
||||||
<mat-chip selected *ngFor="let genre of movie.genres">
|
<mat-chip selected *ngFor="let genre of movie.genres">
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
|
|
||||||
|
|
||||||
<div class="genre-button-container" *ngIf="tv.genres">
|
<div class="genre-button-container" *ngIf="tv.genres">
|
||||||
<span class="label">{{'MediaDetails.Genres' | translate }}</span>
|
<span class="label">{{'MediaDetails.GenresLabel' | translate }}</span>
|
||||||
<div>
|
<div>
|
||||||
<mat-chip-list>
|
<mat-chip-list>
|
||||||
<mat-chip selected *ngFor="let genre of tv.genres">
|
<mat-chip selected *ngFor="let genre of tv.genres">
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
<div class="keyword-button-container" *ngIf="tv?.keywords?.keywordsValue?.length > 0">
|
<div class="keyword-button-container" *ngIf="tv?.keywords?.keywordsValue?.length > 0">
|
||||||
<span class="label">{{'MediaDetails.Keywords' | translate }}:</span>
|
<span class="label">{{'MediaDetails.Keywords' | translate }}</span>
|
||||||
<mat-chip-list>
|
<mat-chip-list>
|
||||||
<mat-chip selected *ngFor="let keyword of tv.keywords.keywordsValue">
|
<mat-chip selected *ngFor="let keyword of tv.keywords.keywordsValue">
|
||||||
{{keyword.name}}
|
{{keyword.name}}
|
||||||
|
|
|
@ -5,8 +5,9 @@
|
||||||
<div> {{ request.requestStatus | translate }}</div>
|
<div> {{ request.requestStatus | translate }}</div>
|
||||||
</mat-panel-title>
|
</mat-panel-title>
|
||||||
<mat-panel-description>
|
<mat-panel-description>
|
||||||
{{'Requests.RequestedBy' | translate}} '{{request.requestedUser.userAlias}}' on
|
{{'Requests.RequestedByOn' | translate: {
|
||||||
{{request.requestedDate | amLocal | amUserLocale | amDateFormat: 'LL' }}
|
user: request.requestedUser.userAlias,
|
||||||
|
date: request.requestedDate | amLocal | amUserLocale | amDateFormat: 'LL' } }}
|
||||||
<span *ngIf="request.denied"> - {{request.deniedReason}}</span>
|
<span *ngIf="request.denied"> - {{request.deniedReason}}</span>
|
||||||
</mat-panel-description>
|
</mat-panel-description>
|
||||||
</mat-expansion-panel-header>
|
</mat-expansion-panel-header>
|
||||||
|
|
|
@ -323,8 +323,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.media-row .mat-raised-button{
|
.media-row .mat-raised-button{
|
||||||
padding:2px 1.5em;;
|
padding:2px 1.5em;
|
||||||
width:170px;
|
|
||||||
margin-top:10px;
|
margin-top:10px;
|
||||||
margin-left:10px;
|
margin-left:10px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
<th mat-header-cell *matHeaderCellDef> </th>
|
<th mat-header-cell *matHeaderCellDef> </th>
|
||||||
<td mat-cell *matCellDef="let element">
|
<td mat-cell *matCellDef="let element">
|
||||||
<button mat-raised-button color="accent" [routerLink]="'/details/artist/' + element.foreignArtistId">{{ 'Requests.Details' | translate}}</button>
|
<button mat-raised-button color="accent" [routerLink]="'/details/artist/' + element.foreignArtistId">{{ 'Requests.Details' | translate}}</button>
|
||||||
<button mat-raised-button color="warn" (click)="openOptions(element)" *ngIf="isAdmin"> {{ 'Requests.Options' | translate}}</button>
|
<button mat-raised-button color="warn" (click)="openOptions(element)" *ngIf="isAdmin || ( manageOwnRequests && element.requestedUser?.userName == userName )"> {{ 'Requests.Options' | translate}}</button>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,8 @@ export class AlbumsGridComponent implements OnInit, AfterViewInit {
|
||||||
public defaultSort: string = "requestedDate";
|
public defaultSort: string = "requestedDate";
|
||||||
public defaultOrder: string = "desc";
|
public defaultOrder: string = "desc";
|
||||||
public currentFilter: RequestFilterType = RequestFilterType.All;
|
public currentFilter: RequestFilterType = RequestFilterType.All;
|
||||||
|
public manageOwnRequests: boolean;
|
||||||
|
public userName: string;
|
||||||
|
|
||||||
public RequestFilter = RequestFilterType;
|
public RequestFilter = RequestFilterType;
|
||||||
|
|
||||||
|
@ -42,10 +44,12 @@ export class AlbumsGridComponent implements OnInit, AfterViewInit {
|
||||||
constructor(private requestService: RequestServiceV2, private ref: ChangeDetectorRef,
|
constructor(private requestService: RequestServiceV2, private ref: ChangeDetectorRef,
|
||||||
private auth: AuthService, private storageService: StorageService) {
|
private auth: AuthService, private storageService: StorageService) {
|
||||||
|
|
||||||
|
this.userName = auth.claims().name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngOnInit() {
|
public ngOnInit() {
|
||||||
this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser");
|
this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser");
|
||||||
|
this.manageOwnRequests = this.auth.hasRole("ManageOwnRequests")
|
||||||
|
|
||||||
const defaultCount = this.storageService.get(this.storageKeyGridCount);
|
const defaultCount = this.storageService.get(this.storageKeyGridCount);
|
||||||
const defaultSort = this.storageService.get(this.storageKey);
|
const defaultSort = this.storageService.get(this.storageKey);
|
||||||
|
@ -117,16 +121,17 @@ export class AlbumsGridComponent implements OnInit, AfterViewInit {
|
||||||
|
|
||||||
public openOptions(request: IAlbumRequest) {
|
public openOptions(request: IAlbumRequest) {
|
||||||
const filter = () => {
|
const filter = () => {
|
||||||
this.dataSource = this.dataSource.filter((req) => {
|
this.dataSource = this.dataSource.filter((req) => {
|
||||||
return req.id !== request.id;
|
return req.id !== request.id;
|
||||||
})
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const onChange = () => {
|
const onChange = () => {
|
||||||
this.ref.detectChanges();
|
this.ref.detectChanges();
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onOpenOptions.emit({ request: request, filter: filter, onChange: onChange });
|
const data = { request: request, filter: filter, onChange: onChange, manageOwnRequests: this.manageOwnRequests, isAdmin: this.isAdmin };
|
||||||
|
this.onOpenOptions.emit(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public switchFilter(type: RequestFilterType) {
|
public switchFilter(type: RequestFilterType) {
|
||||||
|
|
|
@ -76,7 +76,7 @@
|
||||||
<th mat-header-cell *matHeaderCellDef> </th>
|
<th mat-header-cell *matHeaderCellDef> </th>
|
||||||
<td mat-cell *matCellDef="let element">
|
<td mat-cell *matCellDef="let element">
|
||||||
<button id="detailsButton{{element.id}}" mat-raised-button color="accent" [routerLink]="'/details/movie/' + element.theMovieDbId">{{ 'Requests.Details' | translate}}</button>
|
<button id="detailsButton{{element.id}}" mat-raised-button color="accent" [routerLink]="'/details/movie/' + element.theMovieDbId">{{ 'Requests.Details' | translate}}</button>
|
||||||
<button id="optionsButton{{element.id}}" mat-raised-button color="warn" (click)="openOptions(element)" *ngIf="isAdmin || manageOwnRequests"> {{ 'Requests.Options' | translate}}</button>
|
<button id="optionsButton{{element.id}}" mat-raised-button color="warn" (click)="openOptions(element)" *ngIf="isAdmin || ( manageOwnRequests && element.requestedUser?.userName == userName ) "> {{ 'Requests.Options' | translate}}</button>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ export class MoviesGridComponent implements OnInit, AfterViewInit {
|
||||||
public defaultOrder: string = "desc";
|
public defaultOrder: string = "desc";
|
||||||
public currentFilter: RequestFilterType = RequestFilterType.All;
|
public currentFilter: RequestFilterType = RequestFilterType.All;
|
||||||
public selection = new SelectionModel<IMovieRequests>(true, []);
|
public selection = new SelectionModel<IMovieRequests>(true, []);
|
||||||
|
public userName: string;
|
||||||
|
|
||||||
public RequestFilter = RequestFilterType;
|
public RequestFilter = RequestFilterType;
|
||||||
|
|
||||||
|
@ -46,10 +47,11 @@ export class MoviesGridComponent implements OnInit, AfterViewInit {
|
||||||
@ViewChild(MatSort) sort: MatSort;
|
@ViewChild(MatSort) sort: MatSort;
|
||||||
|
|
||||||
constructor(private requestService: RequestServiceV2, private ref: ChangeDetectorRef,
|
constructor(private requestService: RequestServiceV2, private ref: ChangeDetectorRef,
|
||||||
private auth: AuthService, private storageService: StorageService,
|
private auth: AuthService, private storageService: StorageService,
|
||||||
private requestServiceV1: RequestService, private notification: NotificationService,
|
private requestServiceV1: RequestService, private notification: NotificationService,
|
||||||
private translateService: TranslateService) {
|
private translateService: TranslateService) {
|
||||||
|
|
||||||
|
this.userName = auth.claims().name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngOnInit() {
|
public ngOnInit() {
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject } from '@angular/core';
|
||||||
import { MAT_BOTTOM_SHEET_DATA, MatBottomSheetRef } from '@angular/material/bottom-sheet';
|
import { MAT_BOTTOM_SHEET_DATA, MatBottomSheetRef } from '@angular/material/bottom-sheet';
|
||||||
import { RequestService } from '../../../services';
|
import { MessageService, RequestService } from '../../../services';
|
||||||
import { RequestType } from '../../../interfaces';
|
import { IRequestEngineResult, RequestType } from '../../../interfaces';
|
||||||
import { UpdateType } from '../../models/UpdateType';
|
import { UpdateType } from '../../models/UpdateType';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'request-options',
|
selector: 'request-options',
|
||||||
|
@ -13,21 +15,31 @@ export class RequestOptionsComponent {
|
||||||
public RequestType = RequestType;
|
public RequestType = RequestType;
|
||||||
|
|
||||||
constructor(@Inject(MAT_BOTTOM_SHEET_DATA) public data: any,
|
constructor(@Inject(MAT_BOTTOM_SHEET_DATA) public data: any,
|
||||||
private requestService: RequestService, private bottomSheetRef: MatBottomSheetRef<RequestOptionsComponent>) { }
|
private requestService: RequestService,
|
||||||
|
private messageService: MessageService,
|
||||||
|
private bottomSheetRef: MatBottomSheetRef<RequestOptionsComponent>,
|
||||||
|
private translate: TranslateService) { }
|
||||||
|
|
||||||
public async delete() {
|
public async delete() {
|
||||||
|
var request: Observable<IRequestEngineResult>;
|
||||||
if (this.data.type === RequestType.movie) {
|
if (this.data.type === RequestType.movie) {
|
||||||
await this.requestService.removeMovieRequestAsync(this.data.id);
|
request = this.requestService.removeMovieRequestAsync(this.data.id);
|
||||||
}
|
}
|
||||||
if (this.data.type === RequestType.tvShow) {
|
if (this.data.type === RequestType.tvShow) {
|
||||||
await this.requestService.deleteChild(this.data.id).toPromise();
|
request = this.requestService.deleteChild(this.data.id);
|
||||||
}
|
}
|
||||||
if (this.data.type === RequestType.album) {
|
if (this.data.type === RequestType.album) {
|
||||||
await this.requestService.removeAlbumRequest(this.data.id).toPromise();
|
request = this.requestService.removeAlbumRequest(this.data.id);
|
||||||
}
|
}
|
||||||
|
request.subscribe(result => {
|
||||||
this.bottomSheetRef.dismiss({type: UpdateType.Delete});
|
if (result.result) {
|
||||||
return;
|
this.messageService.send(this.translate.instant("Requests.SuccessfullyDeleted"));
|
||||||
|
this.bottomSheetRef.dismiss({type: UpdateType.Delete});
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
this.messageService.sendRequestEngineResultError(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async approve() {
|
public async approve() {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" id="search" class="form-control form-control-custom searchwidth" placeholder="Search"
|
<input type="text" id="search" class="form-control form-control-custom searchwidth" [placeholder]="'Search.Search' | translate"
|
||||||
(keyup)="search($event)">
|
(keyup)="search($event)">
|
||||||
<span class="input-group-btn">
|
<span class="input-group-btn">
|
||||||
<button id="filterBtn" class="btn btn-sm btn-info-outline" (click)="filterDisplay = !filterDisplay">
|
<button id="filterBtn" class="btn btn-sm btn-info-outline" (click)="filterDisplay = !filterDisplay">
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" id="search" class="form-control form-control-custom searchwidth" placeholder="Search"
|
<input type="text" id="search" class="form-control form-control-custom searchwidth" [placeholder]="'Search.Search' | translate"
|
||||||
(keyup)="search($event)">
|
(keyup)="search($event)">
|
||||||
<span class="input-group-btn">
|
<span class="input-group-btn">
|
||||||
<button id="filterBtn" class="btn btn-sm btn-info-outline" (click)="filterDisplay = !filterDisplay">
|
<button id="filterBtn" class="btn btn-sm btn-info-outline" (click)="filterDisplay = !filterDisplay">
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div>
|
<div>
|
||||||
<input type="text" id="search" class="form-control form-control-custom" placeholder="Search" (keyup)="search($event)">
|
<input type="text" id="search" class="form-control form-control-custom" [placeholder]="'Common.Search' | translate" (keyup)="search($event)">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
|
|
|
@ -73,8 +73,8 @@ export class RequestService extends ServiceHelpers {
|
||||||
this.http.delete(`${this.url}movie/${requestId}`, {headers: this.headers}).subscribe();
|
this.http.delete(`${this.url}movie/${requestId}`, {headers: this.headers}).subscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeMovieRequestAsync(requestId: number) {
|
public removeMovieRequestAsync(requestId: number): Observable<IRequestEngineResult> {
|
||||||
return this.http.delete(`${this.url}movie/${requestId}`, {headers: this.headers}).toPromise();
|
return this.http.delete<IRequestEngineResult>(`${this.url}movie/${requestId}`, {headers: this.headers});
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateMovieRequest(request: IMovieRequests): Observable<IMovieRequests> {
|
public updateMovieRequest(request: IMovieRequests): Observable<IMovieRequests> {
|
||||||
|
@ -128,8 +128,9 @@ export class RequestService extends ServiceHelpers {
|
||||||
public approveChild(child: ITvUpdateModel): Observable<IRequestEngineResult> {
|
public approveChild(child: ITvUpdateModel): Observable<IRequestEngineResult> {
|
||||||
return this.http.post<IRequestEngineResult>(`${this.url}tv/approve`, JSON.stringify(child), {headers: this.headers});
|
return this.http.post<IRequestEngineResult>(`${this.url}tv/approve`, JSON.stringify(child), {headers: this.headers});
|
||||||
}
|
}
|
||||||
public deleteChild(childId: number): Observable<boolean> {
|
|
||||||
return this.http.delete<boolean>(`${this.url}tv/child/${childId}`, {headers: this.headers});
|
public deleteChild(childId: number): Observable<IRequestEngineResult> {
|
||||||
|
return this.http.delete<IRequestEngineResult>(`${this.url}tv/child/${childId}`, {headers: this.headers});
|
||||||
}
|
}
|
||||||
|
|
||||||
public subscribeToMovie(requestId: number): Observable<boolean> {
|
public subscribeToMovie(requestId: number): Observable<boolean> {
|
||||||
|
@ -184,7 +185,7 @@ export class RequestService extends ServiceHelpers {
|
||||||
return this.http.get<IAlbumRequest[]>(`${this.url}music/search/${search}`, {headers: this.headers});
|
return this.http.get<IAlbumRequest[]>(`${this.url}music/search/${search}`, {headers: this.headers});
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeAlbumRequest(request: number): any {
|
public removeAlbumRequest(request: number): Observable<IRequestEngineResult> {
|
||||||
return this.http.delete(`${this.url}music/${request}`, {headers: this.headers});
|
return this.http.delete<IRequestEngineResult>(`${this.url}music/${request}`, {headers: this.headers});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
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