Merge remote-tracking branch 'upstream/develop' into original-language

pull/4619/head
sephrat 2 years ago
commit 18742776da

@ -28,6 +28,8 @@ jobs:
unit-test:
runs-on: ubuntu-latest
permissions:
checks: write
steps:
- uses: actions/checkout@v2
- uses: actions/setup-dotnet@v1
@ -45,7 +47,16 @@ jobs:
- name: Run Unit Tests
run: |
cd src
dotnet test --logger trx --results-directory "TestResults"
dotnet test --logger "trx;LogFileName=test-results.trx" || true
- name: Test Report
uses: dorny/test-reporter@v1
if: always()
with:
name: DotNET Tests
path: "**/test-results.trx"
reporter: dotnet-trx
fail-on-error: true
analysis:
runs-on: ubuntu-latest

@ -1,3 +1,20 @@
## [4.16.17](https://github.com/Ombi-app/Ombi/compare/v4.16.16...v4.16.17) (2022-04-25)
## [4.16.16](https://github.com/Ombi-app/Ombi/compare/v4.16.15...v4.16.16) (2022-04-25)
### Bug Fixes
* **4616:** :bug: fixed mandatory fields ([d8f2260](https://github.com/Ombi-app/Ombi/commit/d8f2260c7ae3ed48386743b7adbd06e284487034))
## [4.16.15](https://github.com/Ombi-app/Ombi/compare/v4.16.14...v4.16.15) (2022-04-24)
## [4.16.14](https://github.com/Ombi-app/Ombi/compare/v4.16.13...v4.16.14) (2022-04-19)
@ -321,30 +338,3 @@
# [4.12.0](https://github.com/Ombi-app/Ombi/compare/v4.11.8...v4.12.0) (2022-02-14)
### Features
* **radarr:** 4K Requests and Radarr 4K support ([ba88848](https://github.com/Ombi-app/Ombi/commit/ba88848866b0a9dedb1e79b55c4d81a0fd453843))
## [4.11.8](https://github.com/Ombi-app/Ombi/compare/v4.11.7...v4.11.8) (2022-02-13)
### Bug Fixes
* **settings:** :bug: Fixed an issue where we were not displaying the excluded keyworks correctly in the TheMovieDbSettings page ([d3b3316](https://github.com/Ombi-app/Ombi/commit/d3b3316cbac18356b2f6b0912a3deb2c183e6534))
## [4.11.7](https://github.com/Ombi-app/Ombi/compare/v4.11.6...v4.11.7) (2022-02-12)
### Bug Fixes
* **notifications:** :bug: This is a fix for some of the duplicate notification issues [#3825](https://github.com/Ombi-app/Ombi/issues/3825) ([22bb422](https://github.com/Ombi-app/Ombi/commit/22bb4226ead2d62e8c2c2c05be47d7da621402e2))

@ -665,14 +665,21 @@ Here are some of the features Ombi has:
<sub><b>Shoghi</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Teifun2">
<img src="https://avatars.githubusercontent.com/u/7461832?v=4" width="50;" alt="Teifun2"/>
<br />
<sub><b>Teifun2</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/thomasvt1">
<img src="https://avatars.githubusercontent.com/u/2271011?v=4" width="50;" alt="thomasvt1"/>
<br />
<sub><b>Thomas Van Tilburg</b></sub>
</a>
</td></tr>
<tr>
</td>
<td align="center">
<a href="https://github.com/Tim-Trott">
<img src="https://avatars.githubusercontent.com/u/8249434?v=4" width="50;" alt="Tim-Trott"/>
@ -707,15 +714,15 @@ Here are some of the features Ombi has:
<br />
<sub><b>Xirg</b></sub>
</a>
</td>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/bazhip">
<img src="https://avatars.githubusercontent.com/u/10350445?v=4" width="50;" alt="bazhip"/>
<br />
<sub><b>Tim OBrien</b></sub>
</a>
</td></tr>
<tr>
</td>
<td align="center">
<a href="https://github.com/x-limitless-x">
<img src="https://avatars.githubusercontent.com/u/17127926?v=4" width="50;" alt="x-limitless-x"/>
@ -750,15 +757,15 @@ Here are some of the features Ombi has:
<br />
<sub><b>M4tta</b></sub>
</a>
</td>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/maartenheebink">
<img src="https://avatars.githubusercontent.com/u/28894544?v=4" width="50;" alt="maartenheebink"/>
<br />
<sub><b>Maartenheebink</b></sub>
</a>
</td></tr>
<tr>
</td>
<td align="center">
<a href="https://github.com/masterhuck">
<img src="https://avatars.githubusercontent.com/u/4671442?v=4" width="50;" alt="masterhuck"/>

@ -533,7 +533,10 @@ namespace Ombi.Core.Engine
}
else
{
x.ShowSubscribe = true;
if (!x.Available && !x.Available4K && (!x.Denied ?? true) && (!x.Denied4K ?? true))
{
x.ShowSubscribe = true;
}
var hasSub = sub.FirstOrDefault(r => r.RequestId == x.Id);
x.Subscribed = hasSub != null;
}

@ -270,7 +270,10 @@ namespace Ombi.Core.Engine
}
else
{
x.ShowSubscribe = true;
if (!x.Available && (!x.Denied ?? false))
{
x.ShowSubscribe = true;
}
var hasSub = sub.FirstOrDefault(r => r.RequestId == x.Id);
x.Subscribed = hasSub != null;
}

@ -886,7 +886,10 @@ namespace Ombi.Core.Engine
}
else
{
x.ShowSubscribe = true;
if (!x.Available && (!x.Denied ?? true))
{
x.ShowSubscribe = true;
}
var result = relevantSubs.FirstOrDefault(s => s.RequestId == x.Id);
x.Subscribed = result != null;
}

@ -70,7 +70,7 @@ namespace Ombi.Core.Senders
}
return new SenderResult { Success = false, Sent = false, Message = "Something went wrong!" };
return new SenderResult { Success = false, Sent = false };
}
private async Task<SenderResult> SendToLidarr(AlbumRequest model, LidarrSettings settings)

@ -133,8 +133,7 @@ namespace Ombi.Core.Senders
return new SenderResult
{
Success = false,
Message = "Something went wrong!"
Success = false
};
}
@ -343,8 +342,6 @@ namespace Ombi.Core.Senders
await Task.Delay(500);
}
var seriesChanges = false;
foreach (var season in model.SeasonRequests)
{
foreach (var ep in season.Episodes)
@ -359,72 +356,36 @@ namespace Ombi.Core.Senders
}
existingSeason = result.seasons.FirstOrDefault(x => x.seasonNumber == season.SeasonNumber);
var sonarrEpisodeList = sonarrEpList.Where(x => x.seasonNumber == season.SeasonNumber).ToList();
var sonarrEpCount = sonarrEpisodeList.Count;
var ourRequestCount = season.Episodes.Count;
var ourEpisodes = season.Episodes.Select(x => x.EpisodeNumber).ToList();
var unairedEpisodes = sonarrEpisodeList.Where(x => x.airDateUtc > DateTime.UtcNow).Select(x => x.episodeNumber).ToList();
//// Check if we have requested all the latest episodes, if we have then monitor
//// NOTE, not sure if needed since ombi ui displays future episodes anyway...
//ourEpisodes.AddRange(unairedEpisodes);
//var distinctEpisodes = ourEpisodes.Distinct().ToList();
//var missingEpisodes = Enumerable.Range(distinctEpisodes.Min(), distinctEpisodes.Count).Except(distinctEpisodes);
if (sonarrEpCount == ourRequestCount /*|| !missingEpisodes.Any()*/)
// Make sure this season is set to monitored
if (!existingSeason.monitored)
{
// We have the same amount of requests as all of the episodes in the season.
// We need to monitor it, problem being is all episodes will now be monitored
// So we need to monitor the series but unmonitor every episode
existingSeason.monitored = true;
seriesChanges = true;
var sea = result.seasons.FirstOrDefault(x => x.seasonNumber == existingSeason.seasonNumber);
sea.monitored = true;
// We do not need to update the episodes as marking the season as monitored will mark the episodes as monitored.
var seasonToUpdate = result.seasons.FirstOrDefault(x => x.seasonNumber == season.SeasonNumber);
seasonToUpdate.monitored = true; // Update by ref
}
else
{
// Make sure this season is set to monitored
if (!existingSeason.monitored)
result = await SonarrApi.UpdateSeries(result, s.ApiKey, s.FullUri);
var epToUnmonitored = new List<Episode>();
var newEpList = sonarrEpList.ConvertAll(ep => new Episode(ep)); // Clone it so we don't modify the original member
foreach (var ep in newEpList.Where(x => x.seasonNumber == existingSeason.seasonNumber).ToList())
{
// We need to monitor it, problem being is all episodes will now be monitored
// So we need to monitor the series but unmonitor every episode
// Except the episodes that are already monitored before we update the series (we do not want to unmonitored episodes that are monitored beforehand)
existingSeason.monitored = true;
var sea = result.seasons.FirstOrDefault(x => x.seasonNumber == existingSeason.seasonNumber);
sea.monitored = true;
//var previouslyMonitoredEpisodes = sonarrEpList.Where(x =>
// x.seasonNumber == existingSeason.seasonNumber && x.monitored).Select(x => x.episodeNumber).ToList(); // We probably don't actually care about this
result = await SonarrApi.UpdateSeries(result, s.ApiKey, s.FullUri);
var epToUnmonitored = new List<Episode>();
var newEpList = sonarrEpList.ConvertAll(ep => new Episode(ep)); // Clone it so we don't modify the original member
foreach (var ep in newEpList.Where(x => x.seasonNumber == existingSeason.seasonNumber).ToList())
{
//if (previouslyMonitoredEpisodes.Contains(ep.episodeNumber))
//{
// // This was previously monitored.
// continue;
//}
ep.monitored = false;
epToUnmonitored.Add(ep);
}
foreach (var epToUpdate in epToUnmonitored)
{
await SonarrApi.UpdateEpisode(epToUpdate, s.ApiKey, s.FullUri);
}
ep.monitored = false;
epToUnmonitored.Add(ep);
}
// Now update the episodes that need updating
foreach (var epToUpdate in episodesToUpdate.Where(x => x.seasonNumber == season.SeasonNumber))
foreach (var epToUpdate in epToUnmonitored)
{
await SonarrApi.UpdateEpisode(epToUpdate, s.ApiKey, s.FullUri);
}
}
}
if (seriesChanges)
{
await SonarrApi.SeasonPass(s.ApiKey, s.FullUri, result);
// Now update the episodes that need updating
foreach (var epToUpdate in episodesToUpdate.Where(x => x.seasonNumber == season.SeasonNumber))
{
await SonarrApi.UpdateEpisode(epToUpdate, s.ApiKey, s.FullUri);
}
}
if (!s.AddOnly)

