Added the ability to re-process requests

pull/4185/head v4.0.1345
tidusjar 4 years ago
parent 6c64f3d4a3
commit 264568f396

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ombi.Core.Models; using Ombi.Core.Models;
using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests;
@ -24,5 +25,6 @@ namespace Ombi.Core.Engine.Interfaces
Task UnSubscribeRequest(int requestId, RequestType type); Task UnSubscribeRequest(int requestId, RequestType type);
Task SubscribeToRequest(int requestId, RequestType type); Task SubscribeToRequest(int requestId, RequestType type);
Task<RequestQuotaCountModel> GetRemainingRequests(OmbiUser user = null); Task<RequestQuotaCountModel> GetRemainingRequests(OmbiUser user = null);
Task<RequestEngineResult> ReProcessRequest(int requestId, CancellationToken cancellationToken);
} }
} }

@ -21,6 +21,7 @@ using Ombi.Settings.Settings.Models;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository; using Ombi.Store.Repository;
using Ombi.Core.Models; using Ombi.Core.Models;
using System.Threading;
namespace Ombi.Core.Engine namespace Ombi.Core.Engine
{ {
@ -555,6 +556,11 @@ namespace Ombi.Core.Engine
await NotificationHelper.Notify(request, NotificationType.RequestApproved); await NotificationHelper.Notify(request, NotificationType.RequestApproved);
} }
return await ProcessSendingMovie(request);
}
private async Task<RequestEngineResult> ProcessSendingMovie(MovieRequests request)
{
if (request.Approved) if (request.Approved)
{ {
var result = await Sender.Send(request); var result = await Sender.Send(request);
@ -634,6 +640,21 @@ namespace Ombi.Core.Engine
return await MovieRepository.GetAll().AnyAsync(x => x.RequestedUserId == userId); return await MovieRepository.GetAll().AnyAsync(x => x.RequestedUserId == userId);
} }
public async Task<RequestEngineResult> ReProcessRequest(int requestId, CancellationToken cancellationToken)
{
var request = await MovieRepository.Find(requestId);
if (request == null)
{
return new RequestEngineResult
{
Result = false,
ErrorMessage = "Request does not exist"
};
}
return await ProcessSendingMovie(request);
}
public async Task<RequestEngineResult> MarkUnavailable(int modelId) public async Task<RequestEngineResult> MarkUnavailable(int modelId)
{ {
var request = await MovieRepository.Find(modelId); var request = await MovieRepository.Find(modelId);

@ -25,6 +25,7 @@ using Ombi.Settings.Settings.Models;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository; using Ombi.Store.Repository;
using Ombi.Core.Models; using Ombi.Core.Models;
using System.Threading;
namespace Ombi.Core.Engine namespace Ombi.Core.Engine
{ {
@ -896,6 +897,22 @@ namespace Ombi.Core.Engine
} }
public async Task<RequestEngineResult> ReProcessRequest(int requestId, CancellationToken cancellationToken)
{
var request = await TvRepository.GetChild().FirstOrDefaultAsync(x => x.Id == requestId, cancellationToken);
if (request == null)
{
return new RequestEngineResult
{
Result = false,
ErrorMessage = "Request does not exist"
};
}
return await ProcessSendingShow(request);
}
private async Task<RequestEngineResult> AfterRequest(ChildRequests model, string requestOnBehalf) private async Task<RequestEngineResult> AfterRequest(ChildRequests model, string requestOnBehalf)
{ {
var sendRuleResult = await RunSpecificRule(model, SpecificRules.CanSendNotification); var sendRuleResult = await RunSpecificRule(model, SpecificRules.CanSendNotification);
@ -913,6 +930,11 @@ namespace Ombi.Core.Engine
EpisodeCount = model.SeasonRequests.Select(m => m.Episodes.Count).Sum(), EpisodeCount = model.SeasonRequests.Select(m => m.Episodes.Count).Sum(),
}); });
return await ProcessSendingShow(model);
}
private async Task<RequestEngineResult> ProcessSendingShow(ChildRequests model)
{
if (model.Approved) if (model.Approved)
{ {
// Autosend // Autosend

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Data.Sqlite; using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@ -28,6 +29,11 @@ namespace Ombi.Store.Repository
return await _db.FindAsync(key); return await _db.FindAsync(key);
} }
public async Task<T> Find(object key, CancellationToken cancellationToken)
{
return await _db.FindAsync(new[] { key }, cancellationToken: cancellationToken);
}
public IQueryable<T> GetAll() public IQueryable<T> GetAll()
{ {
return _db.AsQueryable(); return _db.AsQueryable();

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query;
@ -12,6 +13,7 @@ namespace Ombi.Store.Repository
public interface IRepository<T> where T : Entity public interface IRepository<T> where T : Entity
{ {
Task<T> Find(object key); Task<T> Find(object key);
Task<T> Find(object key, CancellationToken cancellationToken);
IQueryable<T> GetAll(); IQueryable<T> GetAll();
Task<T> FirstOrDefaultAsync(Expression<Func<T, bool>> predicate); Task<T> FirstOrDefaultAsync(Expression<Func<T, bool>> predicate);
Task AddRange(IEnumerable<T> content, bool save = true); Task AddRange(IEnumerable<T> content, bool save = true);

@ -24,6 +24,7 @@
[type]="requestType" [type]="requestType"
(openTrailer)="openDialog()" (openTrailer)="openDialog()"
(onAdvancedOptions)="openAdvancedOptions()" (onAdvancedOptions)="openAdvancedOptions()"
(onReProcessRequest)="reProcessRequest()"
> >
</social-icons> </social-icons>

@ -190,6 +190,16 @@ export class MovieDetailsComponent {
}); });
} }
public reProcessRequest() {
this.requestService2.reprocessRequest(this.movieRequest.id, RequestType.movie).subscribe(result => {
if (result.result) {
this.messageService.send(result.message ? result.message : "Successfully Re-processed the request", "Ok");
} else {
this.messageService.send(result.errorMessage, "Ok");
}
});
}
private loadBanner() { private loadBanner() {
this.imageService.getMovieBanner(this.theMovidDbId.toString()).subscribe(x => { this.imageService.getMovieBanner(this.theMovidDbId.toString()).subscribe(x => {
if (!this.movie.backdropPath) { if (!this.movie.backdropPath) {

@ -35,5 +35,9 @@
<span *ngIf="type === RequestType.movie"> {{ 'MediaDetails.RadarrConfiguration' | translate}}</span> <span *ngIf="type === RequestType.movie"> {{ 'MediaDetails.RadarrConfiguration' | translate}}</span>
<span *ngIf="type === RequestType.tvShow"> {{ 'MediaDetails.SonarrConfiguration' | translate}}</span> <span *ngIf="type === RequestType.tvShow"> {{ 'MediaDetails.SonarrConfiguration' | translate}}</span>
</button> </button>
<button *ngIf="type === RequestType.movie" mat-menu-item (click)="reProcessRequest()">
<i class="fas fa-sync icon-spacing"></i>
<span> {{ 'MediaDetails.ReProcessRequest' | translate}}</span>
</button>
</mat-menu> </mat-menu>
</div> </div>

@ -26,6 +26,7 @@ export class SocialIconsComponent {
@Output() openTrailer: EventEmitter<any> = new EventEmitter(); @Output() openTrailer: EventEmitter<any> = new EventEmitter();
@Output() onAdvancedOptions: EventEmitter<any> = new EventEmitter(); @Output() onAdvancedOptions: EventEmitter<any> = new EventEmitter();
@Output() onReProcessRequest: EventEmitter<any> = new EventEmitter();
public RequestType = RequestType; public RequestType = RequestType;
@ -37,4 +38,8 @@ export class SocialIconsComponent {
public openAdvancedOptions() { public openAdvancedOptions() {
this.onAdvancedOptions.emit(); this.onAdvancedOptions.emit();
} }
public reProcessRequest() {
this.onReProcessRequest.emit();
}
} }

@ -70,6 +70,7 @@
<button *ngIf="request.available" mat-raised-button color="warn" (click)="changeAvailability(request, false);">{{ 'Requests.MarkUnavailable' | translate }}</button> <button *ngIf="request.available" mat-raised-button color="warn" (click)="changeAvailability(request, false);">{{ 'Requests.MarkUnavailable' | translate }}</button>
<button *ngIf="!request.denied" mat-raised-button color="danger" (click)="deny(request);">{{ 'Requests.Deny' | translate }}</button> <button *ngIf="!request.denied" mat-raised-button color="danger" (click)="deny(request);">{{ 'Requests.Deny' | translate }}</button>
<button mat-raised-button color="danger" (click)="delete(request);">{{ 'Requests.RequestPanel.Delete' | translate }}</button> <button mat-raised-button color="danger" (click)="delete(request);">{{ 'Requests.RequestPanel.Delete' | translate }}</button>
<button mat-raised-button color="accent" (click)="reProcessRequest(request);">{{ 'MediaDetails.ReProcessRequest' | translate }}</button>
</div> </div>

@ -4,6 +4,7 @@ import { RequestService } from "../../../../../services/request.service";
import { MessageService } from "../../../../../services"; import { MessageService } from "../../../../../services";
import { MatDialog } from "@angular/material/dialog"; import { MatDialog } from "@angular/material/dialog";
import { DenyDialogComponent } from "../../../shared/deny-dialog/deny-dialog.component"; import { DenyDialogComponent } from "../../../shared/deny-dialog/deny-dialog.component";
import { RequestServiceV2 } from "../../../../../services/requestV2.service";
@Component({ @Component({
templateUrl: "./tv-requests-panel.component.html", templateUrl: "./tv-requests-panel.component.html",
@ -16,7 +17,9 @@ export class TvRequestsPanelComponent {
public displayedColumns: string[] = ['number', 'title', 'airDate', 'status']; public displayedColumns: string[] = ['number', 'title', 'airDate', 'status'];
constructor(private requestService: RequestService, private messageService: MessageService, constructor(private requestService: RequestService,
private requestService2: RequestServiceV2,
private messageService: MessageService,
public dialog: MatDialog) { public dialog: MatDialog) {
} }
@ -93,4 +96,14 @@ export class TvRequestsPanelComponent {
}); });
}); });
} }
public reProcessRequest(request: IChildRequests) {
this.requestService2.reprocessRequest(request.id, RequestType.tvShow).subscribe(result => {
if (result.result) {
this.messageService.send(result.message ? result.message : "Successfully Re-processed the request", "Ok");
} else {
this.messageService.send(result.errorMessage, "Ok");
}
});
}
} }

@ -187,5 +187,4 @@ export class RequestService extends ServiceHelpers {
public removeAlbumRequest(request: number): any { public removeAlbumRequest(request: number): any {
return this.http.delete(`${this.url}music/${request}`, {headers: this.headers}); return this.http.delete(`${this.url}music/${request}`, {headers: this.headers});
} }
} }

@ -4,7 +4,7 @@ import { Injectable, Inject } from "@angular/core";
import { HttpClient } from "@angular/common/http"; import { HttpClient } from "@angular/common/http";
import { Observable } from "rxjs"; import { Observable } from "rxjs";
import { ServiceHelpers } from "./service.helpers"; import { ServiceHelpers } from "./service.helpers";
import { IRequestsViewModel, IMovieRequests, IChildRequests, IMovieAdvancedOptions as IMediaAdvancedOptions, IRequestEngineResult, IAlbumRequest, ITvRequestViewModelV2 } from "../interfaces"; import { IRequestsViewModel, IMovieRequests, IChildRequests, IMovieAdvancedOptions as IMediaAdvancedOptions, IRequestEngineResult, IAlbumRequest, ITvRequestViewModelV2, RequestType } from "../interfaces";
@Injectable() @Injectable()
@ -92,4 +92,8 @@ export class RequestServiceV2 extends ServiceHelpers {
public requestTv(tv: ITvRequestViewModelV2): Observable<IRequestEngineResult> { public requestTv(tv: ITvRequestViewModelV2): Observable<IRequestEngineResult> {
return this.http.post<IRequestEngineResult>(`${this.url}TV/`, JSON.stringify(tv), {headers: this.headers}); return this.http.post<IRequestEngineResult>(`${this.url}TV/`, JSON.stringify(tv), {headers: this.headers});
} }
public reprocessRequest(requestId: number, type: RequestType): Observable<IRequestEngineResult> {
return this.http.post<IRequestEngineResult>(`${this.url}reprocess/${type}/${requestId}`, undefined, { headers: this.headers });
}
} }

