mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-22 14:13:36 -07:00
Compare commits
503 commits
Author | SHA1 | Date | |
---|---|---|---|
|
b72f47470c | ||
|
72d4115378 |
||
|
11fd7a5fc8 |
||
|
d2be48a921 | ||
|
a92c76021a | ||
|
97d5167db6 | ||
|
2519cca9f6 | ||
|
cfeee39978 | ||
|
cee40146ee | ||
|
1eff48e58e | ||
|
3b2a0d84be | ||
|
ed5bc3f873 | ||
|
067c029f42 | ||
|
cfe2b6ac0f | ||
|
c9ab4f4f9f | ||
|
acb679f99d | ||
|
f88c5ad818 | ||
|
b3e8ca6950 |
||
|
15a97794f6 | ||
|
ba6e708e18 | ||
|
08c9017a2c | ||
|
f8658fe6d5 | ||
|
7303e7da3b | ||
|
ffb495019f | ||
|
13c1544476 | ||
|
04ddf3d09b | ||
|
ea0b690c18 |
||
|
dae0fe6be4 | ||
|
dbbfdd926f | ||
|
cb6d441ccd | ||
|
6344ae98cd | ||
|
0dfd4533db | ||
|
6e539585f1 | ||
|
cf0c1614a4 | ||
|
2868314a34 | ||
|
3eef2fafee |
||
|
9227bc0b4c |
||
|
fe2fe24158 | ||
|
a801cfdb09 | ||
|
72af4f734d | ||
|
fc94fcfe68 |
||
|
6df9d6e1d2 | ||
|
fefc768aa5 |
||
|
b00e3878a7 | ||
|
cc98fc6aca |
||
|
e8ca519ef9 | ||
|
579d048ba1 | ||
|
cd260ed844 | ||
|
dc2b958915 |
||
|
3234204221 | ||
|
138df1eb25 | ||
|
53a6a092b1 | ||
|
da6665deb6 | ||
|
fcb4082731 |
||
|
3fd722395a | ||
|
7b0db11336 | ||
|
029ea79192 | ||
|
2009fb743e |
||
|
7b7ebf9767 | ||
|
3b1395e6f5 | ||
|
dd9892fc1f | ||
|
b24f6084e0 | ||
|
4eef0e6e21 | ||
|
0fb29a0b16 | ||
|
938a0b74aa | ||
|
0af3511e81 | ||
|
fc1ad67246 | ||
|
e1f2a84806 |
||
|
a84d26e8a3 | ||
|
48d3dec26d |
||
|
3bd98c1d71 |
||
|
9c21074189 |
||
|
7654fba9b5 | ||
|
ea00d6c12f | ||
|
43b55d9940 | ||
|
d9787dc32a | ||
|
be886eed3c | ||
|
061132f897 | ||
|
a7e0c8cb1d |
||
|
ae5844c27e |
||
|
9975fa42de |
||
|
51721bed2b |
||
|
9e8171a794 | ||
|
1e3bd6377c |
||
|
69929f1a8c |
||
|
3608322d60 |
||
|
ff85d54800 |
||
|
a1c20e951b |
||
|
d43c72f35a |
||
|
c792e614c1 |
||
|
100bfe3384 |
||
|
5dce9abb11 |
||
|
07e798df2f | ||
|
061ed3c4b5 | ||
|
f8c61027bf |
||
|
8ff7d9995d | ||
|
60c4ddd92d | ||
|
0db5928600 |
||
|
0a538195c9 | ||
|
cad00efab6 | ||
|
38f7ced860 |
||
|
af8b519b46 | ||
|
f3a6ccb4cf |
||
|
7e3ef3c76b |
||
|
16ff00145f |
||
|
a1083f67c7 |
||
|
8e3cad09b5 | ||
|
d0bbdc4e7d | ||
|
9c3cb42c29 | ||
|
bade1d6354 | ||
|
6b49d9bc71 | ||
|
ee3bf10421 | ||
|
71c86a8db9 |
||
|
5cbb2ca528 | ||
|
43fe449e32 |
||
|
6d6890d0dd | ||
|
617f26b332 |
||
|
adfbc845a2 |
||
|
a27b459247 |
||
|
460fa39bb9 |
||
|
955a742fae |
||
|
2c8fe8087a |
||
|
5017e38f87 |
||
|
71df058865 |
||
|
af6a986771 |
||
|
94eb26f5fd | ||
|
f12ef99021 | ||
|
28f1998889 | ||
|
08eb13b788 | ||
|
5ca7a009ba | ||
|
3f1a336c3d | ||
|
530cc8d610 |
||
|
62b9a1f65f | ||
|
d0744ce87b | ||
|
54d90a7d2b | ||
|
57e7830f8e | ||
|
18c3b314d6 | ||
|
835b0878f6 | ||
|
bdb0f8e58c |
||
|
11edac961b |
||
|
9e28879fc1 |
||
|
87796102c6 |
||
|
3f3437598d | ||
|
a77d939c56 |
||
|
32da949a95 | ||
|
7bc915cc14 |
||
|
ed06c22fb2 |
||
|
7e1e254cfe |
||
|
aa3cb9a8a5 | ||
|
c5c8dda7e4 |
||
|
291425e609 |
||
|
1261a446e7 |
||
|
9c2e1b4353 |
||
|
40ee175ccd |
||
|
f703ff255c |
||
|
563a0443ea |
||
|
19e0a886ce |
||
|
500b65ea7e | ||
|
163185de35 | ||
|
34c32f8338 | ||
|
880e511f2b | ||
|
c8ad12eb5f | ||
|
f9738cff3e | ||
|
2f2d35ec86 |
||
|
aacaa3e140 |
||
|
763b64d49f | ||
|
895b9bf6a0 | ||
|
a34a4f7f78 | ||
|
ac05495425 |
||
|
cf9aadaa52 | ||
|
4e80e7b7c3 |
||
|
7789d6c94f |
||
|
a15ed58b1d | ||
|
d464b9aa20 | ||
|
5bc87b3972 |
||
|
3c3edf6273 |
||
|
f2552ef6ed |
||
|
37f65648a2 |
||
|
93969b5a2d |
||
|
2de9b9ba80 |
||
|
6e8cabad17 |
||
|
7facf43c29 | ||
|
826eeec0a8 | ||
|
fb836b502c | ||
|
8a24b56299 |
||
|
21bfc5a45a |
||
|
5f60950802 |
||
|
6025c5ed75 |
||
|
84454e53c0 |
||
|
8584ad4605 |
||
|
23a4fede69 |
||
|
a0201e3f58 |
||
|
dc619e80ba |
||
|
a47171aa08 |
||
|
3e46e8e91b |
||
|
d60a2e1500 | ||
|
1f37de0888 |
||
|
151efe19d0 |
||
|
67a710e5a4 | ||
|
cd60291d8d | ||
|
90b934a369 |
||
|
f4af21bc92 | ||
|
79cef7e0f8 |
||
|
60c1990959 | ||
|
c528993962 | ||
|
138f18bd9e | ||
|
82c7f1c44f |
||
|
9424586e9c |
||
|
ac5b377c67 |
||
|
e261f2a6c2 |
||
|
01b71b0752 | ||
|
b8a8f029d8 |
||
|
f94e8ab153 | ||
|
ae82243ad6 | ||
|
bb6deddfae |
||
|
91e65174a9 |
||
|
b5a98e3de6 | ||
|
7e9c8bec6b |
||
|
9aedb8c6ba | ||
|
d745b64fa4 | ||
|
969bc7bb25 | ||
|
9cfb10bb1e |
||
|
06b46ec1d4 | ||
|
d240d2dfcc | ||
|
9ff624ce46 |
||
|
f3c3ae1e3d | ||
|
226796d913 | ||
|
0e5e0adf86 | ||
|
a3b8b538a4 | ||
|
aeb3cae51c | ||
|
506f60773b |
||
|
c8dab6b334 |
||
|
025228ebb1 | ||
|
97cc42ffa8 |
||
|
ca947bd302 | ||
|
588bdffbb4 | ||
|
b087d606ff | ||
|
c817be810a | ||
|
faf65533f8 | ||
|
18374198f9 |
||
|
a70e9403c7 | ||
|
5f6eab09f9 | ||
|
1751305064 | ||
|
58ec6a3867 | ||
|
78f340ee5f |
||
|
540f14b735 | ||
|
de4baade9f | ||
|
e1adb07b70 | ||
|
a595f6c2fd | ||
|
80884bcd72 | ||
|
0a3a9b11e4 | ||
|
0069bfdf54 |
||
|
1e87f20104 |
||
|
bdc0214e1f | ||
|
f818f81412 | ||
|
141f96da5e |
||
|
c262b7c22b | ||
|
a7f8b25793 | ||
|
7bb8becfb1 | ||
|
d9dbf7ca91 | ||
|
12444871df |
||
|
e75c3088d4 | ||
|
bd2c2d3901 | ||
|
29dc84e819 | ||
|
0716f48c3e | ||
|
c98f82cca2 | ||
|
b5f694f867 | ||
|
fcd78fee61 | ||
|
605e746fce |
||
|
83aacf0c25 |
||
|
622f77eef2 | ||
|
382c19500f | ||
|
cf0df66772 | ||
|
24db462aab | ||
|
cd4895c0b1 | ||
|
4098da305a | ||
|
86d9837ba2 | ||
|
353de981a4 |
||
|
c08805494c | ||
|
aca4ee3791 | ||
|
473423719c | ||
|
4a50a00d47 |
||
|
b55cad0dbb | ||
|
887a7fc0ec | ||
|
e05333e7aa |
||
|
5123a76954 | ||
|
8eda250367 | ||
|
854d1c0660 | ||
|
46ce254f40 | ||
|
f229d88bd7 |
||
|
fed035ab54 | ||
|
12e8559e86 | ||
|
67fb9921c0 | ||
|
62272367b8 | ||
|
f162feeea5 | ||
|
8cd556e268 | ||
|
8cf066f084 | ||
|
e6c9ce5ad0 |
||
|
a59455eb17 | ||
|
a2cc23b351 |
||
|
805011f5f0 | ||
|
6fa506491f |
||
|
c1271572f1 |
||
|
7486275d1a | ||
|
e98f71f8ff |
||
|
fd1b2ba2ab | ||
|
10701c4a0b | ||
|
a6274bc38d | ||
|
4816acf6f9 |
||
|
1e0b355731 | ||
|
f62e70fc49 | ||
|
0e8940d79c | ||
|
37655aff9d |
||
|
5ad6ea3d70 | ||
|
187b18d5c0 | ||
|
41f0b61518 | ||
|
1b8c47f316 |
||
|
46920032ba |
||
|
51c7c48b66 | ||
|
ecfbb8eda9 |
||
|
3e23d36ac3 | ||
|
1d5fabd317 |
||
|
40843fd6ac | ||
|
bcb3e7f003 |
||
|
987ec5a18c |
||
|
c614e0ca5f |
||
|
29aa0c1761 | ||
|
867645aa59 | ||
|
3b56ae904a | ||
|
17ba2020ee | ||
|
a4fdfd2303 | ||
|
217367047d | ||
|
a40ab5cddf |
||
|
b6e2a9c8a3 | ||
|
ac50730629 | ||
|
031e2b9283 |
||
|
76a0d0d268 |
||
|
b4a14c2d28 |
||
|
b01f6ddec2 | ||
|
fc1ebf949a | ||
|
3e5158ef9c | ||
|
55855c5add |
||
|
5446406cf2 |
||
|
d9eff39840 |
||
|
29831a338c | ||
|
fa65712bd5 |
||
|
dc98613bb4 |
||
|
9ba50982b0 | ||
|
9fe7ec115e |
||
|
9167bd32b4 | ||
|
2e6f35f89a |
||
|
33d6704789 | ||
|
061c771b77 | ||
|
fc14780bd3 | ||
|
e52037e4c9 | ||
|
4013693c30 | ||
|
8c9ad9b414 | ||
|
86edff5689 | ||
|
e4f6244ad2 | ||
|
9fb8af7e09 | ||
|
5a538faf64 | ||
|
28e248046a | ||
|
7ea7d58cb8 |
||
|
092cdee81d | ||
|
2cddec7590 |
||
|
0f12b01325 |
||
|
89805dcd96 | ||
|
66b05e5a85 | ||
|
386736fa7f | ||
|
ff04d87534 |
||
|
b0b1764f38 | ||
|
66aa101019 |
||
|
29fb614efd | ||
|
369eb33917 |
||
|
bce6f4c2f3 | ||
|
a7da7b7a8b | ||
|
47ea64b5a4 |
||
|
c222f1a945 |
||
|
15fe04d4a6 | ||
|
00e25f12e8 |
||
|
1d53261382 |
||
|
2f5d54c5bf | ||
|
d661f32e8a |
||
|
65f26812be | ||
|
47ab7e5b68 | ||
|
72769df5e4 |
||
|
3731c588d5 |
||
|
bf65c76ff9 |
||
|
8b8ec4340d | ||
|
44d38fbaae |
||
|
26ac75f0c2 |
||
|
f044a4325a | ||
|
b07faaef3c | ||
|
3ba4ec33f6 | ||
|
fcc1eaaa37 |
||
|
f102dcf751 |
||
|
aa532457f2 |
||
|
ff142b09ab |
||
|
6f40ab07e4 |
||
|
2edc67bb58 |
||
|
d5e85ffdac |
||
|
dd48149ad9 | ||
|
64dce3010e | ||
|
7fd9178f53 |
||
|
875da959f3 |
||
|
f8adb5de85 |
||
|
c3284bc70a | ||
|
81ddc8553b |
||
|
9dcf1bb59a | ||
|
f22d3da765 |
||
|
1fe7e9dda2 |
||
|
2849e02684 | ||
|
898bc89fa7 |
||
|
e00e39a1be | ||
|
6d423b5447 |
||
|
c08156ca32 |
||
|
c8090b4e93 | ||
|
3f1f35df31 | ||
|
96b79cc361 | ||
|
9a73463766 |
||
|
4d1ba5e82a | ||
|
b9d55a469b |
||
|
a9f7980942 | ||
|
f877921914 | ||
|
20bbe92114 | ||
|
f858c88433 | ||
|
ab1a11af78 | ||
|
75183f3a81 | ||
|
7dd9b1cac0 |
||
|
87fc5d8fc7 | ||
|
0649d50b5f | ||
|
d5ef1d53e5 |
||
|
acc0b4a326 |
||
|
a70bf8f46c |
||
|
181892bcfe |
||
|
ae430e700c |
||
|
25c7c6ab40 |
||
|
4070f0d093 |
||
|
6d16442d4d |
||
|
fe501d34a0 |
||
|
bd8fd89055 |
||
|
d03b29856d | ||
|
a11bd346e0 |
||
|
8357819b53 | ||
|
b54fba5c99 | ||
|
f400def107 |
||
|
7705743251 | ||
|
44840bcd87 | ||
|
1ac0e5768b | ||
|
da6ed76bd6 | ||
|
0e8c47a1d3 |
||
|
7017806bfb |
||
|
9e45e816c3 |
||
|
a96d2a7818 | ||
|
75d279b83a |
||
|
4da0a597d7 |
||
|
ae25e41b1b | ||
|
9096e91d55 | ||
|
5938077d82 | ||
|
5973056393 | ||
|
a1ff72d428 |
||
|
4f12939e22 | ||
|
70a6a8f953 | ||
|
03d94220c7 | ||
|
6794b887f6 | ||
|
a373359ae8 | ||
|
1a0823ca80 | ||
|
e0a23313c1 | ||
|
b57cd31817 |
||
|
8b7b11c70f |
||
|
cac0288b72 |
||
|
18742776da | ||
|
d792bf5902 |
||
|
3cc84778a4 | ||
|
651fcedcab | ||
|
e827af7bed |
||
|
1c232ec3e4 |
||
|
5d58db3a94 |
||
|
8f30fbe690 | ||
|
da8251c4f2 | ||
|
803a34d922 |
||
|
d8f2260c7a | ||
|
1027fcf1f3 | ||
|
48111827bd |
||
|
39bfdf7bcb |
||
|
4cdd501ed3 |
||
|
d8e831de91 |
||
|
b1fbd8efa5 |
||
|
0c73501d32 |
||
|
ef7ec861d8 | ||
|
4fa71f71a0 | ||
|
7383cd4c70 |
||
|
8daf8e0c7f | ||
|
a0e0ae1da3 | ||
|
eea8663f7d | ||
|
9652719c6b |
||
|
809202be5f | ||
|
59f9625507 | ||
|
c4524d22a9 |
||
|
d41dd7210b | ||
|
e8fb74de03 | ||
|
fc202f5337 | ||
|
6756ee688a |
248 changed files with 25131 additions and 14557 deletions
2
.github/workflows/automation-tests.yml
vendored
2
.github/workflows/automation-tests.yml
vendored
|
@ -24,7 +24,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
node-version: '18'
|
node-version: '18'
|
||||||
|
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
'**/node_modules'
|
'**/node_modules'
|
||||||
|
|
24
.github/workflows/build.yml
vendored
24
.github/workflows/build.yml
vendored
|
@ -15,7 +15,7 @@ jobs:
|
||||||
node-version: '18'
|
node-version: '18'
|
||||||
|
|
||||||
- name: NodeModules Cache
|
- name: NodeModules Cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: '**/node_modules'
|
path: '**/node_modules'
|
||||||
key: node_modules-${{ hashFiles('**/yarn.lock') }}
|
key: node_modules-${{ hashFiles('**/yarn.lock') }}
|
||||||
|
@ -27,7 +27,7 @@ jobs:
|
||||||
run: yarn --cwd ./src/Ombi/ClientApp run build
|
run: yarn --cwd ./src/Ombi/ClientApp run build
|
||||||
|
|
||||||
- name: Publish UI Artifacts
|
- name: Publish UI Artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: angular_dist
|
name: angular_dist
|
||||||
path: |
|
path: |
|
||||||
|
@ -39,10 +39,10 @@ jobs:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-dotnet@v1
|
- uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: '6.0.x'
|
dotnet-version: '8.0.x'
|
||||||
|
|
||||||
- name: Nuget Cache
|
- name: Nuget Cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.nuget/packages
|
path: ~/.nuget/packages
|
||||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
||||||
|
@ -84,10 +84,10 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: win10-x64
|
- os: win-x64
|
||||||
format: zip
|
format: zip
|
||||||
compression: zip
|
compression: zip
|
||||||
- os: win10-x86
|
- os: win-x86
|
||||||
format: zip
|
format: zip
|
||||||
compression: zip
|
compression: zip
|
||||||
- os: linux-x64
|
- os: linux-x64
|
||||||
|
@ -106,13 +106,13 @@ jobs:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-dotnet@v1
|
- uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: '6.0.x'
|
dotnet-version: '8.0.x'
|
||||||
- uses: actions/setup-dotnet@v1
|
- uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: '5.0.x'
|
dotnet-version: '5.0.x'
|
||||||
|
|
||||||
- name: Nuget Cache
|
- name: Nuget Cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.nuget/packages
|
path: ~/.nuget/packages
|
||||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
||||||
|
@ -130,7 +130,7 @@ jobs:
|
||||||
working-directory: src/Ombi
|
working-directory: src/Ombi
|
||||||
|
|
||||||
- name: Download Angular
|
- name: Download Angular
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: angular_dist
|
name: angular_dist
|
||||||
path: ~/src/Ombi/dist
|
path: ~/src/Ombi/dist
|
||||||
|
@ -156,7 +156,7 @@ jobs:
|
||||||
directory: 'src/Ombi/${{ matrix.os }}'
|
directory: 'src/Ombi/${{ matrix.os }}'
|
||||||
|
|
||||||
- name: Publish Release
|
- name: Publish Release
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.os }}
|
name: ${{ matrix.os }}
|
||||||
path: |
|
path: |
|
||||||
|
@ -170,7 +170,7 @@ jobs:
|
||||||
|
|
||||||
- name: Download Artifacts
|
- name: Download Artifacts
|
||||||
id: download
|
id: download
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
path: artifacts
|
path: artifacts
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ jobs:
|
||||||
if: contains(github.ref, 'develop')
|
if: contains(github.ref, 'develop')
|
||||||
with:
|
with:
|
||||||
prerelease: true
|
prerelease: true
|
||||||
generate_release_notes: true
|
generate_release_notes: false
|
||||||
body: ${{ needs.versioning.outputs.changelog }}
|
body: ${{ needs.versioning.outputs.changelog }}
|
||||||
name: ${{ needs.versioning.outputs.tag }}
|
name: ${{ needs.versioning.outputs.tag }}
|
||||||
tag_name: ${{ needs.versioning.outputs.tag }}
|
tag_name: ${{ needs.versioning.outputs.tag }}
|
||||||
|
|
2
.github/workflows/chromatic.yml
vendored
2
.github/workflows/chromatic.yml
vendored
|
@ -17,7 +17,7 @@
|
||||||
# fetch-depth: 0
|
# fetch-depth: 0
|
||||||
|
|
||||||
# - name: NodeModules Cache
|
# - name: NodeModules Cache
|
||||||
# uses: actions/cache@v2
|
# uses: actions/cache@v4
|
||||||
# with:
|
# with:
|
||||||
# path: '**/node_modules'
|
# path: '**/node_modules'
|
||||||
# key: node_modules-${{ hashFiles('**/yarn.lock') }}
|
# key: node_modules-${{ hashFiles('**/yarn.lock') }}
|
||||||
|
|
6
.github/workflows/codeql-analysis.yml
vendored
6
.github/workflows/codeql-analysis.yml
vendored
|
@ -37,7 +37,7 @@ jobs:
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v1
|
uses: github/codeql-action/init@v3
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
|
@ -48,7 +48,7 @@ jobs:
|
||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@v1
|
uses: github/codeql-action/autobuild@v3
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 https://git.io/JvXDl
|
# 📚 https://git.io/JvXDl
|
||||||
|
@ -62,4 +62,4 @@ jobs:
|
||||||
# make release
|
# make release
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v1
|
uses: github/codeql-action/analyze@v3
|
||||||
|
|
14
.github/workflows/pr.yml
vendored
14
.github/workflows/pr.yml
vendored
|
@ -20,7 +20,7 @@ jobs:
|
||||||
node-version: '18'
|
node-version: '18'
|
||||||
|
|
||||||
- name: NodeModules Cache
|
- name: NodeModules Cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: '**/node_modules'
|
path: '**/node_modules'
|
||||||
key: node_modules-${{ hashFiles('**/yarn.lock') }}
|
key: node_modules-${{ hashFiles('**/yarn.lock') }}
|
||||||
|
@ -38,10 +38,10 @@ jobs:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-dotnet@v1
|
- uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: '6.0.x'
|
dotnet-version: '8.0.x'
|
||||||
|
|
||||||
- name: Nuget Cache
|
- name: Nuget Cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.nuget/packages
|
path: ~/.nuget/packages
|
||||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
||||||
|
@ -76,10 +76,10 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: win10-x64
|
- os: win-x64
|
||||||
format: zip
|
format: zip
|
||||||
compression: zip
|
compression: zip
|
||||||
- os: win10-x86
|
- os: win-x86
|
||||||
format: zip
|
format: zip
|
||||||
compression: zip
|
compression: zip
|
||||||
- os: linux-x64
|
- os: linux-x64
|
||||||
|
@ -98,10 +98,10 @@ jobs:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-dotnet@v1
|
- uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: '6.0.x'
|
dotnet-version: '8.0.x'
|
||||||
|
|
||||||
- name: Nuget Cache
|
- name: Nuget Cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.nuget/packages
|
path: ~/.nuget/packages
|
||||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
||||||
|
|
2444
CHANGELOG.md
2444
CHANGELOG.md
File diff suppressed because it is too large
Load diff
2309
src/.idea/.idea.Ombi/.idea/contentModel.xml
generated
2309
src/.idea/.idea.Ombi/.idea/contentModel.xml
generated
File diff suppressed because it is too large
Load diff
440
src/.idea/.idea.Ombi/.idea/dbnavigator.xml
generated
Normal file
440
src/.idea/.idea.Ombi/.idea/dbnavigator.xml
generated
Normal file
|
@ -0,0 +1,440 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="DBNavigator.Project.DDLFileAttachmentManager">
|
||||||
|
<mappings />
|
||||||
|
<preferences />
|
||||||
|
</component>
|
||||||
|
<component name="DBNavigator.Project.DatabaseAssistantManager">
|
||||||
|
<assistants />
|
||||||
|
</component>
|
||||||
|
<component name="DBNavigator.Project.DatabaseBrowserManager">
|
||||||
|
<autoscroll-to-editor value="false" />
|
||||||
|
<autoscroll-from-editor value="true" />
|
||||||
|
<show-object-properties value="true" />
|
||||||
|
<loaded-nodes />
|
||||||
|
</component>
|
||||||
|
<component name="DBNavigator.Project.DatabaseFileManager">
|
||||||
|
<open-files />
|
||||||
|
</component>
|
||||||
|
<component name="DBNavigator.Project.ExecutionManager">
|
||||||
|
<retain-sticky-names value="false" />
|
||||||
|
</component>
|
||||||
|
<component name="DBNavigator.Project.ParserDiagnosticsManager">
|
||||||
|
<diagnostics-history />
|
||||||
|
</component>
|
||||||
|
<component name="DBNavigator.Project.Settings">
|
||||||
|
<connections />
|
||||||
|
<browser-settings>
|
||||||
|
<general>
|
||||||
|
<display-mode value="TABBED" />
|
||||||
|
<navigation-history-size value="100" />
|
||||||
|
<show-object-details value="false" />
|
||||||
|
<enable-sticky-paths value="true" />
|
||||||
|
</general>
|
||||||
|
<filters>
|
||||||
|
<object-type-filter>
|
||||||
|
<object-type name="SCHEMA" enabled="true" />
|
||||||
|
<object-type name="USER" enabled="true" />
|
||||||
|
<object-type name="ROLE" enabled="true" />
|
||||||
|
<object-type name="PRIVILEGE" enabled="true" />
|
||||||
|
<object-type name="CHARSET" enabled="true" />
|
||||||
|
<object-type name="TABLE" enabled="true" />
|
||||||
|
<object-type name="VIEW" enabled="true" />
|
||||||
|
<object-type name="MATERIALIZED_VIEW" enabled="true" />
|
||||||
|
<object-type name="NESTED_TABLE" enabled="true" />
|
||||||
|
<object-type name="COLUMN" enabled="true" />
|
||||||
|
<object-type name="INDEX" enabled="true" />
|
||||||
|
<object-type name="CONSTRAINT" enabled="true" />
|
||||||
|
<object-type name="DATASET_TRIGGER" enabled="true" />
|
||||||
|
<object-type name="DATABASE_TRIGGER" enabled="true" />
|
||||||
|
<object-type name="SYNONYM" enabled="true" />
|
||||||
|
<object-type name="SEQUENCE" enabled="true" />
|
||||||
|
<object-type name="PROCEDURE" enabled="true" />
|
||||||
|
<object-type name="FUNCTION" enabled="true" />
|
||||||
|
<object-type name="PACKAGE" enabled="true" />
|
||||||
|
<object-type name="TYPE" enabled="true" />
|
||||||
|
<object-type name="TYPE_ATTRIBUTE" enabled="true" />
|
||||||
|
<object-type name="ARGUMENT" enabled="true" />
|
||||||
|
<object-type name="JAVA_CLASS" enabled="true" />
|
||||||
|
<object-type name="JAVA_INNER_CLASS" enabled="true" />
|
||||||
|
<object-type name="JAVA_FIELD" enabled="true" />
|
||||||
|
<object-type name="JAVA_METHOD" enabled="true" />
|
||||||
|
<object-type name="DIMENSION" enabled="true" />
|
||||||
|
<object-type name="CLUSTER" enabled="true" />
|
||||||
|
<object-type name="DBLINK" enabled="true" />
|
||||||
|
<object-type name="CREDENTIAL" enabled="true" />
|
||||||
|
<object-type name="AI_PROFILE" enabled="true" />
|
||||||
|
</object-type-filter>
|
||||||
|
</filters>
|
||||||
|
<sorting>
|
||||||
|
<object-type name="COLUMN" sorting-type="NAME" />
|
||||||
|
<object-type name="FUNCTION" sorting-type="NAME" />
|
||||||
|
<object-type name="PROCEDURE" sorting-type="NAME" />
|
||||||
|
<object-type name="ARGUMENT" sorting-type="POSITION" />
|
||||||
|
<object-type name="TYPE ATTRIBUTE" sorting-type="POSITION" />
|
||||||
|
</sorting>
|
||||||
|
<default-editors>
|
||||||
|
<object-type name="VIEW" editor-type="SELECTION" />
|
||||||
|
<object-type name="PACKAGE" editor-type="SELECTION" />
|
||||||
|
<object-type name="TYPE" editor-type="SELECTION" />
|
||||||
|
</default-editors>
|
||||||
|
</browser-settings>
|
||||||
|
<navigation-settings>
|
||||||
|
<lookup-filters>
|
||||||
|
<lookup-objects>
|
||||||
|
<object-type name="SCHEMA" enabled="true" />
|
||||||
|
<object-type name="USER" enabled="false" />
|
||||||
|
<object-type name="ROLE" enabled="false" />
|
||||||
|
<object-type name="PRIVILEGE" enabled="false" />
|
||||||
|
<object-type name="CHARSET" enabled="false" />
|
||||||
|
<object-type name="TABLE" enabled="true" />
|
||||||
|
<object-type name="VIEW" enabled="true" />
|
||||||
|
<object-type name="MATERIALIZED VIEW" enabled="true" />
|
||||||
|
<object-type name="INDEX" enabled="true" />
|
||||||
|
<object-type name="CONSTRAINT" enabled="true" />
|
||||||
|
<object-type name="DATASET TRIGGER" enabled="true" />
|
||||||
|
<object-type name="DATABASE TRIGGER" enabled="true" />
|
||||||
|
<object-type name="SYNONYM" enabled="false" />
|
||||||
|
<object-type name="SEQUENCE" enabled="true" />
|
||||||
|
<object-type name="PROCEDURE" enabled="true" />
|
||||||
|
<object-type name="FUNCTION" enabled="true" />
|
||||||
|
<object-type name="PACKAGE" enabled="true" />
|
||||||
|
<object-type name="TYPE" enabled="true" />
|
||||||
|
<object-type name="JAVA CLASS" enabled="true" />
|
||||||
|
<object-type name="INNER CLASS" enabled="true" />
|
||||||
|
<object-type name="JAVA FIELD" enabled="true" />
|
||||||
|
<object-type name="JAVA METHOD" enabled="true" />
|
||||||
|
<object-type name="JAVA PARAMETER" enabled="true" />
|
||||||
|
<object-type name="DIMENSION" enabled="false" />
|
||||||
|
<object-type name="CLUSTER" enabled="false" />
|
||||||
|
<object-type name="DBLINK" enabled="false" />
|
||||||
|
<object-type name="CREDENTIAL" enabled="false" />
|
||||||
|
</lookup-objects>
|
||||||
|
<force-database-load value="false" />
|
||||||
|
<prompt-connection-selection value="true" />
|
||||||
|
<prompt-schema-selection value="true" />
|
||||||
|
</lookup-filters>
|
||||||
|
</navigation-settings>
|
||||||
|
<dataset-grid-settings>
|
||||||
|
<general>
|
||||||
|
<enable-zooming value="true" />
|
||||||
|
<enable-column-tooltip value="true" />
|
||||||
|
</general>
|
||||||
|
<sorting>
|
||||||
|
<nulls-first value="true" />
|
||||||
|
<max-sorting-columns value="4" />
|
||||||
|
</sorting>
|
||||||
|
<audit-columns>
|
||||||
|
<column-names value="" />
|
||||||
|
<visible value="true" />
|
||||||
|
<editable value="false" />
|
||||||
|
</audit-columns>
|
||||||
|
</dataset-grid-settings>
|
||||||
|
<dataset-editor-settings>
|
||||||
|
<text-editor-popup>
|
||||||
|
<active value="false" />
|
||||||
|
<active-if-empty value="false" />
|
||||||
|
<data-length-threshold value="100" />
|
||||||
|
<popup-delay value="1000" />
|
||||||
|
</text-editor-popup>
|
||||||
|
<values-actions-popup>
|
||||||
|
<show-popup-button value="true" />
|
||||||
|
<element-count-threshold value="1000" />
|
||||||
|
<data-length-threshold value="250" />
|
||||||
|
</values-actions-popup>
|
||||||
|
<general>
|
||||||
|
<fetch-block-size value="100" />
|
||||||
|
<fetch-timeout value="30" />
|
||||||
|
<trim-whitespaces value="true" />
|
||||||
|
<convert-empty-strings-to-null value="true" />
|
||||||
|
<select-content-on-cell-edit value="true" />
|
||||||
|
<large-value-preview-active value="true" />
|
||||||
|
</general>
|
||||||
|
<filters>
|
||||||
|
<prompt-filter-dialog value="true" />
|
||||||
|
<default-filter-type value="BASIC" />
|
||||||
|
</filters>
|
||||||
|
<qualified-text-editor text-length-threshold="300">
|
||||||
|
<content-types>
|
||||||
|
<content-type name="Text" enabled="true" />
|
||||||
|
<content-type name="Properties" enabled="true" />
|
||||||
|
<content-type name="XML" enabled="true" />
|
||||||
|
<content-type name="DTD" enabled="true" />
|
||||||
|
<content-type name="HTML" enabled="true" />
|
||||||
|
<content-type name="XHTML" enabled="true" />
|
||||||
|
<content-type name="CSS" enabled="true" />
|
||||||
|
<content-type name="SQL" enabled="true" />
|
||||||
|
<content-type name="PL/SQL" enabled="true" />
|
||||||
|
<content-type name="JavaScript" enabled="true" />
|
||||||
|
<content-type name="JSON" enabled="true" />
|
||||||
|
<content-type name="JSON5" enabled="true" />
|
||||||
|
<content-type name="YAML" enabled="true" />
|
||||||
|
<content-type name="C#" enabled="true" />
|
||||||
|
</content-types>
|
||||||
|
</qualified-text-editor>
|
||||||
|
<record-navigation>
|
||||||
|
<navigation-target value="VIEWER" />
|
||||||
|
</record-navigation>
|
||||||
|
</dataset-editor-settings>
|
||||||
|
<code-editor-settings>
|
||||||
|
<general>
|
||||||
|
<show-object-navigation-gutter value="false" />
|
||||||
|
<show-spec-declaration-navigation-gutter value="true" />
|
||||||
|
<enable-spellchecking value="true" />
|
||||||
|
<enable-reference-spellchecking value="false" />
|
||||||
|
</general>
|
||||||
|
<confirmations>
|
||||||
|
<save-changes value="false" />
|
||||||
|
<revert-changes value="true" />
|
||||||
|
<exit-on-changes value="ASK" />
|
||||||
|
</confirmations>
|
||||||
|
</code-editor-settings>
|
||||||
|
<code-completion-settings>
|
||||||
|
<filters>
|
||||||
|
<basic-filter>
|
||||||
|
<filter-element type="RESERVED_WORD" id="keyword" selected="true" />
|
||||||
|
<filter-element type="RESERVED_WORD" id="function" selected="true" />
|
||||||
|
<filter-element type="RESERVED_WORD" id="parameter" selected="true" />
|
||||||
|
<filter-element type="RESERVED_WORD" id="datatype" selected="true" />
|
||||||
|
<filter-element type="RESERVED_WORD" id="exception" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="schema" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="role" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="user" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="privilege" selected="true" />
|
||||||
|
<user-schema>
|
||||||
|
<filter-element type="OBJECT" id="table" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="view" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="materialized view" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="index" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="constraint" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="trigger" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="synonym" selected="false" />
|
||||||
|
<filter-element type="OBJECT" id="sequence" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="procedure" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="function" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="package" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="type" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="dimension" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="cluster" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="dblink" selected="true" />
|
||||||
|
</user-schema>
|
||||||
|
<public-schema>
|
||||||
|
<filter-element type="OBJECT" id="table" selected="false" />
|
||||||
|
<filter-element type="OBJECT" id="view" selected="false" />
|
||||||
|
<filter-element type="OBJECT" id="materialized view" selected="false" />
|
||||||
|
<filter-element type="OBJECT" id="index" selected="false" />
|
||||||
|
<filter-element type="OBJECT" id="constraint" selected="false" />
|
||||||
|
<filter-element type="OBJECT" id="trigger" selected="false" />
|
||||||
|
<filter-element type="OBJECT" id="synonym" selected="false" />
|
||||||
|
<filter-element type="OBJECT" id="sequence" selected="false" />
|
||||||
|
<filter-element type="OBJECT" id="procedure" selected="false" />
|
||||||
|
<filter-element type="OBJECT" id="function" selected="false" />
|
||||||
|
<filter-element type="OBJECT" id="package" selected="false" />
|
||||||
|
<filter-element type="OBJECT" id="type" selected="false" />
|
||||||
|
<filter-element type="OBJECT" id="dimension" selected="false" />
|
||||||
|
<filter-element type="OBJECT" id="cluster" selected="false" />
|
||||||
|
<filter-element type="OBJECT" id="dblink" selected="false" />
|
||||||
|
</public-schema>
|
||||||
|
<any-schema>
|
||||||
|
<filter-element type="OBJECT" id="table" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="view" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="materialized view" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="index" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="constraint" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="trigger" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="synonym" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="sequence" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="procedure" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="function" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="package" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="type" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="dimension" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="cluster" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="dblink" selected="true" />
|
||||||
|
</any-schema>
|
||||||
|
</basic-filter>
|
||||||
|
<extended-filter>
|
||||||
|
<filter-element type="RESERVED_WORD" id="keyword" selected="true" />
|
||||||
|
<filter-element type="RESERVED_WORD" id="function" selected="true" />
|
||||||
|
<filter-element type="RESERVED_WORD" id="parameter" selected="true" />
|
||||||
|
<filter-element type="RESERVED_WORD" id="datatype" selected="true" />
|
||||||
|
<filter-element type="RESERVED_WORD" id="exception" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="schema" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="user" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="role" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="privilege" selected="true" />
|
||||||
|
<user-schema>
|
||||||
|
<filter-element type="OBJECT" id="table" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="view" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="materialized view" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="index" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="constraint" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="trigger" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="synonym" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="sequence" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="procedure" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="function" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="package" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="type" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="dimension" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="cluster" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="dblink" selected="true" />
|
||||||
|
</user-schema>
|
||||||
|
<public-schema>
|
||||||
|
<filter-element type="OBJECT" id="table" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="view" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="materialized view" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="index" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="constraint" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="trigger" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="synonym" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="sequence" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="procedure" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="function" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="package" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="type" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="dimension" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="cluster" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="dblink" selected="true" />
|
||||||
|
</public-schema>
|
||||||
|
<any-schema>
|
||||||
|
<filter-element type="OBJECT" id="table" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="view" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="materialized view" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="index" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="constraint" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="trigger" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="synonym" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="sequence" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="procedure" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="function" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="package" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="type" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="dimension" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="cluster" selected="true" />
|
||||||
|
<filter-element type="OBJECT" id="dblink" selected="true" />
|
||||||
|
</any-schema>
|
||||||
|
</extended-filter>
|
||||||
|
</filters>
|
||||||
|
<sorting enabled="true">
|
||||||
|
<sorting-element type="RESERVED_WORD" id="keyword" />
|
||||||
|
<sorting-element type="RESERVED_WORD" id="datatype" />
|
||||||
|
<sorting-element type="OBJECT" id="column" />
|
||||||
|
<sorting-element type="OBJECT" id="table" />
|
||||||
|
<sorting-element type="OBJECT" id="view" />
|
||||||
|
<sorting-element type="OBJECT" id="materialized view" />
|
||||||
|
<sorting-element type="OBJECT" id="index" />
|
||||||
|
<sorting-element type="OBJECT" id="constraint" />
|
||||||
|
<sorting-element type="OBJECT" id="trigger" />
|
||||||
|
<sorting-element type="OBJECT" id="synonym" />
|
||||||
|
<sorting-element type="OBJECT" id="sequence" />
|
||||||
|
<sorting-element type="OBJECT" id="procedure" />
|
||||||
|
<sorting-element type="OBJECT" id="function" />
|
||||||
|
<sorting-element type="OBJECT" id="package" />
|
||||||
|
<sorting-element type="OBJECT" id="type" />
|
||||||
|
<sorting-element type="OBJECT" id="dimension" />
|
||||||
|
<sorting-element type="OBJECT" id="cluster" />
|
||||||
|
<sorting-element type="OBJECT" id="dblink" />
|
||||||
|
<sorting-element type="OBJECT" id="schema" />
|
||||||
|
<sorting-element type="OBJECT" id="role" />
|
||||||
|
<sorting-element type="OBJECT" id="user" />
|
||||||
|
<sorting-element type="RESERVED_WORD" id="function" />
|
||||||
|
<sorting-element type="RESERVED_WORD" id="parameter" />
|
||||||
|
</sorting>
|
||||||
|
<format>
|
||||||
|
<enforce-code-style-case value="true" />
|
||||||
|
</format>
|
||||||
|
</code-completion-settings>
|
||||||
|
<execution-engine-settings>
|
||||||
|
<statement-execution>
|
||||||
|
<fetch-block-size value="100" />
|
||||||
|
<execution-timeout value="20" />
|
||||||
|
<debug-execution-timeout value="600" />
|
||||||
|
<focus-result value="false" />
|
||||||
|
<prompt-execution value="false" />
|
||||||
|
</statement-execution>
|
||||||
|
<script-execution>
|
||||||
|
<command-line-interfaces />
|
||||||
|
<execution-timeout value="300" />
|
||||||
|
</script-execution>
|
||||||
|
<method-execution>
|
||||||
|
<execution-timeout value="30" />
|
||||||
|
<debug-execution-timeout value="600" />
|
||||||
|
<parameter-history-size value="10" />
|
||||||
|
</method-execution>
|
||||||
|
</execution-engine-settings>
|
||||||
|
<operation-settings>
|
||||||
|
<transactions>
|
||||||
|
<uncommitted-changes>
|
||||||
|
<on-project-close value="ASK" />
|
||||||
|
<on-disconnect value="ASK" />
|
||||||
|
<on-autocommit-toggle value="ASK" />
|
||||||
|
</uncommitted-changes>
|
||||||
|
<multiple-uncommitted-changes>
|
||||||
|
<on-commit value="ASK" />
|
||||||
|
<on-rollback value="ASK" />
|
||||||
|
</multiple-uncommitted-changes>
|
||||||
|
</transactions>
|
||||||
|
<session-browser>
|
||||||
|
<disconnect-session value="ASK" />
|
||||||
|
<kill-session value="ASK" />
|
||||||
|
<reload-on-filter-change value="false" />
|
||||||
|
</session-browser>
|
||||||
|
<compiler>
|
||||||
|
<compile-type value="KEEP" />
|
||||||
|
<compile-dependencies value="ASK" />
|
||||||
|
<always-show-controls value="false" />
|
||||||
|
</compiler>
|
||||||
|
</operation-settings>
|
||||||
|
<ddl-file-settings>
|
||||||
|
<extensions>
|
||||||
|
<mapping file-type-id="VIEW" extensions="vw" />
|
||||||
|
<mapping file-type-id="TRIGGER" extensions="trg" />
|
||||||
|
<mapping file-type-id="PROCEDURE" extensions="prc" />
|
||||||
|
<mapping file-type-id="FUNCTION" extensions="fnc" />
|
||||||
|
<mapping file-type-id="PACKAGE" extensions="pkg" />
|
||||||
|
<mapping file-type-id="PACKAGE_SPEC" extensions="pks" />
|
||||||
|
<mapping file-type-id="PACKAGE_BODY" extensions="pkb" />
|
||||||
|
<mapping file-type-id="TYPE" extensions="tpe" />
|
||||||
|
<mapping file-type-id="TYPE_SPEC" extensions="tps" />
|
||||||
|
<mapping file-type-id="TYPE_BODY" extensions="tpb" />
|
||||||
|
<mapping file-type-id="JAVA_SOURCE" extensions="sql" />
|
||||||
|
</extensions>
|
||||||
|
<general>
|
||||||
|
<lookup-ddl-files value="true" />
|
||||||
|
<create-ddl-files value="false" />
|
||||||
|
<synchronize-ddl-files value="true" />
|
||||||
|
<use-qualified-names value="false" />
|
||||||
|
<make-scripts-rerunnable value="true" />
|
||||||
|
</general>
|
||||||
|
</ddl-file-settings>
|
||||||
|
<assistant-settings>
|
||||||
|
<credential-settings>
|
||||||
|
<credentials />
|
||||||
|
</credential-settings>
|
||||||
|
</assistant-settings>
|
||||||
|
<general-settings>
|
||||||
|
<regional-settings>
|
||||||
|
<date-format value="MEDIUM" />
|
||||||
|
<number-format value="UNGROUPED" />
|
||||||
|
<locale value="SYSTEM_DEFAULT" />
|
||||||
|
<use-custom-formats value="false" />
|
||||||
|
</regional-settings>
|
||||||
|
<environment>
|
||||||
|
<environment-types>
|
||||||
|
<environment-type id="development" name="Development" description="Development environment" color="-2430209/-12296320" readonly-code="false" readonly-data="false" />
|
||||||
|
<environment-type id="integration" name="Integration" description="Integration environment" color="-2621494/-12163514" readonly-code="true" readonly-data="false" />
|
||||||
|
<environment-type id="production" name="Production" description="Productive environment" color="-11574/-10271420" readonly-code="true" readonly-data="true" />
|
||||||
|
<environment-type id="other" name="Other" description="" color="-1576/-10724543" readonly-code="false" readonly-data="false" />
|
||||||
|
</environment-types>
|
||||||
|
<visibility-settings>
|
||||||
|
<connection-tabs value="true" />
|
||||||
|
<dialog-headers value="true" />
|
||||||
|
<object-editor-tabs value="true" />
|
||||||
|
<script-editor-tabs value="false" />
|
||||||
|
<execution-result-tabs value="true" />
|
||||||
|
</visibility-settings>
|
||||||
|
</environment>
|
||||||
|
</general-settings>
|
||||||
|
</component>
|
||||||
|
</project>
|
2
src/.idea/.idea.Ombi/.idea/indexLayout.xml
generated
2
src/.idea/.idea.Ombi/.idea/indexLayout.xml
generated
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ContentModelUserStore">
|
<component name="UserContentModel">
|
||||||
<attachedFolders />
|
<attachedFolders />
|
||||||
<explicitIncludes />
|
<explicitIncludes />
|
||||||
<explicitExcludes />
|
<explicitExcludes />
|
||||||
|
|
8
src/.idea/.idea.Ombi/.idea/modules.xml
generated
8
src/.idea/.idea.Ombi/.idea/modules.xml
generated
|
@ -1,8 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectModuleManager">
|
|
||||||
<modules>
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/.idea.Ombi/riderModule.iml" filepath="$PROJECT_DIR$/.idea/.idea.Ombi/riderModule.iml" />
|
|
||||||
</modules>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
7
src/.idea/.idea.Ombi/.idea/projectSettingsUpdater.xml
generated
Normal file
7
src/.idea/.idea.Ombi/.idea/projectSettingsUpdater.xml
generated
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="RiderProjectSettingsUpdater">
|
||||||
|
<option name="singleClickDiffPreview" value="1" />
|
||||||
|
<option name="vcsConfiguration" value="3" />
|
||||||
|
</component>
|
||||||
|
</project>
|
222
src/.idea/.idea.Ombi/.idea/workspace.xml
generated
222
src/.idea/.idea.Ombi/.idea/workspace.xml
generated
|
@ -1,25 +1,20 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
|
<component name="AutoImportSettings">
|
||||||
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="57001998-efde-494a-80b3-d7acfc91f770" name="Default Changelist" comment="">
|
<list default="true" id="57001998-efde-494a-80b3-d7acfc91f770" name="Default Changelist" comment="">
|
||||||
<change afterPath="$PROJECT_DIR$/Ombi.Core/Engine/Interfaces/IMusicSearchEngineV2.cs" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/Ombi/ClientApp/src/app/settings/plex/plex.component.html" beforeDir="false" afterPath="$PROJECT_DIR$/Ombi/ClientApp/src/app/settings/plex/plex.component.html" afterDir="false" />
|
||||||
<change afterPath="$PROJECT_DIR$/Ombi.Core/Engine/V2/MusicSearchEngineV2.cs" afterDir="false" />
|
|
||||||
<change afterPath="$PROJECT_DIR$/Ombi.Core/Models/Search/V2/Music/ArtistInformation.cs" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/.idea.Ombi/.idea/contentModel.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.Ombi/.idea/contentModel.xml" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/.idea.Ombi/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.Ombi/.idea/workspace.xml" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/config/applicationhost.config" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/config/applicationhost.config" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/Ombi.Api.MusicBrainz/Models/Artist/ArtistInformation.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Ombi.Api.MusicBrainz/Models/Artist/ArtistInformation.cs" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/Ombi.DependencyInjection/IocExtensions.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Ombi.DependencyInjection/IocExtensions.cs" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/Ombi/ClientApp/src/app/media-details/components/artist/artist-details.component.ts" beforeDir="false" afterPath="$PROJECT_DIR$/Ombi/ClientApp/src/app/media-details/components/artist/artist-details.component.ts" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/Ombi/ClientApp/src/app/services/searchV2.service.ts" beforeDir="false" afterPath="$PROJECT_DIR$/Ombi/ClientApp/src/app/services/searchV2.service.ts" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/Ombi/Controllers/V2/SearchController.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Ombi/Controllers/V2/SearchController.cs" afterDir="false" />
|
|
||||||
</list>
|
</list>
|
||||||
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
|
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||||
</component>
|
</component>
|
||||||
|
<component name="DpaMonitoringSettings">
|
||||||
|
<option name="firstShow" value="false" />
|
||||||
|
</component>
|
||||||
<component name="FileEditorManager">
|
<component name="FileEditorManager">
|
||||||
<leaf>
|
<leaf>
|
||||||
<file pinned="false" current-in-tab="false">
|
<file pinned="false" current-in-tab="false">
|
||||||
|
@ -237,27 +232,75 @@
|
||||||
<component name="Git.Settings">
|
<component name="Git.Settings">
|
||||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
|
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
|
||||||
</component>
|
</component>
|
||||||
|
<component name="GitHubPullRequestSearchHistory">{
|
||||||
|
"lastFilter": {
|
||||||
|
"state": "OPEN",
|
||||||
|
"assignee": "tidusjar"
|
||||||
|
}
|
||||||
|
}</component>
|
||||||
|
<component name="GitToolBoxStore">
|
||||||
|
<option name="recentBranches">
|
||||||
|
<RecentBranches>
|
||||||
|
<option name="branchesForRepo">
|
||||||
|
<list>
|
||||||
|
<RecentBranchesForRepo>
|
||||||
|
<option name="branches">
|
||||||
|
<list>
|
||||||
|
<RecentBranch>
|
||||||
|
<option name="branchName" value="wizard-database" />
|
||||||
|
<option name="lastUsedInstant" value="1735917525" />
|
||||||
|
</RecentBranch>
|
||||||
|
<RecentBranch>
|
||||||
|
<option name="branchName" value="develop" />
|
||||||
|
<option name="lastUsedInstant" value="1735917524" />
|
||||||
|
</RecentBranch>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="repositoryRootUrl" value="file://$PROJECT_DIR$/.." />
|
||||||
|
</RecentBranchesForRepo>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</RecentBranches>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="GithubProjectSettings">
|
||||||
|
<option name="branchProtectionPatterns">
|
||||||
|
<list>
|
||||||
|
<option value="master" />
|
||||||
|
<option value="develop" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="GithubPullRequestsUISettings">{
|
||||||
|
"selectedUrlAndAccountId": {
|
||||||
|
"url": "https://github.com/ombi-app/ombi",
|
||||||
|
"accountId": "22dd09fe-fb9e-48a4-bfcc-3c152edf3f25"
|
||||||
|
}
|
||||||
|
}</component>
|
||||||
<component name="HighlightingSettingsPerFile">
|
<component name="HighlightingSettingsPerFile">
|
||||||
<setting file="file://$PROJECT_DIR$/Ombi.Helpers.Tests/EmbyHelperTests.cs" root0="FORCE_HIGHLIGHTING" />
|
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/990126b794024fe2bd16aebdd37eba1d7b600/93/25662f04/ServerVersion.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
<setting file="file://$PROJECT_DIR$/Ombi.Api.MusicBrainz/MusicBrainzApi.cs" root0="FORCE_HIGHLIGHTING" />
|
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/3bd4df5aff92cabbc4d630be64227073db1b8539b3a1e47786b4b189d7cdb7/DbContext.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
<setting file="file://$PROJECT_DIR$/Ombi.Schedule.Tests/OmbiQuartzTests.cs" root0="FORCE_HIGHLIGHTING" />
|
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/449b441523c469ed34ff5a5e14f0bafcd8f097aa463655303dc19048fa44ac3/EntityFrameworkServiceCollectionExtensions.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
<setting file="file://$PROJECT_DIR$/Ombi.Api.MusicBrainz/Models/Artist/ArtistInformation.cs" root0="FORCE_HIGHLIGHTING" />
|
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/7d81b2d4f22bee75e5438c707251ae43cb0974c207db91ffc159118c84b4eb9/ServiceProvider.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
<setting file="file://$PROJECT_DIR$/Ombi/Controllers/V2/SearchController.cs" root0="FORCE_HIGHLIGHTING" />
|
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/a424e6912048b4cd25715f158e789aae24db5c2911d9e622d39bc6ac3246c6/MySqlConnectionStringBuilder.cs" root0="SKIP_HIGHLIGHTING" />
|
||||||
<setting file="file://$PROJECT_DIR$/Ombi.DependencyInjection/IocExtensions.cs" root0="FORCE_HIGHLIGHTING" />
|
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/bd1d5c50194fea68ff3559c160230b0ab50f5acf4ce3061bffd6d62958e2182/ExceptionDispatchInfo.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/V2/MultiSearchEngine.cs" root0="FORCE_HIGHLIGHTING" />
|
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/e9881a453a581134c1a18331ac1f8f1201a5382a685bf2a40777fa22619/DbContextOptions`.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/V2/IMultiSearchEngine.cs" root0="FORCE_HIGHLIGHTING" />
|
|
||||||
<setting file="file://$PROJECT_DIR$/Ombi.Api.MusicBrainz/IMusicBrainzApi.cs" root0="FORCE_HIGHLIGHTING" />
|
<setting file="file://$PROJECT_DIR$/Ombi.Api.MusicBrainz/IMusicBrainzApi.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
|
<setting file="file://$PROJECT_DIR$/Ombi.Api.MusicBrainz/MusicBrainzApi.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/Interfaces/IMusicSearchEngineV2.cs" root0="FORCE_HIGHLIGHTING" />
|
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/Interfaces/IMusicSearchEngineV2.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
<setting file="file://$PROJECT_DIR$/Ombi.Core/Models/Search/V2/Music/ArtistInformation.cs" root0="FORCE_HIGHLIGHTING" />
|
|
||||||
<setting file="mock:///Dummy.cs" root0="FORCE_HIGHLIGHTING" />
|
|
||||||
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/V2/MusicSearchEngineV2.cs" root0="FORCE_HIGHLIGHTING" />
|
|
||||||
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/RecentlyAddedEngine.cs" root0="FORCE_HIGHLIGHTING" />
|
|
||||||
<setting file="mock:///Dummy.cs" root0="FORCE_HIGHLIGHTING" />
|
|
||||||
<setting file="file://$PROJECT_DIR$/Ombi/Controllers/V1/TokenController.cs" root0="FORCE_HIGHLIGHTING" />
|
|
||||||
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/MusicSearchEngine.cs" root0="FORCE_HIGHLIGHTING" />
|
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/MusicSearchEngine.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
<setting file="file://$PROJECT_DIR$/Ombi/Program.cs" root0="FORCE_HIGHLIGHTING" />
|
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/RecentlyAddedEngine.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/UserStatsEngine.cs" root0="FORCE_HIGHLIGHTING" />
|
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/UserStatsEngine.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
<setting file="mock:///Dummy.cs" root0="FORCE_HIGHLIGHTING" />
|
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/V2/IMultiSearchEngine.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
|
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/V2/MultiSearchEngine.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
|
<setting file="file://$PROJECT_DIR$/Ombi.Core/Engine/V2/MusicSearchEngineV2.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
|
<setting file="file://$PROJECT_DIR$/Ombi.Core/Models/Search/V2/Music/ArtistInformation.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
|
<setting file="file://$PROJECT_DIR$/Ombi.DependencyInjection/IocExtensions.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
|
<setting file="file://$PROJECT_DIR$/Ombi.Helpers.Tests/EmbyHelperTests.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
|
<setting file="file://$PROJECT_DIR$/Ombi.Schedule.Tests/OmbiQuartzTests.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
|
<setting file="file://$PROJECT_DIR$/Ombi/Controllers/V1/TokenController.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
|
<setting file="file://$PROJECT_DIR$/Ombi/Controllers/V2/SearchController.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
|
<setting file="file://$PROJECT_DIR$/Ombi/Program.cs" root0="FORCE_HIGHLIGHTING" />
|
||||||
</component>
|
</component>
|
||||||
<component name="IdeDocumentHistory">
|
<component name="IdeDocumentHistory">
|
||||||
<option name="CHANGED_PATHS">
|
<option name="CHANGED_PATHS">
|
||||||
|
@ -275,12 +318,17 @@
|
||||||
<component name="PackageJsonUpdateNotifier">
|
<component name="PackageJsonUpdateNotifier">
|
||||||
<dismissed value="$PROJECT_DIR$/Ombi/ClientApp/package.json" />
|
<dismissed value="$PROJECT_DIR$/Ombi/ClientApp/package.json" />
|
||||||
</component>
|
</component>
|
||||||
|
<component name="ProjectColorInfo">{
|
||||||
|
"customColor": "",
|
||||||
|
"associatedIndex": 0
|
||||||
|
}</component>
|
||||||
<component name="ProjectFrameBounds" extendedState="6">
|
<component name="ProjectFrameBounds" extendedState="6">
|
||||||
<option name="x" value="1087" />
|
<option name="x" value="1087" />
|
||||||
<option name="y" value="-1113" />
|
<option name="y" value="-1113" />
|
||||||
<option name="width" value="1400" />
|
<option name="width" value="1400" />
|
||||||
<option name="height" value="1000" />
|
<option name="height" value="1000" />
|
||||||
</component>
|
</component>
|
||||||
|
<component name="ProjectId" id="2wGwbN5gDqLwyiO1WJdlwJzZ5M9" />
|
||||||
<component name="ProjectLevelVcsManager" settingsEditedManually="true">
|
<component name="ProjectLevelVcsManager" settingsEditedManually="true">
|
||||||
<ConfirmationsSetting value="2" id="Add" />
|
<ConfirmationsSetting value="2" id="Add" />
|
||||||
</component>
|
</component>
|
||||||
|
@ -343,27 +391,26 @@
|
||||||
<pane id="FileSystemExplorer" />
|
<pane id="FileSystemExplorer" />
|
||||||
</panes>
|
</panes>
|
||||||
</component>
|
</component>
|
||||||
<component name="PropertiesComponent">
|
<component name="ProjectViewState">
|
||||||
<property name="ASKED_SHARE_PROJECT_CONFIGURATION_FILES" value="true" />
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
<property name="Rider.DefaultBreakpoints.AreToggled" value="true" />
|
<option name="showLibraryContents" value="true" />
|
||||||
<property name="Rider.ProjectViewActivator.IsNotFirstRun" value="true" />
|
|
||||||
<property name="SHARE_PROJECT_CONFIGURATION_FILES" value="true" />
|
|
||||||
<property name="WebServerToolWindowFactoryState" value="false" />
|
|
||||||
<property name="nodejs_package_manager_path" value="npm" />
|
|
||||||
</component>
|
</component>
|
||||||
<component name="RunDashboard">
|
<component name="PropertiesComponent"><![CDATA[{
|
||||||
<option name="ruleStates">
|
"keyToString": {
|
||||||
<list>
|
".NET Launch Settings Profile.Ombi.Schedule.Tests.executor": "Run",
|
||||||
<RuleState>
|
".NET Launch Settings Profile.Ombi.executor": "Debug",
|
||||||
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
</RuleState>
|
"RunOnceActivity.git.unshallow": "true",
|
||||||
<RuleState>
|
"fb34c741-04ca-4b4f-8ea1-651a011b42c8.executor": "Debug",
|
||||||
<option name="name" value="StatusDashboardGroupingRule" />
|
"git-widget-placeholder": "watchlist-expired-notification",
|
||||||
</RuleState>
|
"node.js.detected.package.eslint": "true",
|
||||||
</list>
|
"node.js.selected.package.eslint": "(autodetect)",
|
||||||
</option>
|
"node.js.selected.package.tslint": "(autodetect)",
|
||||||
</component>
|
"nodejs_package_manager_path": "yarn",
|
||||||
<component name="RunManager" selected=".NET Launch Settings Profile.Ombi: IIS Express">
|
"vue.rearranger.settings.migration": "true"
|
||||||
|
}
|
||||||
|
}]]></component>
|
||||||
|
<component name="RunManager" selected=".NET Launch Settings Profile.Ombi">
|
||||||
<configuration name="Ombi" type="LaunchSettings" factoryName=".NET Launch Settings Profile">
|
<configuration name="Ombi" type="LaunchSettings" factoryName=".NET Launch Settings Profile">
|
||||||
<option name="LAUNCH_PROFILE_PROJECT_FILE_PATH" value="$PROJECT_DIR$/Ombi/Ombi.csproj" />
|
<option name="LAUNCH_PROFILE_PROJECT_FILE_PATH" value="$PROJECT_DIR$/Ombi/Ombi.csproj" />
|
||||||
<option name="LAUNCH_PROFILE_TFM" value=".NETCoreApp,Version=v2.2" />
|
<option name="LAUNCH_PROFILE_TFM" value=".NETCoreApp,Version=v2.2" />
|
||||||
|
@ -376,7 +423,7 @@
|
||||||
<option name="SEND_DEBUG_REQUEST" value="1" />
|
<option name="SEND_DEBUG_REQUEST" value="1" />
|
||||||
<option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" />
|
<option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Build" enabled="true" />
|
<option name="Build" />
|
||||||
</method>
|
</method>
|
||||||
</configuration>
|
</configuration>
|
||||||
<configuration name="Ombi: IIS Express" type="LaunchSettings" factoryName=".NET Launch Settings Profile">
|
<configuration name="Ombi: IIS Express" type="LaunchSettings" factoryName=".NET Launch Settings Profile">
|
||||||
|
@ -391,7 +438,7 @@
|
||||||
<option name="SEND_DEBUG_REQUEST" value="1" />
|
<option name="SEND_DEBUG_REQUEST" value="1" />
|
||||||
<option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" />
|
<option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Build" enabled="true" />
|
<option name="Build" />
|
||||||
</method>
|
</method>
|
||||||
</configuration>
|
</configuration>
|
||||||
<configuration name="Ombi.Schedule.Tests" type="LaunchSettings" factoryName=".NET Launch Settings Profile">
|
<configuration name="Ombi.Schedule.Tests" type="LaunchSettings" factoryName=".NET Launch Settings Profile">
|
||||||
|
@ -406,7 +453,7 @@
|
||||||
<option name="SEND_DEBUG_REQUEST" value="1" />
|
<option name="SEND_DEBUG_REQUEST" value="1" />
|
||||||
<option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" />
|
<option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Build" enabled="true" />
|
<option name="Build" />
|
||||||
</method>
|
</method>
|
||||||
</configuration>
|
</configuration>
|
||||||
<configuration name="Ombi.Schedule.Tests: IIS Express" type="LaunchSettings" factoryName=".NET Launch Settings Profile">
|
<configuration name="Ombi.Schedule.Tests: IIS Express" type="LaunchSettings" factoryName=".NET Launch Settings Profile">
|
||||||
|
@ -421,7 +468,7 @@
|
||||||
<option name="SEND_DEBUG_REQUEST" value="1" />
|
<option name="SEND_DEBUG_REQUEST" value="1" />
|
||||||
<option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" />
|
<option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Build" enabled="true" />
|
<option name="Build" />
|
||||||
</method>
|
</method>
|
||||||
</configuration>
|
</configuration>
|
||||||
<configuration name="Ombi.Updater" type="LaunchSettings" factoryName=".NET Launch Settings Profile">
|
<configuration name="Ombi.Updater" type="LaunchSettings" factoryName=".NET Launch Settings Profile">
|
||||||
|
@ -436,10 +483,11 @@
|
||||||
<option name="SEND_DEBUG_REQUEST" value="1" />
|
<option name="SEND_DEBUG_REQUEST" value="1" />
|
||||||
<option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" />
|
<option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Build" enabled="true" />
|
<option name="Build" />
|
||||||
</method>
|
</method>
|
||||||
</configuration>
|
</configuration>
|
||||||
</component>
|
</component>
|
||||||
|
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
||||||
<component name="TaskManager">
|
<component name="TaskManager">
|
||||||
<task active="true" id="Default" summary="Default task">
|
<task active="true" id="Default" summary="Default task">
|
||||||
<changelist id="57001998-efde-494a-80b3-d7acfc91f770" name="Default Changelist" comment="" />
|
<changelist id="57001998-efde-494a-80b3-d7acfc91f770" name="Default Changelist" comment="" />
|
||||||
|
@ -448,6 +496,9 @@
|
||||||
<option name="presentableId" value="Default" />
|
<option name="presentableId" value="Default" />
|
||||||
<updated>1563957157468</updated>
|
<updated>1563957157468</updated>
|
||||||
<workItem from="1563957162999" duration="5401000" />
|
<workItem from="1563957162999" duration="5401000" />
|
||||||
|
<workItem from="1745681294313" duration="1814000" />
|
||||||
|
<workItem from="1747080279165" duration="838000" />
|
||||||
|
<workItem from="1747082180432" duration="1994000" />
|
||||||
</task>
|
</task>
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
|
@ -493,7 +544,11 @@
|
||||||
</layout>
|
</layout>
|
||||||
</component>
|
</component>
|
||||||
<component name="TypeScriptGeneratedFilesManager">
|
<component name="TypeScriptGeneratedFilesManager">
|
||||||
<option name="version" value="1" />
|
<option name="version" value="3" />
|
||||||
|
</component>
|
||||||
|
<component name="UnityProjectConfiguration" hasMinimizedUI="false" />
|
||||||
|
<component name="VcsManagerConfiguration">
|
||||||
|
<option name="CLEAR_INITIAL_COMMIT_MESSAGE" value="true" />
|
||||||
</component>
|
</component>
|
||||||
<component name="XDebuggerManager">
|
<component name="XDebuggerManager">
|
||||||
<breakpoint-manager>
|
<breakpoint-manager>
|
||||||
|
@ -505,7 +560,7 @@
|
||||||
<line-breakpoint enabled="true" type="DotNet Breakpoints">
|
<line-breakpoint enabled="true" type="DotNet Breakpoints">
|
||||||
<url>file://$PROJECT_DIR$/Ombi/Controllers/V1/TokenController.cs</url>
|
<url>file://$PROJECT_DIR$/Ombi/Controllers/V1/TokenController.cs</url>
|
||||||
<line>48</line>
|
<line>48</line>
|
||||||
<properties documentPath="$PROJECT_DIR$/Ombi/Controllers/V1/TokenController.cs" initialLine="48">
|
<properties documentPath="$PROJECT_DIR$/Ombi/Controllers/V1/TokenController.cs">
|
||||||
<startOffsets>
|
<startOffsets>
|
||||||
<option value="1518" />
|
<option value="1518" />
|
||||||
</startOffsets>
|
</startOffsets>
|
||||||
|
@ -518,12 +573,12 @@
|
||||||
<line-breakpoint enabled="true" type="DotNet Breakpoints">
|
<line-breakpoint enabled="true" type="DotNet Breakpoints">
|
||||||
<url>file://$PROJECT_DIR$/Ombi.Core/Engine/V2/MultiSearchEngine.cs</url>
|
<url>file://$PROJECT_DIR$/Ombi.Core/Engine/V2/MultiSearchEngine.cs</url>
|
||||||
<line>59</line>
|
<line>59</line>
|
||||||
<properties documentPath="$PROJECT_DIR$/Ombi.Core/Engine/V2/MultiSearchEngine.cs" initialLine="59">
|
<properties documentPath="$PROJECT_DIR$/Ombi.Core/Engine/V2/MultiSearchEngine.cs" containingFunctionPresentation="Method 'MultiSearch'">
|
||||||
<startOffsets>
|
<startOffsets>
|
||||||
<option value="2276" />
|
<option value="2369" />
|
||||||
</startOffsets>
|
</startOffsets>
|
||||||
<endOffsets>
|
<endOffsets>
|
||||||
<option value="2316" />
|
<option value="2576" />
|
||||||
</endOffsets>
|
</endOffsets>
|
||||||
</properties>
|
</properties>
|
||||||
<option name="timeStamp" value="4" />
|
<option name="timeStamp" value="4" />
|
||||||
|
@ -531,12 +586,12 @@
|
||||||
<line-breakpoint enabled="true" type="DotNet Breakpoints">
|
<line-breakpoint enabled="true" type="DotNet Breakpoints">
|
||||||
<url>file://$PROJECT_DIR$/Ombi.Core/Engine/V2/MultiSearchEngine.cs</url>
|
<url>file://$PROJECT_DIR$/Ombi.Core/Engine/V2/MultiSearchEngine.cs</url>
|
||||||
<line>49</line>
|
<line>49</line>
|
||||||
<properties documentPath="$PROJECT_DIR$/Ombi.Core/Engine/V2/MultiSearchEngine.cs" initialLine="49">
|
<properties documentPath="$PROJECT_DIR$/Ombi.Core/Engine/V2/MultiSearchEngine.cs" containingFunctionPresentation="Method 'MultiSearch'">
|
||||||
<startOffsets>
|
<startOffsets>
|
||||||
<option value="2001" />
|
<option value="1903" />
|
||||||
</startOffsets>
|
</startOffsets>
|
||||||
<endOffsets>
|
<endOffsets>
|
||||||
<option value="2002" />
|
<option value="1945" />
|
||||||
</endOffsets>
|
</endOffsets>
|
||||||
</properties>
|
</properties>
|
||||||
<option name="timeStamp" value="5" />
|
<option name="timeStamp" value="5" />
|
||||||
|
@ -544,16 +599,55 @@
|
||||||
<line-breakpoint enabled="true" type="DotNet Breakpoints">
|
<line-breakpoint enabled="true" type="DotNet Breakpoints">
|
||||||
<url>file://$PROJECT_DIR$/Ombi.Api.MusicBrainz/MusicBrainzApi.cs</url>
|
<url>file://$PROJECT_DIR$/Ombi.Api.MusicBrainz/MusicBrainzApi.cs</url>
|
||||||
<line>30</line>
|
<line>30</line>
|
||||||
<properties documentPath="$PROJECT_DIR$/Ombi.Api.MusicBrainz/MusicBrainzApi.cs" initialLine="30">
|
<properties documentPath="$PROJECT_DIR$/Ombi.Api.MusicBrainz/MusicBrainzApi.cs" containingFunctionPresentation="Method 'SearchArtist'">
|
||||||
<startOffsets>
|
<startOffsets>
|
||||||
<option value="917" />
|
<option value="833" />
|
||||||
</startOffsets>
|
</startOffsets>
|
||||||
<endOffsets>
|
<endOffsets>
|
||||||
<option value="1016" />
|
<option value="834" />
|
||||||
</endOffsets>
|
</endOffsets>
|
||||||
</properties>
|
</properties>
|
||||||
<option name="timeStamp" value="7" />
|
<option name="timeStamp" value="7" />
|
||||||
</line-breakpoint>
|
</line-breakpoint>
|
||||||
|
<line-breakpoint enabled="true" type="DotNet Breakpoints">
|
||||||
|
<url>file://$PROJECT_DIR$/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs</url>
|
||||||
|
<line>110</line>
|
||||||
|
<properties documentPath="$PROJECT_DIR$/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs" containingFunctionPresentation="Method 'Execute'">
|
||||||
|
<startOffsets>
|
||||||
|
<option value="5123" />
|
||||||
|
</startOffsets>
|
||||||
|
<endOffsets>
|
||||||
|
<option value="5206" />
|
||||||
|
</endOffsets>
|
||||||
|
</properties>
|
||||||
|
<option name="timeStamp" value="10" />
|
||||||
|
</line-breakpoint>
|
||||||
|
<line-breakpoint enabled="true" type="DotNet Breakpoints">
|
||||||
|
<url>file://$PROJECT_DIR$/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs</url>
|
||||||
|
<line>77</line>
|
||||||
|
<properties documentPath="$PROJECT_DIR$/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs" containingFunctionPresentation="Method 'Execute'">
|
||||||
|
<startOffsets>
|
||||||
|
<option value="3324" />
|
||||||
|
</startOffsets>
|
||||||
|
<endOffsets>
|
||||||
|
<option value="3365" />
|
||||||
|
</endOffsets>
|
||||||
|
</properties>
|
||||||
|
<option name="timeStamp" value="11" />
|
||||||
|
</line-breakpoint>
|
||||||
|
<line-breakpoint enabled="true" type="DotNet Breakpoints">
|
||||||
|
<url>file://$PROJECT_DIR$/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs</url>
|
||||||
|
<line>100</line>
|
||||||
|
<properties documentPath="$PROJECT_DIR$/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs" containingFunctionPresentation="Method 'Execute'">
|
||||||
|
<startOffsets>
|
||||||
|
<option value="4602" />
|
||||||
|
</startOffsets>
|
||||||
|
<endOffsets>
|
||||||
|
<option value="4636" />
|
||||||
|
</endOffsets>
|
||||||
|
</properties>
|
||||||
|
<option name="timeStamp" value="12" />
|
||||||
|
</line-breakpoint>
|
||||||
</breakpoints>
|
</breakpoints>
|
||||||
</breakpoint-manager>
|
</breakpoint-manager>
|
||||||
<watches-manager>
|
<watches-manager>
|
||||||
|
|
14
src/.idea/.idea.Ombi/riderModule.iml
generated
14
src/.idea/.idea.Ombi/riderModule.iml
generated
|
@ -1,14 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module type="RIDER_MODULE" version="4">
|
|
||||||
<component name="NewModuleRootManager">
|
|
||||||
<content url="file://$USER_HOME$/.nuget/packages/microsoft.net.test.sdk/16.0.1/build/netcoreapp1.0" />
|
|
||||||
<content url="file://$USER_HOME$/.nuget/packages/nunit3testadapter/3.13.0/build/netcoreapp1.0/NUnit3.TestAdapter.dll" />
|
|
||||||
<content url="file://$USER_HOME$/.nuget/packages/nunit3testadapter/3.13.0/build/netcoreapp1.0/NUnit3.TestAdapter.pdb" />
|
|
||||||
<content url="file://$USER_HOME$/.nuget/packages/nunit3testadapter/3.13.0/build/netcoreapp1.0/nunit.engine.netstandard.dll" />
|
|
||||||
<content url="file://$MODULE_DIR$/../../../CHANGELOG.md" />
|
|
||||||
<content url="file://$MODULE_DIR$/../../../appveyor.yml" />
|
|
||||||
<content url="file://$MODULE_DIR$/../../../build.cake" />
|
|
||||||
<content url="file://$MODULE_DIR$/../.." />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
25
src/.vscode/tasks.json
vendored
25
src/.vscode/tasks.json
vendored
|
@ -1,22 +1,31 @@
|
||||||
{
|
{
|
||||||
"version": "0.1.0",
|
"version": "2.0.0",
|
||||||
"command": "dotnet",
|
"command": "dotnet",
|
||||||
"isShellCommand": true,
|
|
||||||
"args": [],
|
"args": [],
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
"taskName": "build",
|
"label": "build",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
|
"build",
|
||||||
"${workspaceRoot}/Ombi/Ombi.csproj"
|
"${workspaceRoot}/Ombi/Ombi.csproj"
|
||||||
],
|
],
|
||||||
"isBuildCommand": true,
|
"problemMatcher": "$msCompile",
|
||||||
"problemMatcher": "$msCompile"
|
"group": {
|
||||||
|
"_id": "build",
|
||||||
|
"isDefault": false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"taskName": "lint",
|
"label": "lint",
|
||||||
|
"type": "shell",
|
||||||
"command": "npm",
|
"command": "npm",
|
||||||
"isShellCommand": true,
|
"args": [
|
||||||
"args": ["run", "lint"]
|
"run",
|
||||||
|
"lint"
|
||||||
|
],
|
||||||
|
"problemMatcher": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.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>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
@ -7,6 +7,7 @@ namespace Ombi.Api.Discord.Models
|
||||||
{
|
{
|
||||||
public string content { get; set; }
|
public string content { get; set; }
|
||||||
public string username { get; set; }
|
public string username { get; set; }
|
||||||
|
public string avatar_url { get; set; }
|
||||||
public List<DiscordEmbeds> embeds { get; set; }
|
public List<DiscordEmbeds> embeds { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +33,6 @@ namespace Ombi.Api.Discord.Models
|
||||||
{
|
{
|
||||||
public string name { get; set; }
|
public string name { get; set; }
|
||||||
public string url { get; set; }
|
public string url { get; set; }
|
||||||
public string iconurl { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DiscordField
|
public class DiscordField
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.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>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</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>net6.0</TargetFramework>
|
<TargetFramework>net8.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>net6.0</TargetFramework>
|
<TargetFramework>net8.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>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</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>net6.0</TargetFramework>
|
<TargetFramework>net8.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>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</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>net6.0</TargetFramework>
|
<TargetFramework>net8.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>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</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>net6.0</TargetFramework>
|
<TargetFramework>net8.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>net6.0</TargetFramework>
|
<TargetFramework>net8.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>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</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>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
@ -29,5 +29,6 @@ namespace Ombi.Api.Plex
|
||||||
Task<PlexAddWrapper> AddUser(string emailAddress, string serverId, string authToken, int[] libs);
|
Task<PlexAddWrapper> AddUser(string emailAddress, string serverId, string authToken, int[] libs);
|
||||||
Task<PlexWatchlistContainer> GetWatchlist(string plexToken, CancellationToken cancellationToken);
|
Task<PlexWatchlistContainer> GetWatchlist(string plexToken, CancellationToken cancellationToken);
|
||||||
Task<PlexWatchlistMetadataContainer> GetWatchlistMetadata(string ratingKey, string plexToken, CancellationToken cancellationToken);
|
Task<PlexWatchlistMetadataContainer> GetWatchlistMetadata(string ratingKey, string plexToken, CancellationToken cancellationToken);
|
||||||
|
Task<bool> Ping(string authToken, CancellationToken cancellationToken = default);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -22,6 +22,18 @@ namespace Ombi.Api.Plex.Models.Friends
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[XmlAttribute(AttributeName = "home")]
|
[XmlAttribute(AttributeName = "home")]
|
||||||
public bool HomeUser { get; set; }
|
public bool HomeUser { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "Server")]
|
||||||
|
public PlexUserServer[] Server { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PlexUserServer
|
||||||
|
{
|
||||||
|
[XmlAttribute(AttributeName = "id")]
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute(AttributeName = "serverId")]
|
||||||
|
public string ServerId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[XmlRoot(ElementName = "MediaContainer")]
|
[XmlRoot(ElementName = "MediaContainer")]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.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>
|
||||||
|
|
|
@ -68,7 +68,7 @@ namespace Ombi.Api.Plex
|
||||||
private const string FriendsUri = "https://plex.tv/api/users";
|
private const string FriendsUri = "https://plex.tv/api/users";
|
||||||
private const string GetAccountUri = "https://plex.tv/users/account.json";
|
private const string GetAccountUri = "https://plex.tv/users/account.json";
|
||||||
private const string ServerUri = "https://plex.tv/pms/servers.xml";
|
private const string ServerUri = "https://plex.tv/pms/servers.xml";
|
||||||
private const string WatchlistUri = "https://metadata.provider.plex.tv/";
|
private const string WatchlistUri = "https://discover.provider.plex.tv/";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sign into the Plex API
|
/// Sign into the Plex API
|
||||||
|
@ -320,6 +320,30 @@ namespace Ombi.Api.Plex
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pings the Plex API to validate if a token is still valid
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="authToken">The authentication token to validate</param>
|
||||||
|
/// <param name="cancellationToken">Cancellation token</param>
|
||||||
|
/// <returns>True if the token is valid, false otherwise</returns>
|
||||||
|
public async Task<bool> Ping(string authToken, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var request = new Request("api/v2/ping", "https://plex.tv/", HttpMethod.Get);
|
||||||
|
await AddHeaders(request, authToken);
|
||||||
|
|
||||||
|
// We don't need to parse the response, just check if the request succeeds
|
||||||
|
await Api.Request(request, cancellationToken);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// If the request fails (401, 403, etc.), the token is invalid
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the required headers and also the authorization header
|
/// Adds the required headers and also the authorization header
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.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>net6.0</TargetFramework>
|
<TargetFramework>net8.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>net6.0</TargetFramework>
|
<TargetFramework>net8.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="6.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</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>net6.0</TargetFramework>
|
<TargetFramework>net8.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="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</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>net6.0</TargetFramework>
|
<TargetFramework>net8.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>net6.0</TargetFramework>
|
<TargetFramework>net8.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>
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace Ombi.Api.Sonarr
|
||||||
|
|
||||||
public async Task<List<MonitoredEpisodeResult>> MonitorEpisode(int[] episodeIds, bool monitor, string apiKey, string baseUrl)
|
public async Task<List<MonitoredEpisodeResult>> MonitorEpisode(int[] episodeIds, bool monitor, string apiKey, string baseUrl)
|
||||||
{
|
{
|
||||||
var request = new Request($"{ApiBaseUrl}Episode/monitor", baseUrl, HttpMethod.Put);
|
var request = new Request($"{ApiBaseUrl}episode/monitor", baseUrl, HttpMethod.Put);
|
||||||
request.AddHeader("X-Api-Key", apiKey);
|
request.AddHeader("X-Api-Key", apiKey);
|
||||||
request.AddJsonBody(new { episodeIds = episodeIds, monitored = monitor });
|
request.AddJsonBody(new { episodeIds = episodeIds, monitored = monitor });
|
||||||
return await Api.Request<List<MonitoredEpisodeResult>>(request);
|
return await Api.Request<List<MonitoredEpisodeResult>>(request);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</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>net6.0</TargetFramework>
|
<TargetFramework>net8.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>net6.0</TargetFramework>
|
<TargetFramework>net8.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>net6.0</TargetFramework>
|
<TargetFramework>net8.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>net6.0</TargetFramework>
|
<TargetFramework>net8.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>net6.0</TargetFramework>
|
<TargetFramework>net8.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="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<PackageReference Include="Polly" Version="7.2.3" />
|
<PackageReference Include="Polly" Version="7.2.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -300,13 +300,13 @@ namespace Ombi.Core.Tests.Engine
|
||||||
{
|
{
|
||||||
UserId = "id1",
|
UserId = "id1",
|
||||||
RequestType = RequestType.Movie,
|
RequestType = RequestType.Movie,
|
||||||
RequestDate = today.AddHours(-1),
|
RequestDate = today.AddMinutes(-1),
|
||||||
},
|
},
|
||||||
new RequestLog
|
new RequestLog
|
||||||
{
|
{
|
||||||
UserId = "id1",
|
UserId = "id1",
|
||||||
RequestType = RequestType.Movie,
|
RequestType = RequestType.Movie,
|
||||||
RequestDate = today.AddHours(-2),
|
RequestDate = today.AddMinutes(-2),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
|
|
@ -298,13 +298,13 @@ namespace Ombi.Core.Tests.Engine
|
||||||
{
|
{
|
||||||
UserId = "id1",
|
UserId = "id1",
|
||||||
RequestType = RequestType.Album,
|
RequestType = RequestType.Album,
|
||||||
RequestDate = today.AddHours(-1),
|
RequestDate = today.AddMinutes(-1),
|
||||||
},
|
},
|
||||||
new RequestLog
|
new RequestLog
|
||||||
{
|
{
|
||||||
UserId = "id1",
|
UserId = "id1",
|
||||||
RequestType = RequestType.Album,
|
RequestType = RequestType.Album,
|
||||||
RequestDate = today.AddHours(-2),
|
RequestDate = today.AddMinutes(-2),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
|
|
@ -304,7 +304,7 @@ namespace Ombi.Core.Tests.Engine
|
||||||
{
|
{
|
||||||
UserId = "id1",
|
UserId = "id1",
|
||||||
RequestType = RequestType.TvShow,
|
RequestType = RequestType.TvShow,
|
||||||
RequestDate = today.AddHours(-1),
|
RequestDate = today.AddMinutes(-1),
|
||||||
EpisodeCount = 1,
|
EpisodeCount = 1,
|
||||||
},
|
},
|
||||||
new RequestLog
|
new RequestLog
|
||||||
|
@ -312,7 +312,7 @@ namespace Ombi.Core.Tests.Engine
|
||||||
UserId = "id1",
|
UserId = "id1",
|
||||||
RequestType = RequestType.TvShow,
|
RequestType = RequestType.TvShow,
|
||||||
EpisodeCount = 1,
|
EpisodeCount = 1,
|
||||||
RequestDate = today.AddHours(-2),
|
RequestDate = today.AddMinutes(-2),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
@ -345,7 +345,7 @@ namespace Ombi.Core.Tests.Engine
|
||||||
{
|
{
|
||||||
UserId = "id1",
|
UserId = "id1",
|
||||||
RequestType = RequestType.TvShow,
|
RequestType = RequestType.TvShow,
|
||||||
RequestDate = today.AddHours(-1),
|
RequestDate = today.AddMinutes(-1),
|
||||||
EpisodeCount = 5,
|
EpisodeCount = 5,
|
||||||
},
|
},
|
||||||
new RequestLog
|
new RequestLog
|
||||||
|
@ -353,7 +353,7 @@ namespace Ombi.Core.Tests.Engine
|
||||||
UserId = "id1",
|
UserId = "id1",
|
||||||
RequestType = RequestType.TvShow,
|
RequestType = RequestType.TvShow,
|
||||||
EpisodeCount = 4,
|
EpisodeCount = 4,
|
||||||
RequestDate = today.AddHours(-2),
|
RequestDate = today.AddMinutes(-2),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.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.18.0" />
|
<PackageReference Include="AutoFixture" Version="4.18.0" />
|
||||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
|
||||||
<PackageReference Include="Moq" Version="4.18.2" />
|
<PackageReference Include="Moq" Version="4.18.2" />
|
||||||
<PackageReference Include="Moq.AutoMock" Version="3.4.0" />
|
<PackageReference Include="Moq.AutoMock" Version="3.4.0" />
|
||||||
<PackageReference Include="Nunit" Version="3.13.3" />
|
<PackageReference Include="Nunit" Version="3.13.3" />
|
||||||
|
|
52
src/Ombi.Core/Authentication/PlexTokenKeepAliveService.cs
Normal file
52
src/Ombi.Core/Authentication/PlexTokenKeepAliveService.cs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Ombi.Api.Plex;
|
||||||
|
|
||||||
|
namespace Ombi.Core.Authentication
|
||||||
|
{
|
||||||
|
public interface IPlexTokenKeepAliveService
|
||||||
|
{
|
||||||
|
Task<bool> KeepTokenAliveAsync(string token, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PlexTokenKeepAliveService : IPlexTokenKeepAliveService
|
||||||
|
{
|
||||||
|
private readonly IPlexApi _plexApi;
|
||||||
|
private readonly ILogger<PlexTokenKeepAliveService> _logger;
|
||||||
|
|
||||||
|
public PlexTokenKeepAliveService(IPlexApi plexApi, ILogger<PlexTokenKeepAliveService> logger)
|
||||||
|
{
|
||||||
|
_plexApi = plexApi;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> KeepTokenAliveAsync(string token, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(token))
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Token is null or empty");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the Ping method to validate the token
|
||||||
|
var isValid = await _plexApi.Ping(token, cancellationToken);
|
||||||
|
|
||||||
|
if (!isValid)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Token validation failed - token may be expired or invalid");
|
||||||
|
}
|
||||||
|
|
||||||
|
return isValid;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error occurred while keeping token alive");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -598,13 +598,13 @@ namespace Ombi.Core.Engine
|
||||||
|
|
||||||
public async Task<RequestEngineResult> ApproveMovieById(int requestId, bool is4K)
|
public async Task<RequestEngineResult> ApproveMovieById(int requestId, bool is4K)
|
||||||
{
|
{
|
||||||
var request = await MovieRepository.Find(requestId);
|
var request = await MovieRepository.GetWithUser().FirstOrDefaultAsync(x => x.Id == requestId);
|
||||||
return await ApproveMovie(request, is4K);
|
return await ApproveMovie(request, is4K);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<RequestEngineResult> DenyMovieById(int modelId, string denyReason, bool is4K)
|
public async Task<RequestEngineResult> DenyMovieById(int modelId, string denyReason, bool is4K)
|
||||||
{
|
{
|
||||||
var request = await MovieRepository.Find(modelId);
|
var request = await MovieRepository.GetWithUser().FirstOrDefaultAsync(x => x.Id == modelId);
|
||||||
if (request == null)
|
if (request == null)
|
||||||
{
|
{
|
||||||
return new RequestEngineResult
|
return new RequestEngineResult
|
||||||
|
@ -790,7 +790,7 @@ namespace Ombi.Core.Engine
|
||||||
|
|
||||||
public async Task<RequestEngineResult> ReProcessRequest(int requestId, bool is4K, CancellationToken cancellationToken)
|
public async Task<RequestEngineResult> ReProcessRequest(int requestId, bool is4K, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var request = await MovieRepository.Find(requestId);
|
var request = await MovieRepository.GetWithUser().FirstOrDefaultAsync(x => x.Id == requestId);
|
||||||
if (request == null)
|
if (request == null)
|
||||||
{
|
{
|
||||||
return new RequestEngineResult
|
return new RequestEngineResult
|
||||||
|
@ -805,7 +805,7 @@ namespace Ombi.Core.Engine
|
||||||
|
|
||||||
public async Task<RequestEngineResult> MarkUnavailable(int modelId, bool is4K)
|
public async Task<RequestEngineResult> MarkUnavailable(int modelId, bool is4K)
|
||||||
{
|
{
|
||||||
var request = await MovieRepository.Find(modelId);
|
var request = await MovieRepository.GetWithUser().FirstOrDefaultAsync(x => x.Id == modelId);
|
||||||
if (request == null)
|
if (request == null)
|
||||||
{
|
{
|
||||||
return new RequestEngineResult
|
return new RequestEngineResult
|
||||||
|
@ -834,7 +834,7 @@ namespace Ombi.Core.Engine
|
||||||
|
|
||||||
public async Task<RequestEngineResult> MarkAvailable(int modelId, bool is4K)
|
public async Task<RequestEngineResult> MarkAvailable(int modelId, bool is4K)
|
||||||
{
|
{
|
||||||
var request = await MovieRepository.Find(modelId);
|
var request = await MovieRepository.GetWithUser().FirstOrDefaultAsync(x => x.Id == modelId);
|
||||||
if (request == null)
|
if (request == null)
|
||||||
{
|
{
|
||||||
return new RequestEngineResult
|
return new RequestEngineResult
|
||||||
|
|
67
src/Ombi.Core/Helpers/DatabaseConfigurationSetup.cs
Normal file
67
src/Ombi.Core/Helpers/DatabaseConfigurationSetup.cs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal;
|
||||||
|
using Ombi.Core.Models;
|
||||||
|
using Polly;
|
||||||
|
using Pomelo.EntityFrameworkCore.MySql.Storage.Internal;
|
||||||
|
|
||||||
|
namespace Ombi.Core.Helpers;
|
||||||
|
|
||||||
|
public static class DatabaseConfigurationSetup
|
||||||
|
{
|
||||||
|
public static void ConfigurePostgres(DbContextOptionsBuilder options, PerDatabaseConfiguration config)
|
||||||
|
{
|
||||||
|
options.UseNpgsql(config.ConnectionString, b =>
|
||||||
|
{
|
||||||
|
b.EnableRetryOnFailure();
|
||||||
|
}).ReplaceService<ISqlGenerationHelper, NpgsqlCaseInsensitiveSqlGenerationHelper>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ConfigureMySql(DbContextOptionsBuilder options, PerDatabaseConfiguration config)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(config.ConnectionString))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("ConnectionString for the MySql/Mariadb database is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
options.UseMySql(config.ConnectionString, GetServerVersion(config.ConnectionString), b =>
|
||||||
|
{
|
||||||
|
//b.CharSetBehavior(Pomelo.EntityFrameworkCore.MySql.Infrastructure.CharSetBehavior.NeverAppend); // ##ISSUE, link to migrations?
|
||||||
|
b.EnableRetryOnFailure();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ServerVersion GetServerVersion(string connectionString)
|
||||||
|
{
|
||||||
|
// Workaround Windows bug, that can lead to the following exception:
|
||||||
|
//
|
||||||
|
// MySqlConnector.MySqlException (0x80004005): SSL Authentication Error
|
||||||
|
// ---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
|
||||||
|
// ---> System.ComponentModel.Win32Exception (0x8009030F): The message or signature supplied for verification has been altered
|
||||||
|
//
|
||||||
|
// See https://github.com/dotnet/runtime/issues/17005#issuecomment-305848835
|
||||||
|
//
|
||||||
|
// Also workaround for the fact, that ServerVersion.AutoDetect() does not use any retrying strategy.
|
||||||
|
ServerVersion serverVersion = null;
|
||||||
|
#pragma warning disable EF1001
|
||||||
|
var retryPolicy = Policy.Handle<Exception>(exception => MySqlTransientExceptionDetector.ShouldRetryOn(exception))
|
||||||
|
#pragma warning restore EF1001
|
||||||
|
.WaitAndRetry(3, (count, context) => TimeSpan.FromMilliseconds(count * 250));
|
||||||
|
|
||||||
|
serverVersion = retryPolicy.Execute(() => serverVersion = ServerVersion.AutoDetect(connectionString));
|
||||||
|
|
||||||
|
return serverVersion;
|
||||||
|
}
|
||||||
|
public class NpgsqlCaseInsensitiveSqlGenerationHelper : NpgsqlSqlGenerationHelper
|
||||||
|
{
|
||||||
|
const string EFMigrationsHisory = "__EFMigrationsHistory";
|
||||||
|
public NpgsqlCaseInsensitiveSqlGenerationHelper(RelationalSqlGenerationHelperDependencies dependencies)
|
||||||
|
: base(dependencies) { }
|
||||||
|
public override string DelimitIdentifier(string identifier) =>
|
||||||
|
base.DelimitIdentifier(identifier == EFMigrationsHisory ? identifier : identifier.ToLower());
|
||||||
|
public override void DelimitIdentifier(StringBuilder builder, string identifier)
|
||||||
|
=> base.DelimitIdentifier(builder, identifier == EFMigrationsHisory ? identifier : identifier.ToLower());
|
||||||
|
}
|
||||||
|
}
|
10
src/Ombi.Core/Helpers/FileSystem.cs
Normal file
10
src/Ombi.Core/Helpers/FileSystem.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
namespace Ombi.Core.Helpers;
|
||||||
|
|
||||||
|
public class FileSystem : IFileSystem
|
||||||
|
{
|
||||||
|
public bool FileExists(string path)
|
||||||
|
{
|
||||||
|
return System.IO.File.Exists(path);
|
||||||
|
}
|
||||||
|
// Implement other file system operations as needed
|
||||||
|
}
|
7
src/Ombi.Core/Helpers/IFileSystem.cs
Normal file
7
src/Ombi.Core/Helpers/IFileSystem.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Ombi.Core.Helpers;
|
||||||
|
|
||||||
|
public interface IFileSystem
|
||||||
|
{
|
||||||
|
bool FileExists(string path);
|
||||||
|
// Add other file system operations as needed
|
||||||
|
}
|
40
src/Ombi.Core/Models/DatabaseConfiguration.cs
Normal file
40
src/Ombi.Core/Models/DatabaseConfiguration.cs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Ombi.Core.Models;
|
||||||
|
|
||||||
|
public class DatabaseConfiguration
|
||||||
|
{
|
||||||
|
public const string SqliteDatabase = "Sqlite";
|
||||||
|
|
||||||
|
public DatabaseConfiguration()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public DatabaseConfiguration(string defaultSqlitePath)
|
||||||
|
{
|
||||||
|
OmbiDatabase = new PerDatabaseConfiguration(SqliteDatabase, $"Data Source={Path.Combine(defaultSqlitePath, "Ombi.db")}");
|
||||||
|
SettingsDatabase = new PerDatabaseConfiguration(SqliteDatabase, $"Data Source={Path.Combine(defaultSqlitePath, "OmbiSettings.db")}");
|
||||||
|
ExternalDatabase = new PerDatabaseConfiguration(SqliteDatabase, $"Data Source={Path.Combine(defaultSqlitePath, "OmbiExternal.db")}");
|
||||||
|
}
|
||||||
|
public PerDatabaseConfiguration OmbiDatabase { get; set; }
|
||||||
|
public PerDatabaseConfiguration SettingsDatabase { get; set; }
|
||||||
|
public PerDatabaseConfiguration ExternalDatabase { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PerDatabaseConfiguration
|
||||||
|
{
|
||||||
|
public PerDatabaseConfiguration(string type, string connectionString)
|
||||||
|
{
|
||||||
|
Type = type;
|
||||||
|
ConnectionString = connectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used in Deserialization
|
||||||
|
public PerDatabaseConfiguration()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
public string Type { get; set; }
|
||||||
|
public string ConnectionString { get; set; }
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
@ -13,8 +13,8 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AutoMapper" Version="12.0.0" />
|
<PackageReference Include="AutoMapper" Version="12.0.0" />
|
||||||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.0" />
|
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="6.0.9" />
|
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.5" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.9" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.5" />
|
||||||
<PackageReference Include="MusicBrainzAPI" Version="2.5.0" />
|
<PackageReference Include="MusicBrainzAPI" Version="2.5.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<PackageReference Include="System.Diagnostics.Process" Version="4.3.0" />
|
<PackageReference Include="System.Diagnostics.Process" Version="4.3.0" />
|
||||||
|
|
|
@ -69,7 +69,7 @@ namespace Ombi.Core.Senders
|
||||||
}
|
}
|
||||||
if (radarrSettings.Enabled)
|
if (radarrSettings.Enabled)
|
||||||
{
|
{
|
||||||
return await SendToRadarr(model, radarrSettings);
|
return await SendToRadarr(model, radarrSettings, is4K);
|
||||||
}
|
}
|
||||||
|
|
||||||
var dogSettings = await _dogNzbSettings.GetSettingsAsync();
|
var dogSettings = await _dogNzbSettings.GetSettingsAsync();
|
||||||
|
@ -133,7 +133,7 @@ namespace Ombi.Core.Senders
|
||||||
return await _dogNzbApi.AddMovie(settings.ApiKey, id);
|
return await _dogNzbApi.AddMovie(settings.ApiKey, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<SenderResult> SendToRadarr(MovieRequests model, RadarrSettings settings)
|
private async Task<SenderResult> SendToRadarr(MovieRequests model, RadarrSettings settings, bool is4k)
|
||||||
{
|
{
|
||||||
var qualityToUse = int.Parse(settings.DefaultQualityProfile);
|
var qualityToUse = int.Parse(settings.DefaultQualityProfile);
|
||||||
|
|
||||||
|
@ -142,17 +142,35 @@ namespace Ombi.Core.Senders
|
||||||
var profiles = await _userProfiles.GetAll().FirstOrDefaultAsync(x => x.UserId == model.RequestedUserId);
|
var profiles = await _userProfiles.GetAll().FirstOrDefaultAsync(x => x.UserId == model.RequestedUserId);
|
||||||
if (profiles != null)
|
if (profiles != null)
|
||||||
{
|
{
|
||||||
if (profiles.RadarrRootPath > 0)
|
if (is4k)
|
||||||
{
|
{
|
||||||
var tempPath = await RadarrRootPath(profiles.RadarrRootPath, settings);
|
if (profiles.Radarr4KRootPath > 0)
|
||||||
if (tempPath.HasValue())
|
|
||||||
{
|
{
|
||||||
rootFolderPath = tempPath;
|
var tempPath = await RadarrRootPath(profiles.Radarr4KRootPath, settings);
|
||||||
|
if (tempPath.HasValue())
|
||||||
|
{
|
||||||
|
rootFolderPath = tempPath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if (profiles.Radarr4KQualityProfile > 0)
|
||||||
if (profiles.RadarrQualityProfile > 0)
|
{
|
||||||
|
qualityToUse = profiles.Radarr4KQualityProfile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
qualityToUse = profiles.RadarrQualityProfile;
|
if (profiles.RadarrRootPath > 0)
|
||||||
|
{
|
||||||
|
var tempPath = await RadarrRootPath(profiles.RadarrRootPath, settings);
|
||||||
|
if (tempPath.HasValue())
|
||||||
|
{
|
||||||
|
rootFolderPath = tempPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (profiles.RadarrQualityProfile > 0)
|
||||||
|
{
|
||||||
|
qualityToUse = profiles.RadarrQualityProfile;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +182,10 @@ namespace Ombi.Core.Senders
|
||||||
if (settings.SendUserTags)
|
if (settings.SendUserTags)
|
||||||
{
|
{
|
||||||
var userTag = await GetOrCreateTag(model, settings);
|
var userTag = await GetOrCreateTag(model, settings);
|
||||||
tags.Add(userTag.id);
|
if (userTag != null)
|
||||||
|
{
|
||||||
|
tags.Add(userTag.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overrides on the request take priority
|
// Overrides on the request take priority
|
||||||
|
@ -180,7 +201,9 @@ namespace Ombi.Core.Senders
|
||||||
List<MovieResponse> movies;
|
List<MovieResponse> movies;
|
||||||
// Check if the movie already exists? Since it could be unmonitored
|
// Check if the movie already exists? Since it could be unmonitored
|
||||||
|
|
||||||
movies = await _radarrV3Api.GetMovies(settings.ApiKey, settings.FullUri);
|
// Get the appropriate Radarr instance settings for existence check
|
||||||
|
var existenceCheckSettings = is4k ? await _radarr4KSettings.GetSettingsAsync() : settings;
|
||||||
|
movies = await _radarrV3Api.GetMovies(existenceCheckSettings.ApiKey, existenceCheckSettings.FullUri);
|
||||||
|
|
||||||
var existingMovie = movies.FirstOrDefault(x => x.tmdbId == model.TheMovieDbId);
|
var existingMovie = movies.FirstOrDefault(x => x.tmdbId == model.TheMovieDbId);
|
||||||
if (existingMovie == null)
|
if (existingMovie == null)
|
||||||
|
@ -228,6 +251,12 @@ namespace Ombi.Core.Senders
|
||||||
|
|
||||||
private async Task<Tag> GetOrCreateTag(MovieRequests model, RadarrSettings s)
|
private async Task<Tag> GetOrCreateTag(MovieRequests model, RadarrSettings s)
|
||||||
{
|
{
|
||||||
|
if (model.RequestedUser == null)
|
||||||
|
{
|
||||||
|
_log.LogWarning("Cannot create tag - RequestedUser is null for movie request {MovieTitle}", model.Title);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var tagName = model.RequestedUser.UserName;
|
var tagName = model.RequestedUser.UserName;
|
||||||
// Does tag exist?
|
// Does tag exist?
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.VisualBasic;
|
|
||||||
using Ombi.Api.DogNzb;
|
|
||||||
using Ombi.Api.DogNzb.Models;
|
|
||||||
using Ombi.Api.SickRage;
|
using Ombi.Api.SickRage;
|
||||||
using Ombi.Api.SickRage.Models;
|
using Ombi.Api.SickRage.Models;
|
||||||
using Ombi.Api.Sonarr;
|
using Ombi.Api.Sonarr;
|
||||||
|
@ -23,15 +19,13 @@ namespace Ombi.Core.Senders
|
||||||
{
|
{
|
||||||
public class TvSender : ITvSender
|
public class TvSender : ITvSender
|
||||||
{
|
{
|
||||||
public TvSender(ISonarrApi sonarrApi, ISonarrV3Api sonarrV3Api, ILogger<TvSender> log, ISettingsService<SonarrSettings> sonarrSettings,
|
public TvSender(ISonarrV3Api sonarrV3Api, ILogger<TvSender> log, ISettingsService<SonarrSettings> sonarrSettings,
|
||||||
ISettingsService<DogNzbSettings> dog, IDogNzbApi dogApi, ISettingsService<SickRageSettings> srSettings,
|
ISettingsService<SickRageSettings> srSettings,
|
||||||
ISickRageApi srApi, IRepository<UserQualityProfiles> userProfiles, IRepository<RequestQueue> requestQueue, INotificationHelper notify)
|
ISickRageApi srApi, IRepository<UserQualityProfiles> userProfiles, IRepository<RequestQueue> requestQueue, INotificationHelper notify)
|
||||||
{
|
{
|
||||||
SonarrApi = sonarrV3Api;
|
SonarrApi = sonarrV3Api;
|
||||||
Logger = log;
|
Logger = log;
|
||||||
SonarrSettings = sonarrSettings;
|
SonarrSettings = sonarrSettings;
|
||||||
DogNzbSettings = dog;
|
|
||||||
DogNzbApi = dogApi;
|
|
||||||
SickRageSettings = srSettings;
|
SickRageSettings = srSettings;
|
||||||
SickRageApi = srApi;
|
SickRageApi = srApi;
|
||||||
UserQualityProfiles = userProfiles;
|
UserQualityProfiles = userProfiles;
|
||||||
|
@ -40,11 +34,9 @@ namespace Ombi.Core.Senders
|
||||||
}
|
}
|
||||||
|
|
||||||
private ISonarrV3Api SonarrApi { get; }
|
private ISonarrV3Api SonarrApi { get; }
|
||||||
private IDogNzbApi DogNzbApi { get; }
|
|
||||||
private ISickRageApi SickRageApi { get; }
|
private ISickRageApi SickRageApi { get; }
|
||||||
private ILogger<TvSender> Logger { get; }
|
private ILogger<TvSender> Logger { get; }
|
||||||
private ISettingsService<SonarrSettings> SonarrSettings { get; }
|
private ISettingsService<SonarrSettings> SonarrSettings { get; }
|
||||||
private ISettingsService<DogNzbSettings> DogNzbSettings { get; }
|
|
||||||
private ISettingsService<SickRageSettings> SickRageSettings { get; }
|
private ISettingsService<SickRageSettings> SickRageSettings { get; }
|
||||||
private IRepository<UserQualityProfiles> UserQualityProfiles { get; }
|
private IRepository<UserQualityProfiles> UserQualityProfiles { get; }
|
||||||
private readonly IRepository<RequestQueue> _requestQueueRepository;
|
private readonly IRepository<RequestQueue> _requestQueueRepository;
|
||||||
|
@ -67,23 +59,7 @@ namespace Ombi.Core.Senders
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var dog = await DogNzbSettings.GetSettingsAsync();
|
|
||||||
if (dog.Enabled)
|
|
||||||
{
|
|
||||||
var result = await SendToDogNzb(model, dog);
|
|
||||||
if (!result.Failure)
|
|
||||||
{
|
|
||||||
return new SenderResult
|
|
||||||
{
|
|
||||||
Sent = true,
|
|
||||||
Success = true
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return new SenderResult
|
|
||||||
{
|
|
||||||
Message = result.ErrorMessage
|
|
||||||
};
|
|
||||||
}
|
|
||||||
var sr = await SickRageSettings.GetSettingsAsync();
|
var sr = await SickRageSettings.GetSettingsAsync();
|
||||||
if (sr.Enabled)
|
if (sr.Enabled)
|
||||||
{
|
{
|
||||||
|
@ -137,12 +113,6 @@ namespace Ombi.Core.Senders
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<DogNzbAddResult> SendToDogNzb(ChildRequests model, DogNzbSettings settings)
|
|
||||||
{
|
|
||||||
var id = model.ParentRequest.ExternalProviderId;
|
|
||||||
return await DogNzbApi.AddTvShow(settings.ApiKey, id.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Send the request to Sonarr to process
|
/// Send the request to Sonarr to process
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -163,7 +133,14 @@ namespace Ombi.Core.Senders
|
||||||
string seriesType;
|
string seriesType;
|
||||||
int? tagToUse = null;
|
int? tagToUse = null;
|
||||||
|
|
||||||
|
Logger.LogInformation("Starting SendToSonarr for series {Title} (TvDbId: {TvDbId})", model.ParentRequest.Title, model.ParentRequest.TvDbId);
|
||||||
|
Logger.LogInformation("Series type: {SeriesType}", model.SeriesType);
|
||||||
|
|
||||||
var profiles = await UserQualityProfiles.GetAll().FirstOrDefaultAsync(x => x.UserId == model.RequestedUserId);
|
var profiles = await UserQualityProfiles.GetAll().FirstOrDefaultAsync(x => x.UserId == model.RequestedUserId);
|
||||||
|
if (profiles != null)
|
||||||
|
{
|
||||||
|
Logger.LogInformation("Found user quality profile for user {UserId}", model.RequestedUserId);
|
||||||
|
}
|
||||||
|
|
||||||
if (model.SeriesType == SeriesType.Anime)
|
if (model.SeriesType == SeriesType.Anime)
|
||||||
{
|
{
|
||||||
|
@ -171,8 +148,10 @@ namespace Ombi.Core.Senders
|
||||||
// For some reason, if we haven't got one use the first root folder in Sonarr
|
// For some reason, if we haven't got one use the first root folder in Sonarr
|
||||||
if (!int.TryParse(s.RootPathAnime, out int animePath))
|
if (!int.TryParse(s.RootPathAnime, out int animePath))
|
||||||
{
|
{
|
||||||
|
Logger.LogWarning("Failed to parse RootPathAnime: {RootPathAnime}, falling back to main root path", s.RootPathAnime);
|
||||||
animePath = int.Parse(s.RootPath); // Set it to the main root folder if we have no anime folder.
|
animePath = int.Parse(s.RootPath); // Set it to the main root folder if we have no anime folder.
|
||||||
}
|
}
|
||||||
|
Logger.LogInformation("Using anime path ID: {AnimePath}", animePath);
|
||||||
rootFolderPath = await GetSonarrRootPath(animePath, s);
|
rootFolderPath = await GetSonarrRootPath(animePath, s);
|
||||||
languageProfileId = s.LanguageProfileAnime > 0 ? s.LanguageProfileAnime : s.LanguageProfile;
|
languageProfileId = s.LanguageProfileAnime > 0 ? s.LanguageProfileAnime : s.LanguageProfile;
|
||||||
|
|
||||||
|
@ -184,6 +163,7 @@ namespace Ombi.Core.Senders
|
||||||
{
|
{
|
||||||
if (profiles.SonarrRootPathAnime > 0)
|
if (profiles.SonarrRootPathAnime > 0)
|
||||||
{
|
{
|
||||||
|
Logger.LogInformation("Using user's anime root path override: {RootPath}", profiles.SonarrRootPathAnime);
|
||||||
rootFolderPath = await GetSonarrRootPath(profiles.SonarrRootPathAnime, s);
|
rootFolderPath = await GetSonarrRootPath(profiles.SonarrRootPathAnime, s);
|
||||||
}
|
}
|
||||||
if (profiles.SonarrQualityProfileAnime > 0)
|
if (profiles.SonarrQualityProfileAnime > 0)
|
||||||
|
@ -199,11 +179,13 @@ namespace Ombi.Core.Senders
|
||||||
int.TryParse(s.QualityProfile, out qualityToUse);
|
int.TryParse(s.QualityProfile, out qualityToUse);
|
||||||
// Get the root path from the rootfolder selected.
|
// Get the root path from the rootfolder selected.
|
||||||
// For some reason, if we haven't got one use the first root folder in Sonarr
|
// For some reason, if we haven't got one use the first root folder in Sonarr
|
||||||
|
Logger.LogInformation("Using standard path ID: {RootPath}", s.RootPath);
|
||||||
rootFolderPath = await GetSonarrRootPath(int.Parse(s.RootPath), s);
|
rootFolderPath = await GetSonarrRootPath(int.Parse(s.RootPath), s);
|
||||||
if (profiles != null)
|
if (profiles != null)
|
||||||
{
|
{
|
||||||
if (profiles.SonarrRootPath > 0)
|
if (profiles.SonarrRootPath > 0)
|
||||||
{
|
{
|
||||||
|
Logger.LogInformation("Using user's standard root path override: {RootPath}", profiles.SonarrRootPath);
|
||||||
rootFolderPath = await GetSonarrRootPath(profiles.SonarrRootPath, s);
|
rootFolderPath = await GetSonarrRootPath(profiles.SonarrRootPath, s);
|
||||||
}
|
}
|
||||||
if (profiles.SonarrQualityProfile > 0)
|
if (profiles.SonarrQualityProfile > 0)
|
||||||
|
@ -216,32 +198,24 @@ namespace Ombi.Core.Senders
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overrides on the request take priority
|
// Overrides on the request take priority
|
||||||
if (model.ParentRequest.QualityOverride.HasValue)
|
if (model.ParentRequest.QualityOverride.HasValue && model.ParentRequest.QualityOverride.Value > 0)
|
||||||
{
|
{
|
||||||
var qualityOverride = model.ParentRequest.QualityOverride.Value;
|
qualityToUse = model.ParentRequest.QualityOverride.Value;
|
||||||
if (qualityOverride > 0)
|
|
||||||
{
|
|
||||||
qualityToUse = qualityOverride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (model.ParentRequest.RootFolder.HasValue)
|
|
||||||
{
|
|
||||||
var rootfolderOverride = model.ParentRequest.RootFolder.Value;
|
|
||||||
if (rootfolderOverride > 0)
|
|
||||||
{
|
|
||||||
rootFolderPath = await GetSonarrRootPath(rootfolderOverride, s);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model.ParentRequest.LanguageProfile.HasValue)
|
if (model.ParentRequest.RootFolder.HasValue && model.ParentRequest.RootFolder.Value > 0)
|
||||||
{
|
{
|
||||||
var languageProfile = model.ParentRequest.LanguageProfile.Value;
|
Logger.LogInformation("Using request root folder override: {RootFolder}", model.ParentRequest.RootFolder.Value);
|
||||||
if (languageProfile > 0)
|
rootFolderPath = await GetSonarrRootPath(model.ParentRequest.RootFolder.Value, s);
|
||||||
{
|
|
||||||
languageProfileId = languageProfile;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (model.ParentRequest.LanguageProfile.HasValue && model.ParentRequest.LanguageProfile.Value > 0)
|
||||||
|
{
|
||||||
|
languageProfileId = model.ParentRequest.LanguageProfile.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.LogInformation("Final root folder path: {RootFolderPath}", rootFolderPath);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (tagToUse.HasValue)
|
if (tagToUse.HasValue)
|
||||||
|
@ -424,10 +398,11 @@ namespace Ombi.Core.Senders
|
||||||
|
|
||||||
await SonarrApi.MonitorEpisode(epToUnmonitored.Select(x => x.id).ToArray(), false, s.ApiKey, s.FullUri);
|
await SonarrApi.MonitorEpisode(epToUnmonitored.Select(x => x.id).ToArray(), false, s.ApiKey, s.FullUri);
|
||||||
}
|
}
|
||||||
// Now update the episodes that need updating
|
|
||||||
await SonarrApi.MonitorEpisode(episodesToUpdate.Where(x => x.seasonNumber == season.SeasonNumber).Select(x => x.id).ToArray(), true, s.ApiKey, s.FullUri);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now update the episodes that need updating
|
||||||
|
await SonarrApi.MonitorEpisode(episodesToUpdate.Select(x => x.id).ToArray(), true, s.ApiKey, s.FullUri);
|
||||||
|
|
||||||
if (!s.AddOnly)
|
if (!s.AddOnly)
|
||||||
{
|
{
|
||||||
await SearchForRequest(model, sonarrEpList, result, s, episodesToUpdate);
|
await SearchForRequest(model, sonarrEpList, result, s, episodesToUpdate);
|
||||||
|
@ -560,17 +535,36 @@ namespace Ombi.Core.Senders
|
||||||
|
|
||||||
private async Task<string> GetSonarrRootPath(int pathId, SonarrSettings sonarrSettings)
|
private async Task<string> GetSonarrRootPath(int pathId, SonarrSettings sonarrSettings)
|
||||||
{
|
{
|
||||||
|
Logger.LogInformation("Getting Sonarr root path for ID: {PathId}", pathId);
|
||||||
var rootFoldersResult = await SonarrApi.GetRootFolders(sonarrSettings.ApiKey, sonarrSettings.FullUri);
|
var rootFoldersResult = await SonarrApi.GetRootFolders(sonarrSettings.ApiKey, sonarrSettings.FullUri);
|
||||||
|
|
||||||
|
if (rootFoldersResult == null || !rootFoldersResult.Any())
|
||||||
|
{
|
||||||
|
Logger.LogError("No root folders returned from Sonarr API");
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.LogInformation("Found {Count} root folders in Sonarr", rootFoldersResult.Count());
|
||||||
|
foreach (var folder in rootFoldersResult)
|
||||||
|
{
|
||||||
|
Logger.LogDebug("Root folder - ID: {Id}, Path: {Path}", folder.id, folder.path);
|
||||||
|
}
|
||||||
|
|
||||||
if (pathId == 0)
|
if (pathId == 0)
|
||||||
{
|
{
|
||||||
return rootFoldersResult.FirstOrDefault().path;
|
var defaultPath = rootFoldersResult.FirstOrDefault()?.path;
|
||||||
|
Logger.LogInformation("Using first root folder as default: {Path}", defaultPath);
|
||||||
|
return defaultPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var r in rootFoldersResult?.Where(r => r.id == pathId))
|
var matchingFolder = rootFoldersResult.FirstOrDefault(r => r.id == pathId);
|
||||||
|
if (matchingFolder != null)
|
||||||
{
|
{
|
||||||
return r.path;
|
Logger.LogInformation("Found matching root folder for ID {PathId}: {Path}", pathId, matchingFolder.path);
|
||||||
|
return matchingFolder.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger.LogError("No matching root folder found for ID: {PathId}", pathId);
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
69
src/Ombi.Core/Services/DatabaseConfigurationService.cs
Normal file
69
src/Ombi.Core/Services/DatabaseConfigurationService.cs
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Ombi.Core.Helpers;
|
||||||
|
using Ombi.Core.Models;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
|
||||||
|
namespace Ombi.Core.Services;
|
||||||
|
|
||||||
|
public class DatabaseConfigurationService : IDatabaseConfigurationService
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
private readonly IFileSystem _fileSystem;
|
||||||
|
|
||||||
|
public DatabaseConfigurationService(
|
||||||
|
ILogger<DatabaseConfigurationService> logger,
|
||||||
|
IFileSystem fileSystem)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_fileSystem = fileSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> ConfigureDatabase(string databaseType, string connectionString, CancellationToken token)
|
||||||
|
{
|
||||||
|
var i = StartupSingleton.Instance;
|
||||||
|
if (string.IsNullOrEmpty(i.StoragePath))
|
||||||
|
{
|
||||||
|
i.StoragePath = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
var databaseFileLocation = Path.Combine(i.StoragePath, "database.json");
|
||||||
|
if (_fileSystem.FileExists(databaseFileLocation))
|
||||||
|
{
|
||||||
|
var error = $"The database file at '{databaseFileLocation}' already exists";
|
||||||
|
_logger.LogError(error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var configuration = new DatabaseConfiguration
|
||||||
|
{
|
||||||
|
ExternalDatabase = new PerDatabaseConfiguration(databaseType, connectionString),
|
||||||
|
OmbiDatabase = new PerDatabaseConfiguration(databaseType, connectionString),
|
||||||
|
SettingsDatabase = new PerDatabaseConfiguration(databaseType, connectionString)
|
||||||
|
};
|
||||||
|
|
||||||
|
var json = JsonConvert.SerializeObject(configuration, Formatting.Indented);
|
||||||
|
|
||||||
|
_logger.LogInformation("Writing database configuration to file");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await File.WriteAllTextAsync(databaseFileLocation, json, token);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.LogError(e, "Failed to write database configuration to file");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("Database configuration written to file");
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
11
src/Ombi.Core/Services/IDatabaseConfigurationService.cs
Normal file
11
src/Ombi.Core/Services/IDatabaseConfigurationService.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Ombi.Core.Services;
|
||||||
|
|
||||||
|
public interface IDatabaseConfigurationService
|
||||||
|
{
|
||||||
|
const string MySqlDatabase = "MySQL";
|
||||||
|
const string PostgresDatabase = "Postgres";
|
||||||
|
Task<bool> ConfigureDatabase(string databaseType, string connectionString, CancellationToken token);
|
||||||
|
}
|
|
@ -107,6 +107,7 @@ namespace Ombi.DependencyInjection
|
||||||
services.AddTransient<IMusicSender, MusicSender>();
|
services.AddTransient<IMusicSender, MusicSender>();
|
||||||
services.AddTransient<IMassEmailSender, MassEmailSender>();
|
services.AddTransient<IMassEmailSender, MassEmailSender>();
|
||||||
services.AddTransient<IPlexOAuthManager, PlexOAuthManager>();
|
services.AddTransient<IPlexOAuthManager, PlexOAuthManager>();
|
||||||
|
services.AddTransient<IPlexTokenKeepAliveService, PlexTokenKeepAliveService>();
|
||||||
services.AddTransient<IVoteEngine, VoteEngine>();
|
services.AddTransient<IVoteEngine, VoteEngine>();
|
||||||
services.AddTransient<IDemoMovieSearchEngine, DemoMovieSearchEngine>();
|
services.AddTransient<IDemoMovieSearchEngine, DemoMovieSearchEngine>();
|
||||||
services.AddTransient<IDemoTvSearchEngine, DemoTvSearchEngine>();
|
services.AddTransient<IDemoTvSearchEngine, DemoTvSearchEngine>();
|
||||||
|
@ -236,6 +237,8 @@ namespace Ombi.DependencyInjection
|
||||||
services.AddScoped<IFeatureService, FeatureService>();
|
services.AddScoped<IFeatureService, FeatureService>();
|
||||||
services.AddTransient<IRecentlyRequestedService, RecentlyRequestedService>();
|
services.AddTransient<IRecentlyRequestedService, RecentlyRequestedService>();
|
||||||
services.AddTransient<IPlexService, PlexService>();
|
services.AddTransient<IPlexService, PlexService>();
|
||||||
|
services.AddSingleton<IFileSystem, FileSystem>();
|
||||||
|
services.AddSingleton<IDatabaseConfigurationService, DatabaseConfigurationService>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RegisterJobs(this IServiceCollection services)
|
public static void RegisterJobs(this IServiceCollection services)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<Version></Version>
|
<Version></Version>
|
||||||
|
@ -11,9 +11,9 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="6.0.9" />
|
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="8.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.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>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="nunit" Version="3.13.3" />
|
<PackageReference Include="nunit" Version="3.13.3" />
|
||||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
IssueResolved = 9,
|
IssueResolved = 9,
|
||||||
IssueComment = 10,
|
IssueComment = 10,
|
||||||
Newsletter = 11,
|
Newsletter = 11,
|
||||||
PartiallyAvailable = 12
|
PartiallyAvailable = 12,
|
||||||
|
PlexWatchlistTokenExpired = 13
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.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="4.6.0" />
|
<PackageReference Include="EasyCrypto" Version="4.6.0" />
|
||||||
<PackageReference Include="LazyCache.AspNetCore" Version="2.4.0" />
|
<PackageReference Include="LazyCache.AspNetCore" Version="2.4.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<PackageReference Include="Nito.AsyncEx" Version="5.1.2" />
|
<PackageReference Include="Nito.AsyncEx" Version="5.1.2" />
|
||||||
<PackageReference Include="Quartz" Version="3.6.2" />
|
<PackageReference Include="Quartz" Version="3.6.2" />
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</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>net6.0</TargetFramework>
|
<TargetFramework>net8.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>
|
||||||
|
|
|
@ -118,39 +118,39 @@
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<data name="NewAlbums" xml:space="preserve">
|
<data name="NewAlbums" xml:space="preserve">
|
||||||
<value>New Albums</value>
|
<value>Novos álbuns</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NewMovies" xml:space="preserve">
|
<data name="NewMovies" xml:space="preserve">
|
||||||
<value>New Movies</value>
|
<value>Novos filmes</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NewTV" xml:space="preserve">
|
<data name="NewTV" xml:space="preserve">
|
||||||
<value>New TV</value>
|
<value>Novas séries</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="GenresLabel" xml:space="preserve">
|
<data name="GenresLabel" xml:space="preserve">
|
||||||
<value>Gêneros:</value>
|
<value>Gêneros:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AlbumTypeLabel" xml:space="preserve">
|
<data name="AlbumTypeLabel" xml:space="preserve">
|
||||||
<value>Type:</value>
|
<value>Tipo:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SeasonLabel" xml:space="preserve">
|
<data name="SeasonLabel" xml:space="preserve">
|
||||||
<value>Temporada:</value>
|
<value>Temporadas:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EpisodesLabel" xml:space="preserve">
|
<data name="EpisodesLabel" xml:space="preserve">
|
||||||
<value>Episodes:</value>
|
<value>Episódios:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PoweredBy" xml:space="preserve">
|
<data name="PoweredBy" xml:space="preserve">
|
||||||
<value>Powered by</value>
|
<value>Distribuído por</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Unsubscribe" xml:space="preserve">
|
<data name="Unsubscribe" xml:space="preserve">
|
||||||
<value>Unsubscribe</value>
|
<value>Cancelar subscrição</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Album" xml:space="preserve">
|
<data name="Album" xml:space="preserve">
|
||||||
<value>Album</value>
|
<value>Álbum</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Movie" xml:space="preserve">
|
<data name="Movie" xml:space="preserve">
|
||||||
<value>Movie</value>
|
<value>Filmes</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TvShow" xml:space="preserve">
|
<data name="TvShow" xml:space="preserve">
|
||||||
<value>TV Show</value>
|
<value>Séries</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.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,19 +12,16 @@ namespace Ombi.Notifications.Templates
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(_templateLocation))
|
if (string.IsNullOrEmpty(_templateLocation))
|
||||||
{
|
{
|
||||||
#if DEBUG
|
//_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "net6.0", "Templates",
|
||||||
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "net6.0", "Templates",
|
// "BasicTemplate.html");
|
||||||
"BasicTemplate.html");
|
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "Templates", "BasicTemplate.html");
|
||||||
#else
|
|
||||||
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "Templates","BasicTemplate.html");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return _templateLocation;
|
return _templateLocation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string _templateLocation;
|
private string _templateLocation;
|
||||||
|
|
||||||
private const string SubjectKey = "{@SUBJECT}";
|
private const string SubjectKey = "{@SUBJECT}";
|
||||||
private const string BodyKey = "{@BODY}";
|
private const string BodyKey = "{@BODY}";
|
||||||
private const string Poster = "{@POSTER}";
|
private const string Poster = "{@POSTER}";
|
||||||
|
@ -43,9 +40,10 @@ namespace Ombi.Notifications.Templates
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetPosterContent(string imgsrc, string url) {
|
private string GetPosterContent(string imgsrc, string url)
|
||||||
|
{
|
||||||
string posterContent;
|
string posterContent;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(imgsrc))
|
if (string.IsNullOrEmpty(imgsrc))
|
||||||
{
|
{
|
||||||
posterContent = string.Empty;
|
posterContent = string.Empty;
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
{
|
{
|
||||||
public interface INewsletterTemplate
|
public interface INewsletterTemplate
|
||||||
{
|
{
|
||||||
string LoadTemplate(string subject, string intro, string tableHtml, string logo, string unsubscribeLink);
|
string LoadTemplate(string subject, string intro, string tableHtml, string logo, string unsubscribeLink, string applicationUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Ombi.I18n.Resources;
|
using Ombi.I18n.Resources;
|
||||||
|
@ -13,11 +13,9 @@ namespace Ombi.Notifications.Templates
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(_templateLocation))
|
if (string.IsNullOrEmpty(_templateLocation))
|
||||||
{
|
{
|
||||||
#if DEBUG
|
//_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "net6.0", "Templates", "NewsletterTemplate.html");
|
||||||
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "net6.0", "Templates", "NewsletterTemplate.html");
|
|
||||||
#else
|
|
||||||
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "Templates", "NewsletterTemplate.html");
|
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "Templates", "NewsletterTemplate.html");
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return _templateLocation;
|
return _templateLocation;
|
||||||
}
|
}
|
||||||
|
@ -27,6 +25,7 @@ namespace Ombi.Notifications.Templates
|
||||||
|
|
||||||
private const string SubjectKey = "{@SUBJECT}";
|
private const string SubjectKey = "{@SUBJECT}";
|
||||||
private const string DateKey = "{@DATENOW}";
|
private const string DateKey = "{@DATENOW}";
|
||||||
|
private const string AppUrl = "{@APPURL}";
|
||||||
private const string Logo = "{@LOGO}";
|
private const string Logo = "{@LOGO}";
|
||||||
private const string TableLocation = "{@RECENTLYADDED}";
|
private const string TableLocation = "{@RECENTLYADDED}";
|
||||||
private const string IntroText = "{@INTRO}";
|
private const string IntroText = "{@INTRO}";
|
||||||
|
@ -35,13 +34,14 @@ namespace Ombi.Notifications.Templates
|
||||||
private const string PoweredByText = "{@POWEREDBYTEXT}";
|
private const string PoweredByText = "{@POWEREDBYTEXT}";
|
||||||
|
|
||||||
|
|
||||||
public string LoadTemplate(string subject, string intro, string tableHtml, string logo, string unsubscribeLink)
|
public string LoadTemplate(string subject, string intro, string tableHtml, string logo, string unsubscribeLink, string applicationUrl)
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder(File.ReadAllText(TemplateLocation));
|
var sb = new StringBuilder(File.ReadAllText(TemplateLocation));
|
||||||
sb.Replace(SubjectKey, subject);
|
sb.Replace(SubjectKey, subject);
|
||||||
sb.Replace(TableLocation, tableHtml);
|
sb.Replace(TableLocation, tableHtml);
|
||||||
sb.Replace(IntroText, intro);
|
sb.Replace(IntroText, intro);
|
||||||
sb.Replace(DateKey, DateTime.Now.ToString("f"));
|
sb.Replace(DateKey, DateTime.Now.ToString("f"));
|
||||||
|
sb.Replace(AppUrl, applicationUrl);
|
||||||
sb.Replace(Logo, string.IsNullOrEmpty(logo) ? OmbiLogo : logo);
|
sb.Replace(Logo, string.IsNullOrEmpty(logo) ? OmbiLogo : logo);
|
||||||
sb.Replace(Unsubscribe, string.IsNullOrEmpty(unsubscribeLink) ? string.Empty : unsubscribeLink);
|
sb.Replace(Unsubscribe, string.IsNullOrEmpty(unsubscribeLink) ? string.Empty : unsubscribeLink);
|
||||||
sb.Replace(UnsubscribeText, string.IsNullOrEmpty(unsubscribeLink) ? string.Empty : Texts.Unsubscribe);
|
sb.Replace(UnsubscribeText, string.IsNullOrEmpty(unsubscribeLink) ? string.Empty : Texts.Unsubscribe);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.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>
|
||||||
|
|
|
@ -428,7 +428,7 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td valign="top" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif; vertical-align: top;">
|
<td valign="top" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif; vertical-align: top;">
|
||||||
<img src="{@LOGO}" style="border: none; -ms-interpolation-mode: bicubic; max-width: 100%;">
|
<a href="{@APPURL}"><img src="{@LOGO}" style="border: none; -ms-interpolation-mode: bicubic; max-width: 100%;"></a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
<PackageReference Include="Nunit" Version="3.13.3" />
|
<PackageReference Include="Nunit" Version="3.13.3" />
|
||||||
<PackageReference Include="NUnit.ConsoleRunner" Version="3.15.2" />
|
<PackageReference Include="NUnit.ConsoleRunner" Version="3.15.2" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
|
||||||
<packagereference Include="Microsoft.NET.Test.Sdk" Version="17.6.2"></packagereference>
|
<packagereference Include="Microsoft.NET.Test.Sdk" Version="17.6.2"></packagereference>
|
||||||
<PackageReference Include="Moq" Version="4.18.2" />
|
<PackageReference Include="Moq" Version="4.18.2" />
|
||||||
<PackageReference Include="Moq.AutoMock" Version="3.4.0" />
|
<PackageReference Include="Moq.AutoMock" Version="3.4.0" />
|
||||||
|
|
|
@ -108,6 +108,7 @@ namespace Ombi.Notifications.Agents
|
||||||
{
|
{
|
||||||
content = model.Message,
|
content = model.Message,
|
||||||
username = settings.Username ?? "Ombi",
|
username = settings.Username ?? "Ombi",
|
||||||
|
avatar_url = settings.Icon.HasValue() ? settings.Icon : string.Empty
|
||||||
};
|
};
|
||||||
|
|
||||||
var fields = new List<DiscordField>();
|
var fields = new List<DiscordField>();
|
||||||
|
@ -157,10 +158,7 @@ namespace Ombi.Notifications.Agents
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var author = new DiscordAuthor
|
var author = new DiscordAuthor();
|
||||||
{
|
|
||||||
iconurl = settings.Icon.HasValue() ? settings.Icon : string.Empty
|
|
||||||
};
|
|
||||||
|
|
||||||
if (model.Data.TryGetValue("ApplicationUrl", out var appUrl))
|
if (model.Data.TryGetValue("ApplicationUrl", out var appUrl))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.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,7 +12,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Ensure.That" Version="10.1.0" />
|
<PackageReference Include="Ensure.That" Version="10.1.0" />
|
||||||
<PackageReference Include="MailKit" Version="4.1.0" />
|
<PackageReference Include="MailKit" Version="4.6.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -91,12 +91,12 @@ namespace Ombi.Schedule.Tests
|
||||||
new Issues
|
new Issues
|
||||||
{
|
{
|
||||||
Status = IssueStatus.Resolved,
|
Status = IssueStatus.Resolved,
|
||||||
ResovledDate = DateTime.Now.AddDays(-2)
|
ResovledDate = DateTime.UtcNow.AddDays(-2)
|
||||||
},
|
},
|
||||||
new Issues
|
new Issues
|
||||||
{
|
{
|
||||||
Status = IssueStatus.Resolved,
|
Status = IssueStatus.Resolved,
|
||||||
ResovledDate = DateTime.Now.AddDays(-4)
|
ResovledDate = DateTime.UtcNow.AddDays(-4)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
|
||||||
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
<Configurations>Debug;Release;NonUiBuild</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
@ -10,10 +13,10 @@
|
||||||
<PackageReference Include="Moq" Version="4.18.2" />
|
<PackageReference Include="Moq" Version="4.18.2" />
|
||||||
<PackageReference Include="Moq.AutoMock" Version="3.4.0" />
|
<PackageReference Include="Moq.AutoMock" Version="3.4.0" />
|
||||||
<PackageReference Include="Nunit" Version="3.13.3" />
|
<PackageReference Include="Nunit" Version="3.13.3" />
|
||||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
|
||||||
<PackageReference Include="NUnit.ConsoleRunner" Version="3.15.2" />
|
<PackageReference Include="NUnit.ConsoleRunner" Version="3.15.2" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||||
<packagereference Include="Microsoft.NET.Test.Sdk" Version="17.6.2"></packagereference>
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -182,8 +182,6 @@ namespace Ombi.Schedule.Tests
|
||||||
_mocker.Verify<OmbiUserManager>(x => x.UpdateAsync(It.IsAny<OmbiUser>()), Times.Never);
|
_mocker.Verify<OmbiUserManager>(x => x.UpdateAsync(It.IsAny<OmbiUser>()), Times.Never);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task Import_Doesnt_Import_Banned_Users()
|
public async Task Import_Doesnt_Import_Banned_Users()
|
||||||
{
|
{
|
||||||
|
@ -247,7 +245,15 @@ namespace Ombi.Schedule.Tests
|
||||||
Id = "id",
|
Id = "id",
|
||||||
Title = "title",
|
Title = "title",
|
||||||
Username = "username",
|
Username = "username",
|
||||||
HomeUser = true
|
HomeUser = true,
|
||||||
|
Server = new PlexUserServer[]
|
||||||
|
{
|
||||||
|
new PlexUserServer
|
||||||
|
{
|
||||||
|
Id = "1",
|
||||||
|
ServerId = "123"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -257,7 +263,6 @@ namespace Ombi.Schedule.Tests
|
||||||
_mocker.Setup<OmbiUserManager, Task<IdentityResult>>(x => x.AddToRoleAsync(It.Is<OmbiUser>(x => x.UserName == "plex"), OmbiRoles.RequestMovie))
|
_mocker.Setup<OmbiUserManager, Task<IdentityResult>>(x => x.AddToRoleAsync(It.Is<OmbiUser>(x => x.UserName == "plex"), OmbiRoles.RequestMovie))
|
||||||
.ReturnsAsync(IdentityResult.Success);
|
.ReturnsAsync(IdentityResult.Success);
|
||||||
|
|
||||||
|
|
||||||
await _subject.Execute(null);
|
await _subject.Execute(null);
|
||||||
|
|
||||||
_mocker.Verify<OmbiUserManager>(x => x.CreateAsync(It.IsAny<OmbiUser>()), Times.Once);
|
_mocker.Verify<OmbiUserManager>(x => x.CreateAsync(It.IsAny<OmbiUser>()), Times.Once);
|
||||||
|
@ -306,7 +311,15 @@ namespace Ombi.Schedule.Tests
|
||||||
{
|
{
|
||||||
Email = "email",
|
Email = "email",
|
||||||
Id = "id",
|
Id = "id",
|
||||||
Username = "plex"
|
Username = "plex",
|
||||||
|
Server = new PlexUserServer[]
|
||||||
|
{
|
||||||
|
new PlexUserServer
|
||||||
|
{
|
||||||
|
Id = "1",
|
||||||
|
ServerId = "123"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -331,9 +344,9 @@ namespace Ombi.Schedule.Tests
|
||||||
ImportPlexAdmin = false,
|
ImportPlexAdmin = false,
|
||||||
ImportPlexUsers = true,
|
ImportPlexUsers = true,
|
||||||
DefaultRoles = new List<string>
|
DefaultRoles = new List<string>
|
||||||
{
|
{
|
||||||
OmbiRoles.RequestMovie
|
OmbiRoles.RequestMovie
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
_mocker.Setup<IPlexApi, Task<PlexUsers>>(x => x.GetUsers(It.IsAny<string>())).ReturnsAsync(new PlexUsers
|
_mocker.Setup<IPlexApi, Task<PlexUsers>>(x => x.GetUsers(It.IsAny<string>())).ReturnsAsync(new PlexUsers
|
||||||
{
|
{
|
||||||
|
@ -343,7 +356,15 @@ namespace Ombi.Schedule.Tests
|
||||||
{
|
{
|
||||||
Email = "email",
|
Email = "email",
|
||||||
Id = "PLEX_ID",
|
Id = "PLEX_ID",
|
||||||
Username = "user"
|
Username = "user",
|
||||||
|
Server = new PlexUserServer[]
|
||||||
|
{
|
||||||
|
new PlexUserServer
|
||||||
|
{
|
||||||
|
Id = "1",
|
||||||
|
ServerId = "123"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -440,5 +461,98 @@ namespace Ombi.Schedule.Tests
|
||||||
|
|
||||||
_mocker.Verify<IUserDeletionEngine>(x => x.DeleteUser(It.Is<OmbiUser>(x => x.ProviderUserId == "ADMIN_ID" && x.Email == "ADMIN@ADMIN.CO" && x.UserName == "Admin")), Times.Never);
|
_mocker.Verify<IUserDeletionEngine>(x => x.DeleteUser(It.Is<OmbiUser>(x => x.ProviderUserId == "ADMIN_ID" && x.Email == "ADMIN@ADMIN.CO" && x.UserName == "Admin")), Times.Never);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Import_Skips_Users_Without_Server_Access()
|
||||||
|
{
|
||||||
|
_mocker.Setup<ISettingsService<UserManagementSettings>, Task<UserManagementSettings>>(x => x.GetSettingsAsync())
|
||||||
|
.ReturnsAsync(new UserManagementSettings { ImportPlexAdmin = false, ImportPlexUsers = true });
|
||||||
|
_mocker.Setup<IPlexApi, Task<PlexUsers>>(x => x.GetUsers(It.IsAny<string>())).ReturnsAsync(new PlexUsers
|
||||||
|
{
|
||||||
|
User = new UserFriends[]
|
||||||
|
{
|
||||||
|
new UserFriends
|
||||||
|
{
|
||||||
|
Email = "email",
|
||||||
|
Id = "NoServer",
|
||||||
|
Title = "title",
|
||||||
|
Username = "username",
|
||||||
|
Server = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await _subject.Execute(null);
|
||||||
|
|
||||||
|
_mocker.Verify<OmbiUserManager>(x => x.CreateAsync(It.IsAny<OmbiUser>()), Times.Never);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Import_Skips_Users_With_Empty_Server_Array()
|
||||||
|
{
|
||||||
|
_mocker.Setup<ISettingsService<UserManagementSettings>, Task<UserManagementSettings>>(x => x.GetSettingsAsync())
|
||||||
|
.ReturnsAsync(new UserManagementSettings { ImportPlexAdmin = false, ImportPlexUsers = true });
|
||||||
|
_mocker.Setup<IPlexApi, Task<PlexUsers>>(x => x.GetUsers(It.IsAny<string>())).ReturnsAsync(new PlexUsers
|
||||||
|
{
|
||||||
|
User = new UserFriends[]
|
||||||
|
{
|
||||||
|
new UserFriends
|
||||||
|
{
|
||||||
|
Email = "email",
|
||||||
|
Id = "EmptyServer",
|
||||||
|
Title = "title",
|
||||||
|
Username = "username",
|
||||||
|
Server = new PlexUserServer[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await _subject.Execute(null);
|
||||||
|
|
||||||
|
_mocker.Verify<OmbiUserManager>(x => x.CreateAsync(It.IsAny<OmbiUser>()), Times.Never);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Import_Creates_User_With_Server_Access()
|
||||||
|
{
|
||||||
|
_mocker.Setup<ISettingsService<UserManagementSettings>, Task<UserManagementSettings>>(x => x.GetSettingsAsync())
|
||||||
|
.ReturnsAsync(new UserManagementSettings { ImportPlexAdmin = false, ImportPlexUsers = true });
|
||||||
|
_mocker.Setup<IPlexApi, Task<PlexUsers>>(x => x.GetUsers(It.IsAny<string>())).ReturnsAsync(new PlexUsers
|
||||||
|
{
|
||||||
|
User = new UserFriends[]
|
||||||
|
{
|
||||||
|
new UserFriends
|
||||||
|
{
|
||||||
|
Email = "email",
|
||||||
|
Id = "HasServer",
|
||||||
|
Title = "title",
|
||||||
|
Username = "username",
|
||||||
|
Server = new PlexUserServer[]
|
||||||
|
{
|
||||||
|
new PlexUserServer
|
||||||
|
{
|
||||||
|
Id = "1",
|
||||||
|
ServerId = "123"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_mocker.Setup<OmbiUserManager, Task<IdentityResult>>(x => x.CreateAsync(It.Is<OmbiUser>(x =>
|
||||||
|
x.UserName == "username" &&
|
||||||
|
x.Email == "email" &&
|
||||||
|
x.ProviderUserId == "HasServer" &&
|
||||||
|
x.UserType == UserType.PlexUser)))
|
||||||
|
.ReturnsAsync(IdentityResult.Success);
|
||||||
|
|
||||||
|
await _subject.Execute(null);
|
||||||
|
|
||||||
|
_mocker.Verify<OmbiUserManager>(x => x.CreateAsync(It.Is<OmbiUser>(x =>
|
||||||
|
x.UserName == "username" &&
|
||||||
|
x.Email == "email" &&
|
||||||
|
x.ProviderUserId == "HasServer" &&
|
||||||
|
x.UserType == UserType.PlexUser)), Times.Once);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,11 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Ombi.Notifications.Models;
|
||||||
|
using Ombi.Core.Notifications;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Core;
|
||||||
|
using Ombi.Core.Authentication;
|
||||||
|
|
||||||
namespace Ombi.Schedule.Tests
|
namespace Ombi.Schedule.Tests
|
||||||
{
|
{
|
||||||
|
@ -35,12 +40,15 @@ namespace Ombi.Schedule.Tests
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
_mocker = new AutoMocker();
|
_mocker = new AutoMocker();
|
||||||
var um = MockHelper.MockUserManager(new List<OmbiUser> { new OmbiUser { Id = "abc", UserType = UserType.PlexUser, MediaServerToken = "token1", UserName = "abc", NormalizedUserName = "ABC" } });
|
var um = MockHelper.MockUserManager(new List<OmbiUser> { new OmbiUser { Id = "abc", Email = "email@email.com", UserType = UserType.PlexUser, MediaServerToken = "token1", UserName = "abc", NormalizedUserName = "ABC" } });
|
||||||
_mocker.Use(um);
|
_mocker.Use(um);
|
||||||
_context = _mocker.GetMock<IJobExecutionContext>();
|
_context = _mocker.GetMock<IJobExecutionContext>();
|
||||||
_context.Setup(x => x.CancellationToken).Returns(CancellationToken.None);
|
_context.Setup(x => x.CancellationToken).Returns(CancellationToken.None);
|
||||||
|
// Mock the keep-alive service to return true by default
|
||||||
|
_mocker.Use<IPlexTokenKeepAliveService>(Mock.Of<IPlexTokenKeepAliveService>(s => s.KeepTokenAliveAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()) == Task.FromResult(true)));
|
||||||
_subject = _mocker.CreateInstance<PlexWatchlistImport>();
|
_subject = _mocker.CreateInstance<PlexWatchlistImport>();
|
||||||
_mocker.Setup<IRepository<PlexWatchlistUserError>, IQueryable<PlexWatchlistUserError>>(x => x.GetAll()).Returns(new List<PlexWatchlistUserError>().AsQueryable().BuildMock());
|
_mocker.Setup<IRepository<PlexWatchlistUserError>, IQueryable<PlexWatchlistUserError>>(x => x.GetAll()).Returns(new List<PlexWatchlistUserError>().AsQueryable().BuildMock());
|
||||||
|
_mocker.Setup<INotificationHelper>(x => x.Notify(It.IsAny<NotificationOptions>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -682,7 +690,6 @@ namespace Ombi.Schedule.Tests
|
||||||
[Test]
|
[Test]
|
||||||
public async Task MovieRequestFromWatchList_AlreadyImported()
|
public async Task MovieRequestFromWatchList_AlreadyImported()
|
||||||
{
|
{
|
||||||
|
|
||||||
_mocker.Setup<ISettingsService<PlexSettings>, Task<PlexSettings>>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true });
|
_mocker.Setup<ISettingsService<PlexSettings>, Task<PlexSettings>>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true });
|
||||||
_mocker.Setup<IPlexApi, Task<PlexWatchlistContainer>>(x => x.GetWatchlist(It.IsAny<string>(), It.IsAny<CancellationToken>())).ReturnsAsync(new PlexWatchlistContainer
|
_mocker.Setup<IPlexApi, Task<PlexWatchlistContainer>>(x => x.GetWatchlist(It.IsAny<string>(), It.IsAny<CancellationToken>())).ReturnsAsync(new PlexWatchlistContainer
|
||||||
{
|
{
|
||||||
|
@ -719,7 +726,7 @@ namespace Ombi.Schedule.Tests
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
_mocker.Setup<IExternalRepository<PlexWatchlistHistory>, IQueryable<PlexWatchlistHistory>>(x => x.GetAll()).Returns(new List<PlexWatchlistHistory> { new PlexWatchlistHistory { Id = 1, TmdbId = "123" } }.AsQueryable());
|
_mocker.Setup<IExternalRepository<PlexWatchlistHistory>, IQueryable<PlexWatchlistHistory>>(x => x.GetAll()).Returns(new List<PlexWatchlistHistory> { new PlexWatchlistHistory { Id = 1, TmdbId = "123", UserId = "abc" } }.AsQueryable());
|
||||||
await _subject.Execute(_context.Object);
|
await _subject.Execute(_context.Object);
|
||||||
_mocker.Verify<IMovieRequestEngine>(x => x.RequestMovie(It.IsAny<MovieRequestViewModel>()), Times.Never);
|
_mocker.Verify<IMovieRequestEngine>(x => x.RequestMovie(It.IsAny<MovieRequestViewModel>()), Times.Never);
|
||||||
_mocker.Verify<IPlexApi>(x => x.GetWatchlistMetadata("abc", It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Once);
|
_mocker.Verify<IPlexApi>(x => x.GetWatchlistMetadata("abc", It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||||
|
@ -778,5 +785,99 @@ namespace Ombi.Schedule.Tests
|
||||||
_mocker.Verify<IExternalRepository<PlexWatchlistHistory>>(x => x.GetAll(), Times.Once);
|
_mocker.Verify<IExternalRepository<PlexWatchlistHistory>>(x => x.GetAll(), Times.Once);
|
||||||
_mocker.Verify<IExternalRepository<PlexWatchlistHistory>>(x => x.Add(It.IsAny<PlexWatchlistHistory>()), Times.Once);
|
_mocker.Verify<IExternalRepository<PlexWatchlistHistory>>(x => x.Add(It.IsAny<PlexWatchlistHistory>()), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task AuthenticationError_NotificationsEnabled_WithEmail_SendsNotification()
|
||||||
|
{
|
||||||
|
_mocker.Setup<ISettingsService<PlexSettings>, Task<PlexSettings>>(x => x.GetSettingsAsync())
|
||||||
|
.ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true, NotifyOnWatchlistTokenExpiration = true });
|
||||||
|
_mocker.Setup<IPlexApi, Task<PlexWatchlistContainer>>(x => x.GetWatchlist(It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
||||||
|
.ReturnsAsync(new PlexWatchlistContainer { AuthError = true });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await _subject.Execute(_context.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
_mocker.Verify<INotificationHelper>(x => x.Notify(It.Is<NotificationOptions>(n =>
|
||||||
|
n.NotificationType == NotificationType.PlexWatchlistTokenExpired &&
|
||||||
|
n.Recipient == "email@email.com" &&
|
||||||
|
n.Substitutes["UserName"] == "abc"
|
||||||
|
)), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task AuthenticationError_NotificationsDisabled_WithEmail_DoesNotSendNotification()
|
||||||
|
{
|
||||||
|
_mocker.Setup<ISettingsService<PlexSettings>, Task<PlexSettings>>(x => x.GetSettingsAsync())
|
||||||
|
.ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true, NotifyOnWatchlistTokenExpiration = false });
|
||||||
|
_mocker.Setup<IPlexApi, Task<PlexWatchlistContainer>>(x => x.GetWatchlist(It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
||||||
|
.ReturnsAsync(new PlexWatchlistContainer { AuthError = true });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await _subject.Execute(_context.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
_mocker.Verify<INotificationHelper>(x => x.Notify(It.IsAny<NotificationOptions>()), Times.Never);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task AuthenticationError_NotificationsEnabled_NoEmail_DoesNotSendNotification()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var user = new OmbiUser { Id = "abc", UserType = UserType.PlexUser, MediaServerToken = "token1", UserName = "abc", NormalizedUserName = "ABC" };
|
||||||
|
var um = MockHelper.MockUserManager(new List<OmbiUser> { user });
|
||||||
|
_mocker.Use(um);
|
||||||
|
|
||||||
|
_mocker.Setup<ISettingsService<PlexSettings>, Task<PlexSettings>>(x => x.GetSettingsAsync())
|
||||||
|
.ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true, NotifyOnWatchlistTokenExpiration = true });
|
||||||
|
_mocker.Setup<IPlexApi, Task<PlexWatchlistContainer>>(x => x.GetWatchlist(It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
||||||
|
.ReturnsAsync(new PlexWatchlistContainer { AuthError = true });
|
||||||
|
|
||||||
|
_subject = _mocker.CreateInstance<PlexWatchlistImport>();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await _subject.Execute(_context.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
_mocker.Verify<INotificationHelper>(x => x.Notify(It.IsAny<NotificationOptions>()), Times.Never);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task SkipsUserIfTokenKeepAliveFails()
|
||||||
|
{
|
||||||
|
// Arrange: Set up the keep-alive service to return false (token invalid/expired)
|
||||||
|
var keepAliveMock = new Mock<IPlexTokenKeepAliveService>();
|
||||||
|
keepAliveMock.Setup(x => x.KeepTokenAliveAsync(It.IsAny<string>(), It.IsAny<CancellationToken>())).ReturnsAsync(false);
|
||||||
|
_mocker.Use(keepAliveMock.Object);
|
||||||
|
_subject = _mocker.CreateInstance<PlexWatchlistImport>();
|
||||||
|
_mocker.Setup<ISettingsService<PlexSettings>, Task<PlexSettings>>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true });
|
||||||
|
// Act
|
||||||
|
await _subject.Execute(_context.Object);
|
||||||
|
// Assert: Should not attempt to import watchlist if keep-alive fails
|
||||||
|
keepAliveMock.Verify(x => x.KeepTokenAliveAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||||
|
_mocker.Verify<IPlexApi>(x => x.GetWatchlist(It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||||
|
_mocker.Verify<INotificationHelper>(x => x.Notify(It.IsAny<NotificationOptions>()), Times.Never); // or Times.Once if notification is expected
|
||||||
|
}
|
||||||
|
[Test]
|
||||||
|
public async Task CallsKeepAliveForEachPlexUser()
|
||||||
|
{
|
||||||
|
// Arrange: Multiple Plex users
|
||||||
|
var users = new List<OmbiUser>
|
||||||
|
{
|
||||||
|
new OmbiUser { Id = "abc1", UserType = UserType.PlexUser, MediaServerToken = "abc1", UserName = "abc1", NormalizedUserName = "ABC1" },
|
||||||
|
new OmbiUser { Id = "abc2", UserType = UserType.PlexUser, MediaServerToken = "abc2", UserName = "abc2", NormalizedUserName = "ABC2" },
|
||||||
|
};
|
||||||
|
var um = MockHelper.MockUserManager(users);
|
||||||
|
_mocker.Use(um);
|
||||||
|
var keepAliveMock = new Mock<IPlexTokenKeepAliveService>();
|
||||||
|
keepAliveMock.Setup(x => x.KeepTokenAliveAsync(It.IsAny<string>(), It.IsAny<CancellationToken>())).ReturnsAsync(true);
|
||||||
|
_mocker.Use(keepAliveMock.Object);
|
||||||
|
_subject = _mocker.CreateInstance<PlexWatchlistImport>();
|
||||||
|
_mocker.Setup<ISettingsService<PlexSettings>, Task<PlexSettings>>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true });
|
||||||
|
// Act
|
||||||
|
await _subject.Execute(_context.Object);
|
||||||
|
// Assert: KeepAlive should be called for each user
|
||||||
|
keepAliveMock.Verify(x => x.KeepTokenAliveAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Exactly(users.Count));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
{
|
|
||||||
"iisSettings": {
|
|
||||||
"windowsAuthentication": false,
|
|
||||||
"anonymousAuthentication": true,
|
|
||||||
"iisExpress": {
|
|
||||||
"applicationUrl": "http://localhost:62604/",
|
|
||||||
"sslPort": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"profiles": {
|
|
||||||
"IIS Express": {
|
|
||||||
"commandName": "IISExpress",
|
|
||||||
"launchBrowser": true,
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Ombi.Schedule.Tests": {
|
|
||||||
"commandName": "Project",
|
|
||||||
"launchBrowser": true,
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
},
|
|
||||||
"applicationUrl": "http://localhost:62605/"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -174,13 +174,18 @@ namespace Ombi.Schedule.Jobs.Emby
|
||||||
}
|
}
|
||||||
if (parent.TheMovieDbId.IsNullOrEmpty())
|
if (parent.TheMovieDbId.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
_logger.LogWarning($"Episode {episode.Name} is not linked to a TMDB series. Skipping.");
|
_logger.LogWarning($"Episode {episode.Name} for Tv Show {parent.Title} Doesn't have a valid TheMovieDbId. Skipping.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!int.TryParse(parent.TheMovieDbId, out var parentMovieDb))
|
||||||
|
{
|
||||||
|
_logger.LogWarning($"Episode {episode.Name} for Tv Show {parent.Title} Doesn't have a valid TheMovieDbId. Skipping.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await AddToContent(content, new UserPlayedEpisode()
|
await AddToContent(content, new UserPlayedEpisode()
|
||||||
{
|
{
|
||||||
TheMovieDbId = int.Parse(parent.TheMovieDbId),
|
TheMovieDbId = parentMovieDb,
|
||||||
SeasonNumber = episode.ParentIndexNumber,
|
SeasonNumber = episode.ParentIndexNumber,
|
||||||
EpisodeNumber = episode.IndexNumber,
|
EpisodeNumber = episode.IndexNumber,
|
||||||
UserId = user.Id
|
UserId = user.Id
|
||||||
|
@ -196,7 +201,7 @@ namespace Ombi.Schedule.Jobs.Emby
|
||||||
|
|
||||||
await AddToContent(content, new UserPlayedEpisode()
|
await AddToContent(content, new UserPlayedEpisode()
|
||||||
{
|
{
|
||||||
TheMovieDbId = int.Parse(parent.TheMovieDbId),
|
TheMovieDbId = parentMovieDb,
|
||||||
SeasonNumber = episode.ParentIndexNumber,
|
SeasonNumber = episode.ParentIndexNumber,
|
||||||
EpisodeNumber = episodeNumber,
|
EpisodeNumber = episodeNumber,
|
||||||
UserId = user.Id
|
UserId = user.Id
|
||||||
|
|
|
@ -174,7 +174,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = GenerateUnsubscribeLink(customization.ApplicationUrl, user.Id);
|
var url = GenerateUnsubscribeLink(customization.ApplicationUrl, user.Id);
|
||||||
var html = email.LoadTemplate(messageContent.Subject, messageContent.Message, body, customization.Logo, url);
|
var html = email.LoadTemplate(messageContent.Subject, messageContent.Message, body, customization.Logo, url, customization.ApplicationUrl ?? string.Empty);
|
||||||
|
|
||||||
var bodyBuilder = new BodyBuilder
|
var bodyBuilder = new BodyBuilder
|
||||||
{
|
{
|
||||||
|
@ -216,7 +216,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
|
|
||||||
var email = new NewsletterTemplate();
|
var email = new NewsletterTemplate();
|
||||||
|
|
||||||
var html = email.LoadTemplate(messageContent.Subject, messageContent.Message, body, customization.Logo, unsubscribeLink);
|
var html = email.LoadTemplate(messageContent.Subject, messageContent.Message, body, customization.Logo, unsubscribeLink, customization.ApplicationUrl ?? string.Empty);
|
||||||
|
|
||||||
await _email.Send(
|
await _email.Send(
|
||||||
new NotificationMessage { Message = html, Subject = messageContent.Subject, To = a.Email },
|
new NotificationMessage { Message = html, Subject = messageContent.Subject, To = a.Email },
|
||||||
|
|
|
@ -7,6 +7,7 @@ using Microsoft.Extensions.Logging;
|
||||||
using Ombi.Api.Emby;
|
using Ombi.Api.Emby;
|
||||||
using Ombi.Api.Jellyfin;
|
using Ombi.Api.Jellyfin;
|
||||||
using Ombi.Api.Plex;
|
using Ombi.Api.Plex;
|
||||||
|
using Ombi.Api.Plex.Models;
|
||||||
using Ombi.Api.TheMovieDb;
|
using Ombi.Api.TheMovieDb;
|
||||||
using Ombi.Api.TheMovieDb.Models;
|
using Ombi.Api.TheMovieDb.Models;
|
||||||
using Ombi.Api.TvMaze;
|
using Ombi.Api.TvMaze;
|
||||||
|
@ -286,7 +287,18 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var servers = settings.Servers[0];
|
var servers = settings.Servers[0];
|
||||||
var metaData = await _plexApi.GetMetadata(servers.PlexAuthToken, settings.Servers[0].FullUri, movie.Key);
|
PlexMetadata metaData = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
metaData = await _plexApi.GetMetadata(servers.PlexAuthToken, settings.Servers[0].FullUri, movie.Key);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_log.LogError($"Could not find the metadata for title: '{movie.Title}', skipping");
|
||||||
|
_log.LogDebug(e, $"Could not find the metadata for title: '{movie.Title}', skipping");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
var guids = new List<string>();
|
var guids = new List<string>();
|
||||||
|
|
||||||
var meta = metaData.MediaContainer.Metadata.FirstOrDefault();
|
var meta = metaData.MediaContainer.Metadata.FirstOrDefault();
|
||||||
|
|
|
@ -278,6 +278,10 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
await Repo.AddRange(contentToAdd);
|
await Repo.AddRange(contentToAdd);
|
||||||
foreach (var c in contentToAdd)
|
foreach (var c in contentToAdd)
|
||||||
{
|
{
|
||||||
|
if (contentProcessed.ContainsKey(c.Id)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
contentProcessed.Add(c.Id, c.Key);
|
contentProcessed.Add(c.Id, c.Key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -300,6 +304,13 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
var existing = await Repo.GetFirstContentByCustom(x => x.Title == movie.title
|
var existing = await Repo.GetFirstContentByCustom(x => x.Title == movie.title
|
||||||
&& x.ReleaseYear == movie.year.ToString()
|
&& x.ReleaseYear == movie.year.ToString()
|
||||||
&& x.Type == MediaType.Movie);
|
&& x.Type == MediaType.Movie);
|
||||||
|
|
||||||
|
|
||||||
|
if (existing == null)
|
||||||
|
{
|
||||||
|
// Let's just check the key
|
||||||
|
existing = await Repo.GetByKey(movie.ratingKey);
|
||||||
|
}
|
||||||
if (existing != null)
|
if (existing != null)
|
||||||
{
|
{
|
||||||
// We need to see if this is a different quality,
|
// We need to see if this is a different quality,
|
||||||
|
@ -336,13 +347,7 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
|
|
||||||
Logger.LogDebug($"We already have movie {movie.title}");
|
Logger.LogDebug($"We already have movie {movie.title}");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//var hasSameKey = await Repo.GetByKey(movie.ratingKey);
|
|
||||||
//if (hasSameKey != null)
|
|
||||||
//{
|
|
||||||
// await Repo.Delete(hasSameKey);
|
|
||||||
//}
|
|
||||||
|
|
||||||
Logger.LogDebug("Adding movie {0}", movie.title);
|
Logger.LogDebug("Adding movie {0}", movie.title);
|
||||||
var guids = new List<string>();
|
var guids = new List<string>();
|
||||||
|
|
|
@ -120,6 +120,13 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
|
|
||||||
foreach (var plexUser in users.User)
|
foreach (var plexUser in users.User)
|
||||||
{
|
{
|
||||||
|
// Skip users without server access
|
||||||
|
if (plexUser.Server == null || !plexUser.Server.Any())
|
||||||
|
{
|
||||||
|
_log.LogInformation($"Skipping user {plexUser.Username ?? plexUser.Id} as they have no server access");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if we should import this user
|
// Check if we should import this user
|
||||||
if (userManagementSettings.BannedPlexUserIds.Contains(plexUser.Id))
|
if (userManagementSettings.BannedPlexUserIds.Contains(plexUser.Id))
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,6 +22,11 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Ombi.Notifications.Models;
|
||||||
|
using Ombi.Core.Notifications;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Ombi.Store.Repository.Requests;
|
||||||
|
using Ombi.Core;
|
||||||
|
|
||||||
namespace Ombi.Schedule.Jobs.Plex
|
namespace Ombi.Schedule.Jobs.Plex
|
||||||
{
|
{
|
||||||
|
@ -37,11 +42,13 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
private readonly IExternalRepository<PlexWatchlistHistory> _watchlistRepo;
|
private readonly IExternalRepository<PlexWatchlistHistory> _watchlistRepo;
|
||||||
private readonly IRepository<PlexWatchlistUserError> _userError;
|
private readonly IRepository<PlexWatchlistUserError> _userError;
|
||||||
private readonly IMovieDbApi _movieDbApi;
|
private readonly IMovieDbApi _movieDbApi;
|
||||||
|
private readonly INotificationHelper _notificationHelper;
|
||||||
|
private readonly IPlexTokenKeepAliveService _tokenKeepAliveService;
|
||||||
|
|
||||||
public PlexWatchlistImport(IPlexApi plexApi, ISettingsService<PlexSettings> settings, OmbiUserManager ombiUserManager,
|
public PlexWatchlistImport(IPlexApi plexApi, ISettingsService<PlexSettings> settings, OmbiUserManager ombiUserManager,
|
||||||
IMovieRequestEngine movieRequestEngine, ITvRequestEngine tvRequestEngine, INotificationHubService notificationHubService,
|
IMovieRequestEngine movieRequestEngine, ITvRequestEngine tvRequestEngine, INotificationHubService notificationHubService,
|
||||||
ILogger<PlexWatchlistImport> logger, IExternalRepository<PlexWatchlistHistory> watchlistRepo, IRepository<PlexWatchlistUserError> userError,
|
ILogger<PlexWatchlistImport> logger, IExternalRepository<PlexWatchlistHistory> watchlistRepo, IRepository<PlexWatchlistUserError> userError,
|
||||||
IMovieDbApi movieDbApi)
|
IMovieDbApi movieDbApi, INotificationHelper notificationHelper, IPlexTokenKeepAliveService tokenKeepAliveService)
|
||||||
{
|
{
|
||||||
_plexApi = plexApi;
|
_plexApi = plexApi;
|
||||||
_settings = settings;
|
_settings = settings;
|
||||||
|
@ -53,6 +60,8 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
_watchlistRepo = watchlistRepo;
|
_watchlistRepo = watchlistRepo;
|
||||||
_userError = userError;
|
_userError = userError;
|
||||||
_movieDbApi = movieDbApi;
|
_movieDbApi = movieDbApi;
|
||||||
|
_notificationHelper = notificationHelper;
|
||||||
|
_tokenKeepAliveService = tokenKeepAliveService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Execute(IJobExecutionContext context)
|
public async Task Execute(IJobExecutionContext context)
|
||||||
|
@ -90,6 +99,36 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogDebug($"Starting Watchlist Import for {user.UserName} with token {user.MediaServerToken}");
|
_logger.LogDebug($"Starting Watchlist Import for {user.UserName} with token {user.MediaServerToken}");
|
||||||
|
|
||||||
|
// Keep the token alive before attempting watchlist import
|
||||||
|
var keepAliveSuccess = await _tokenKeepAliveService.KeepTokenAliveAsync(user.MediaServerToken, context?.CancellationToken ?? CancellationToken.None);
|
||||||
|
if (!keepAliveSuccess)
|
||||||
|
{
|
||||||
|
_logger.LogWarning($"Token for user '{user.UserName}' is invalid or expired (keep-alive failed). Recording error and skipping.");
|
||||||
|
await _userError.Add(new PlexWatchlistUserError
|
||||||
|
{
|
||||||
|
UserId = user.Id,
|
||||||
|
MediaServerToken = user.MediaServerToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Send notification to user about token expiration
|
||||||
|
if (settings.NotifyOnWatchlistTokenExpiration && !string.IsNullOrEmpty(user.Email))
|
||||||
|
{
|
||||||
|
var notificationModel = new NotificationOptions
|
||||||
|
{
|
||||||
|
NotificationType = NotificationType.PlexWatchlistTokenExpired,
|
||||||
|
Recipient = user.Email,
|
||||||
|
DateTime = DateTime.Now,
|
||||||
|
Substitutes = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "UserName", user.UserName }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await _notificationHelper.Notify(notificationModel);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var watchlist = await _plexApi.GetWatchlist(user.MediaServerToken, context?.CancellationToken ?? CancellationToken.None);
|
var watchlist = await _plexApi.GetWatchlist(user.MediaServerToken, context?.CancellationToken ?? CancellationToken.None);
|
||||||
if (watchlist?.AuthError ?? false)
|
if (watchlist?.AuthError ?? false)
|
||||||
{
|
{
|
||||||
|
@ -99,6 +138,22 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
UserId = user.Id,
|
UserId = user.Id,
|
||||||
MediaServerToken = user.MediaServerToken,
|
MediaServerToken = user.MediaServerToken,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Send notification to user about token expiration
|
||||||
|
if (settings.NotifyOnWatchlistTokenExpiration && !string.IsNullOrEmpty(user.Email))
|
||||||
|
{
|
||||||
|
var notificationModel = new NotificationOptions
|
||||||
|
{
|
||||||
|
NotificationType = NotificationType.PlexWatchlistTokenExpired,
|
||||||
|
Recipient = user.Email,
|
||||||
|
DateTime = DateTime.Now,
|
||||||
|
Substitutes = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "UserName", user.UserName }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await _notificationHelper.Notify(notificationModel);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (watchlist == null || !(watchlist.MediaContainer?.Metadata?.Any() ?? false))
|
if (watchlist == null || !(watchlist.MediaContainer?.Metadata?.Any() ?? false))
|
||||||
|
@ -128,7 +183,7 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to see if we have already imported this item
|
// Check to see if we have already imported this item
|
||||||
var alreadyImported = _watchlistRepo.GetAll().Any(x => x.TmdbId == providerIds.TheMovieDb);
|
var alreadyImported = _watchlistRepo.GetAll().Any(x => x.TmdbId == providerIds.TheMovieDb && x.UserId == user.Id);
|
||||||
if (alreadyImported)
|
if (alreadyImported)
|
||||||
{
|
{
|
||||||
_logger.LogDebug($"{item.title} already imported via Plex WatchList, skipping");
|
_logger.LogDebug($"{item.title} already imported via Plex WatchList, skipping");
|
||||||
|
@ -202,14 +257,14 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
if (response.ErrorCode == ErrorCode.AlreadyRequested)
|
if (response.ErrorCode == ErrorCode.AlreadyRequested)
|
||||||
{
|
{
|
||||||
_logger.LogDebug($"Movie already requested for user '{user.UserName}'");
|
_logger.LogDebug($"Movie already requested for user '{user.UserName}'");
|
||||||
await AddToHistory(theMovieDbId);
|
await AddToHistory(theMovieDbId, user.Id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_logger.LogInformation($"Error adding title from PlexWatchlist for user '{user.UserName}'. Message: '{response.ErrorMessage}'");
|
_logger.LogInformation($"Error adding title from PlexWatchlist for user '{user.UserName}'. Message: '{response.ErrorMessage}'");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await AddToHistory(theMovieDbId);
|
await AddToHistory(theMovieDbId, user.Id);
|
||||||
|
|
||||||
_logger.LogInformation($"Added title from PlexWatchlist for user '{user.UserName}'. {response.Message}");
|
_logger.LogInformation($"Added title from PlexWatchlist for user '{user.UserName}'. {response.Message}");
|
||||||
}
|
}
|
||||||
|
@ -230,24 +285,26 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
if (response.ErrorCode == ErrorCode.AlreadyRequested)
|
if (response.ErrorCode == ErrorCode.AlreadyRequested)
|
||||||
{
|
{
|
||||||
_logger.LogDebug($"Show already requested for user '{user.UserName}'");
|
_logger.LogDebug($"Show already requested for user '{user.UserName}'");
|
||||||
await AddToHistory(theMovieDbId);
|
await AddToHistory(theMovieDbId, user.Id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_logger.LogInformation($"Error adding title from PlexWatchlist for user '{user.UserName}'. Message: '{response.ErrorMessage}'");
|
_logger.LogInformation($"Error adding title from PlexWatchlist for user '{user.UserName}'. Message: '{response.ErrorMessage}'");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await AddToHistory(theMovieDbId);
|
await AddToHistory(theMovieDbId, user.Id);
|
||||||
_logger.LogInformation($"Added title from PlexWatchlist for user '{user.UserName}'. {response.Message}");
|
_logger.LogInformation($"Added title from PlexWatchlist for user '{user.UserName}'. {response.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private async Task AddToHistory(int theMovieDbId)
|
private async Task AddToHistory(int theMovieDbId, string userId)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Add to the watchlist history
|
// Add to the watchlist history
|
||||||
var history = new PlexWatchlistHistory
|
var history = new PlexWatchlistHistory
|
||||||
{
|
{
|
||||||
TmdbId = theMovieDbId.ToString()
|
TmdbId = theMovieDbId.ToString(),
|
||||||
|
AddedAt = DateTime.UtcNow,
|
||||||
|
UserId = userId
|
||||||
};
|
};
|
||||||
await _watchlistRepo.Add(history);
|
await _watchlistRepo.Add(history);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.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,6 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup><TargetFramework>net6.0</TargetFramework>
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
|
|
||||||
|
@ -10,7 +11,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="nunit" Version="3.13.3" />
|
<PackageReference Include="nunit" Version="3.13.3" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.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="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
||||||
<PackageReference Include="Quartz" Version="3.6.2" />
|
<PackageReference Include="Quartz" Version="3.6.2" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -9,6 +9,7 @@ namespace Ombi.Core.Settings.Models.External
|
||||||
public bool Enable { get; set; }
|
public bool Enable { get; set; }
|
||||||
public bool EnableWatchlistImport { get; set; }
|
public bool EnableWatchlistImport { get; set; }
|
||||||
public bool MonitorAll { get; set; }
|
public bool MonitorAll { get; set; }
|
||||||
|
public bool NotifyOnWatchlistTokenExpiration { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is the ClientId for OAuth
|
/// This is the ClientId for OAuth
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -217,6 +217,16 @@ namespace Ombi.Store.Context
|
||||||
Enabled = true,
|
Enabled = true,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
case NotificationType.PlexWatchlistTokenExpired:
|
||||||
|
notificationToAdd = new NotificationTemplates
|
||||||
|
{
|
||||||
|
NotificationType = notificationType,
|
||||||
|
Message = "Hello {UserName}! Your Plex watchlist token has expired. Please re-authenticate with Ombi to continue using the watchlist feature.",
|
||||||
|
Subject = "Plex Watchlist Token Expired",
|
||||||
|
Agent = agent,
|
||||||
|
Enabled = true,
|
||||||
|
};
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
|
|
16
src/Ombi.Store/Context/Postgres/ExternalPostgresContext.cs
Normal file
16
src/Ombi.Store/Context/Postgres/ExternalPostgresContext.cs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Context.Postgres
|
||||||
|
{
|
||||||
|
public sealed class ExternalPostgresContext : ExternalContext
|
||||||
|
{
|
||||||
|
private static bool _created;
|
||||||
|
public ExternalPostgresContext(DbContextOptions<ExternalPostgresContext> options) : base(options)
|
||||||
|
{
|
||||||
|
if (_created) return;
|
||||||
|
|
||||||
|
_created = true;
|
||||||
|
Database.Migrate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
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