@ -212,7 +212,7 @@ namespace Ombi.Store.Context
notificationToAdd = new NotificationTemplates
{
NotificationType = notificationType,
Message = "Your TV request is now partially available! Season {PartiallyAvailableSeasonNumber} Episodes {PartiallyAvailableEpisodeNumbers}!",
Message = "Your TV request for {Title} is now partially available! Season {PartiallyAvailableSeasonNumber} Episodes {PartiallyAvailableEpisodeNumbers}!",
Subject = "{ApplicationName}: Partially Available Request!",
Agent = agent,
Enabled = true,

@ -14,7 +14,7 @@
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef> </th>
<td mat-cell *matCellDef="let element">
<button mat-raised-button color="accent" [routerLink]="[element.providerId]">{{ 'Issues.Details' | translate}}</button>
<a mat-raised-button color="accent" [routerLink]="[element.providerId]">{{ 'Issues.Details' | translate}}</a>
</td>
</ng-container>

@ -36,7 +36,7 @@ export class TvRequestGridComponent {
// Make sure something has been selected
const selected = this.selection.hasValue();
if (!selected && !this.tv.requestAll && !this.tv.firstSeason && !this.tv.latestSeason) {
this.notificationService.send("You need to select some episodes!", "OK");
this.notificationService.send(this.translate.instant("Requests.NeedToSelectEpisodes"));
return;
}
@ -80,70 +80,6 @@ export class TvRequestGridComponent {
}
}
public async approve(request: IChildRequests) {
const result = await this.requestService.approveChild({
id: request.id
}).toPromise();
if (result.result) {
request.approved = true;
request.denied = false;
request.seasonRequests.forEach((season) => {
season.episodes.forEach((ep) => {
ep.approved = true;
});
});
this.notificationService.send("Request has been approved", "Ok");
} else {
this.notificationService.send(result.errorMessage, "Ok");
}
}
public changeAvailability(request: IChildRequests, available: boolean) {
request.available = available;
request.seasonRequests.forEach((season) => {
season.episodes.forEach((ep) => {
ep.available = available;
});
});
if (available) {
this.requestService.markTvAvailable({ id: request.id }).subscribe(x => {
if (x.result) {
this.notificationService.send(
`This request is now available`);
} else {
this.notificationService.send("Request Available", x.message ? x.message : x.errorMessage);
request.approved = false;
}
});
} else {
this.requestService.markTvUnavailable({ id: request.id }).subscribe(x => {
if (x.result) {
this.notificationService.send(
`This request is now unavailable`);
} else {
this.notificationService.send("Request Available", x.message ? x.message : x.errorMessage);
request.approved = false;
}
});
}
}
public async deny(request: IChildRequests) {
const dialogRef = this.dialog.open(DenyDialogComponent, {
width: '250px',
data: {requestId: request.id, requestType: RequestType.tvShow}
});
dialogRef.afterClosed().subscribe(result => {
request.denied = true;
request.seasonRequests.forEach((season) => {
season.episodes.forEach((ep) => {
ep.approved = false;
});
});
});
}
public async requestAllSeasons() {
this.tv.requestAll = true;
await this.submitRequests();

@ -6,6 +6,7 @@ import { MatDialog } from "@angular/material/dialog";
import { MessageService } from "../../../../../services";
import { RequestService } from "../../../../../services/request.service";
import { RequestServiceV2 } from "../../../../../services/requestV2.service";
import { TranslateService } from "@ngx-translate/core";
@Component({
templateUrl: "./tv-requests-panel.component.html",
@ -24,7 +25,8 @@ export class TvRequestsPanelComponent {
constructor(private requestService: RequestService,
private requestService2: RequestServiceV2,
private messageService: MessageService,
public dialog: MatDialog) {
public dialog: MatDialog,
private translateService: TranslateService) {
}
@ -41,7 +43,7 @@ export class TvRequestsPanelComponent {
ep.approved = true;
});
});
this.messageService.send("Request has been approved", "Ok");
this.messageService.send(this.translateService.instant("Requests.SuccessfullyApproved"));
} else {
this.messageService.sendRequestEngineResultError(result);
}
@ -52,7 +54,7 @@ export class TvRequestsPanelComponent {
if (result) {
this.tvRequest.splice(this.tvRequest.indexOf(request),1);
this.messageService.send("Request has been Deleted", "Ok");
this.messageService.send(this.translateService.instant("Requests.SuccessfullyDeleted"));
}
}
@ -67,9 +69,9 @@ export class TvRequestsPanelComponent {
this.requestService.markTvAvailable({ id: request.id }).subscribe(x => {
if (x.result) {
this.messageService.send(
`This request is now available`);
this.translateService.instant("Requests.NowAvailable"));
} else {
this.messageService.send("Request Available", x.message ? x.message : x.errorMessage);
this.messageService.sendRequestEngineResultError(x);
request.approved = false;
}
});
@ -77,9 +79,9 @@ export class TvRequestsPanelComponent {
this.requestService.markTvUnavailable({ id: request.id }).subscribe(x => {
if (x.result) {
this.messageService.send(
`This request is now unavailable`);
this.translateService.instant("Requests.NowUnavailable"));
} else {
this.messageService.send("Request Available", x.message ? x.message : x.errorMessage);
this.messageService.sendRequestEngineResultError(x);
request.approved = false;
}
});
@ -102,11 +104,11 @@ export class TvRequestsPanelComponent {
}
public reProcessRequest(request: IChildRequests) {
this.requestService2.reprocessRequest(request.id, RequestType.tvShow, false).subscribe(result => {
if (result.result) {
this.messageService.send(result.message ? result.message : "Successfully Re-processed the request", "Ok");
this.requestService2.reprocessRequest(request.id, RequestType.tvShow, false).subscribe(x => {
if (x.result) {
this.messageService.send(this.translateService.instant("Requests.SuccessfullyReprocessed"));
} else {
this.messageService.sendRequestEngineResultError(result);
this.messageService.sendRequestEngineResultError(x);
}
});
}

@ -59,7 +59,7 @@
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef> </th>
<td mat-cell *matCellDef="let element">
<button mat-raised-button color="accent" [routerLink]="'/details/artist/' + element.foreignArtistId">{{ 'Requests.Details' | translate}}</button>
<a mat-raised-button color="accent" [routerLink]="'/details/artist/' + element.foreignArtistId">{{ 'Requests.Details' | translate}}</a>
<button mat-raised-button color="warn" (click)="openOptions(element)" *ngIf="isAdmin || ( manageOwnRequests && element.requestedUser?.userName == userName )"> {{ 'Requests.Options' | translate}}</button>
</td>
</ng-container>

@ -83,8 +83,8 @@
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef> </th>
<td mat-cell *matCellDef="let element">
<button id="detailsButton{{element.id}}" mat-raised-button color="accent" [routerLink]="'/details/movie/' + element.theMovieDbId">{{ 'Requests.Details' | translate}}</button>
<button id="optionsButton{{element.id}}" mat-raised-button color="warn" (click)="openOptions(element)" *ngIf="isAdmin || ( manageOwnRequests && element.requestedUser?.userName == userName ) "> {{ 'Requests.Options' | translate}}</button>
<a id="detailsButton{{element.id}}" mat-raised-button color="accent" [routerLink]="'/details/movie/' + element.theMovieDbId">{{ 'Requests.Details' | translate}}</a>
<a id="optionsButton{{element.id}}" mat-raised-button color="warn" (click)="openOptions(element)" *ngIf="isAdmin || ( manageOwnRequests && element.requestedUser?.userName == userName ) "> {{ 'Requests.Options' | translate}}</a>
</td>
</ng-container>
@ -103,4 +103,4 @@
<button id="denyFabButton" mat-menu-item (click)="bulkDeny()">{{'Requests.RequestPanel.Deny' | translate}}</button>
<button *ngIf="is4kEnabled" id="deny4kFabButton" mat-menu-item (click)="bulkDeny4K()">{{'Requests.RequestPanel.Deny4K' | translate}}</button>
<button id="deleteFabButton" mat-menu-item (click)="bulkDelete()">{{'Requests.RequestPanel.Delete' | translate}}</button>
</mat-menu>
</mat-menu>

@ -63,7 +63,7 @@
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef> </th>
<td mat-cell *matCellDef="let element">
<button id="detailsButton{{element.id}}" mat-raised-button color="accent" [routerLink]="'/details/tv/' + element.parentRequest.externalProviderId">{{'Requests.Details' | translate}}</button>
<a id="detailsButton{{element.id}}" mat-raised-button color="accent" [routerLink]="'/details/tv/' + element.parentRequest.externalProviderId">{{'Requests.Details' | translate}}</a>
<button id="optionsButton{{element.id}}" mat-raised-button color="warn" (click)="openOptions(element)" *ngIf="isAdmin">{{'Requests.Options' | translate}}</button>
</td>
</ng-container>

@ -22,11 +22,15 @@ export class MessageService {
}
public sendRequestEngineResultError(result: IRequestEngineResult, action: string = "Ok") {
const textKey = 'Requests.ErrorCodes.' + result.errorCode;
const text = this.translate.instant(textKey);
if (text !== textKey) {
this.send(text, action);
} else {
this.send(result.errorMessage ? result.errorMessage : result.message, action);
var text = this.translate.instant(textKey);
if (text === textKey) { // Error code on backend may not exist in frontend
if (result.errorMessage || result.message) {
text = result.errorMessage ? result.errorMessage : result.message;
} else {
text = this.translate.instant('ErrorPages.SomethingWentWrong');
}
}
this.send(text, action);
}
}

@ -9,7 +9,7 @@ import { TesterService, NotificationService, RadarrService } from "../../../serv
selector: "ombi-settings-radarr-form",
templateUrl: "./radarr-form.component.html",
styleUrls: ["./radarr-form.component.scss"],
// changeDetection: ChangeDetectionStrategy.OnPush
changeDetection: ChangeDetectionStrategy.OnPush
})
export class RadarrFormComponent implements OnInit {
@ -23,11 +23,11 @@ export class RadarrFormComponent implements OnInit {
constructor(private radarrService: RadarrService,
private notificationService: NotificationService,
private testerService: TesterService,
private controlContainer: ControlContainer) { }
private controlContainer: ControlContainer) {
}
public ngOnInit() {
this.form = <FormGroup>this.controlContainer.control;
// this.toggleValidators();
this.qualities = [];
this.qualities.push({ name: "Please Select", id: -1 });

@ -8,11 +8,13 @@
<mat-tab-group dynamicHeight>
<mat-tab label="Radarr">
<ombi-settings-radarr-form
#normalForm
formGroupName="radarr">
</ombi-settings-radarr-form>
</mat-tab>
<mat-tab *ngIf="is4kEnabled" label="Radarr 4K">
<ombi-settings-radarr-form
#4kForm
formGroupName="radarr4K">
</ombi-settings-radarr-form>
</mat-tab>

@ -1,9 +1,10 @@
import { Component, OnInit } from "@angular/core";
import { Component, OnInit, QueryList, ViewChild, ViewChildren } from "@angular/core";
import { FormBuilder, FormGroup } from "@angular/forms";
import { IMinimumAvailability, IRadarrCombined, IRadarrProfile, IRadarrRootFolder } from "../../interfaces";
import { NotificationService, SettingsService } from "../../services";
import { FeaturesFacade } from "../../state/features/features.facade";
import { RadarrFormComponent } from "./components/radarr-form.component";
@Component({
templateUrl: "./radarr.component.html",
@ -19,11 +20,15 @@ export class RadarrComponent implements OnInit {
public form: FormGroup;
public is4kEnabled: boolean = false;
@ViewChildren('4kForm') public form4k: QueryList<RadarrFormComponent>;
@ViewChildren('normalForm') public normalForm: QueryList<RadarrFormComponent>;
constructor(private settingsService: SettingsService,
private notificationService: NotificationService,
private featureFacade: FeaturesFacade,
private fb: FormBuilder) { }
public ngOnInit() {
this.is4kEnabled = this.featureFacade.is4kEnabled();
this.settingsService.getRadarr()
@ -56,7 +61,16 @@ export class RadarrComponent implements OnInit {
scanForAvailability: [x.radarr4K.scanForAvailability]
}),
});
this.normalForm.changes.forEach((comp => {
comp.first.toggleValidators();
}))
if (this.is4kEnabled) {
this.form4k.changes.forEach((comp => {
comp.first.toggleValidators();
}))
}
});
}

@ -2,7 +2,7 @@
<div class="buttons">
<button type="button" mat-raised-button color="primary" data-test="adduserbtn" [routerLink]="['/usermanagement/user']">Add User To Ombi</button>
<a type="button" mat-raised-button color="primary" data-test="adduserbtn" [routerLink]="['/usermanagement/user']">Add User To Ombi</a>
<button type="button" style="float:right;" mat-raised-button color="primary" (click)="showBulkEdit = !showBulkEdit" [disabled]="this.selection.selected.length <= 0">Bulk Edit</button>
@ -105,7 +105,7 @@
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef> </th>
<td mat-cell *matCellDef="let u">
<button id="edit{{u.userName}}" mat-raised-button color="accent" [routerLink]="['/usermanagement/user/' + u.id]">Edit</button>
<a id="edit{{u.userName}}" mat-raised-button color="accent" [routerLink]="['/usermanagement/user/' + u.id]">Edit</a>
<button *ngIf="!u.hasLoggedIn" mat-raised-button color="accent" (click)="welcomeEmail(u)" [disabled]="!applicationUrl"><i class="far fa-paper-plane"></i> Welcome</button>
</td>
</ng-container>

@ -142,6 +142,10 @@
background-color: $ombi-active;
}
a.mat-raised-button {
text-decoration:none;
}
hr {
border-top: 1px solid $accent-dark;
}

@ -282,11 +282,18 @@ namespace Ombi.Controllers.V1.External
{
try
{
var currentUser = await GetCurrentUserAsync();
if (!currentUser.Email.HasValue())
{
throw new Exception($"User '{currentUser.UserName}' has no email address set on their user profile.");
}
var message = new NotificationMessage
{
Message = "This is just a test! Success!",
Subject = $"Ombi: Test",
To = (await GetCurrentUserAsync()).Email,
To = currentUser.Email,
};
message.Other.Add("PlainTextBody", "This is just a test! Success!");
@ -539,7 +546,7 @@ namespace Ombi.Controllers.V1.External
{
var user = await UserManager.Users.Include(x => x.UserNotificationPreferences).FirstOrDefaultAsync(x => x.UserName == HttpContext.User.Identity.Name);
var status = await WhatsAppApi.SendMessage(new WhatsAppModel {
From = settings.From,

@ -60,7 +60,8 @@
"CheckPageForUpdates": "Check this page for continuous site updates."
},
"ErrorPages": {
"NotFound": "Page not found"
"NotFound": "Page not found",
"SomethingWentWrong": "Something went wrong!"
},
"NavigationBar": {
"Discover": "Discover",

@ -1,3 +1,3 @@
{
"version": "4.16.14"
"version": "4.16.17"
}
Loading…
Cancel
Save