@ -11,6 +11,7 @@ using System;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using System.Linq; using System.Linq;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Attributes;
namespace Ombi.Controllers.V2 namespace Ombi.Controllers.V2
{ {
@ -134,12 +135,14 @@ namespace Ombi.Controllers.V2
return await _tvRequestEngine.GetUnavailableRequests(count, position, sort, sortOrder); return await _tvRequestEngine.GetUnavailableRequests(count, position, sort, sortOrder);
} }
[PowerUser]
[HttpPost("movie/advancedoptions")] [HttpPost("movie/advancedoptions")]
public async Task<RequestEngineResult> UpdateAdvancedOptions([FromBody] MediaAdvancedOptions options) public async Task<RequestEngineResult> UpdateAdvancedOptions([FromBody] MediaAdvancedOptions options)
{ {
return await _movieRequestEngine.UpdateAdvancedOptions(options); return await _movieRequestEngine.UpdateAdvancedOptions(options);
} }
[PowerUser]
[HttpPost("tv/advancedoptions")] [HttpPost("tv/advancedoptions")]
public async Task<RequestEngineResult> UpdateTvAdvancedOptions([FromBody] MediaAdvancedOptions options) public async Task<RequestEngineResult> UpdateTvAdvancedOptions([FromBody] MediaAdvancedOptions options)
{ {
@ -198,6 +201,21 @@ namespace Ombi.Controllers.V2
return result; return result;
} }
[PowerUser]
[HttpPost("reprocess/{type}/{requestId}")]
public async Task<IActionResult> ReProcessRequest(RequestType type, int requestId)
{
switch (type)
{
case RequestType.TvShow:
return Ok(await _tvRequestEngine.ReProcessRequest(requestId, HttpContext.RequestAborted));
case RequestType.Movie:
return Ok(await _movieRequestEngine.ReProcessRequest(requestId, HttpContext.RequestAborted));
}
return BadRequest();
}
private string GetApiAlias() private string GetApiAlias()
{ {
// Make sure this only applies when using the API KEY // Make sure this only applies when using the API KEY

@ -288,7 +288,8 @@
"RadarrConfiguration": "Radarr Configuration", "RadarrConfiguration": "Radarr Configuration",
"RequestOnBehalf": "Request on behalf of", "RequestOnBehalf": "Request on behalf of",
"PleaseSelectUser": "Please select a user", "PleaseSelectUser": "Please select a user",
"StreamingOn": "Streaming On" "StreamingOn": "Streaming On",
"ReProcessRequest": "Re-Process Request"
}, },
"Discovery": { "Discovery": {
"PopularTab": "Popular", "PopularTab": "Popular",

Loading…
Cancel
Save