mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-14 09:12:57 -07:00
Added the ability to re-process requests
This commit is contained in:
parent
6c64f3d4a3
commit
264568f396
15 changed files with 115 additions and 6 deletions
|
@ -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…
Add table
Add a link
Reference in a new issue