A lot more lidarr work, i'm done for the day wow... !wip #2313

This commit is contained in:
Jamie 2018-08-24 23:02:40 +01:00
parent 207c60b7f8
commit 3750243f11
19 changed files with 174 additions and 94 deletions

View file

@ -7,6 +7,6 @@
public int trackCount { get; set; } public int trackCount { get; set; }
public int totalTrackCount { get; set; } public int totalTrackCount { get; set; }
public int sizeOnDisk { get; set; } public int sizeOnDisk { get; set; }
public decimal percentOfTracks { get; set; } public decimal percentOfEpisodes { get; set; }
} }
} }

View file

@ -73,7 +73,7 @@ namespace Ombi.Core.Engine
var vm = new List<SearchArtistViewModel>(); var vm = new List<SearchArtistViewModel>();
foreach (var r in result) foreach (var r in result)
{ {
vm.Add(MapIntoArtistVm(r)); vm.Add(await MapIntoArtistVm(r));
} }
return vm; return vm;
@ -107,7 +107,7 @@ namespace Ombi.Core.Engine
return await _lidarrApi.GetArtist(artistId, settings.ApiKey, settings.FullUri); return await _lidarrApi.GetArtist(artistId, settings.ApiKey, settings.FullUri);
} }
private SearchArtistViewModel MapIntoArtistVm(ArtistLookup a) private async Task<SearchArtistViewModel> MapIntoArtistVm(ArtistLookup a)
{ {
var vm = new SearchArtistViewModel var vm = new SearchArtistViewModel
{ {
@ -128,6 +128,9 @@ namespace Ombi.Core.Engine
vm.Poster = a.remotePoster; vm.Poster = a.remotePoster;
} }
await Rules.StartSpecificRules(vm, SpecificRules.LidarrArtist);
return vm; return vm;
} }
@ -162,6 +165,10 @@ namespace Ombi.Core.Engine
vm.Cover = a.remoteCover; vm.Cover = a.remoteCover;
} }
await Rules.StartSpecificRules(vm, SpecificRules.LidarrAlbum);
await RunSearchRules(vm);
return vm; return vm;
} }
private LidarrSettings _settings; private LidarrSettings _settings;

View file

@ -1,8 +1,9 @@
using System; using System;
using Ombi.Store.Entities;
namespace Ombi.Core.Models.Search namespace Ombi.Core.Models.Search
{ {
public class SearchAlbumViewModel public class SearchAlbumViewModel : SearchViewModel
{ {
public string Title { get; set; } public string Title { get; set; }
public string ForeignAlbumId { get; set; } public string ForeignAlbumId { get; set; }
@ -14,6 +15,9 @@ namespace Ombi.Core.Models.Search
public string ForeignArtistId { get; set; } public string ForeignArtistId { get; set; }
public string Cover { get; set; } public string Cover { get; set; }
public string Disk { get; set; } public string Disk { get; set; }
public decimal PercentOfTracks { get; set; }
public override RequestType Type => RequestType.Album;
public bool PartiallyAvailable => PercentOfTracks != 100 && PercentOfTracks > 0;
public bool FullyAvailable => PercentOfTracks == 100;
} }
} }

View file

@ -12,8 +12,6 @@ namespace Ombi.Core.Models.Search
public string Poster { get; set; } public string Poster { get; set; }
public string Logo { get; set; } public string Logo { get; set; }
public bool Monitored { get; set; } public bool Monitored { get; set; }
public bool Available { get; set; }
public bool Requested { get; set; }
public string ArtistType { get; set; } public string ArtistType { get; set; }
public string CleanName { get; set; } public string CleanName { get; set; }
public Link[] Links { get; set; } // Couldn't be bothered to map it public Link[] Links { get; set; } // Couldn't be bothered to map it

View file

@ -3,5 +3,7 @@
public enum SpecificRules public enum SpecificRules
{ {
CanSendNotification, CanSendNotification,
LidarrArtist,
LidarrAlbum,
} }
} }

View file

@ -11,13 +11,15 @@ namespace Ombi.Core.Rule.Rules.Search
{ {
public class ExistingRule : BaseSearchRule, IRules<SearchViewModel> public class ExistingRule : BaseSearchRule, IRules<SearchViewModel>
{ {
public ExistingRule(IMovieRequestRepository movie, ITvRequestRepository tv) public ExistingRule(IMovieRequestRepository movie, ITvRequestRepository tv, IMusicRequestRepository music)
{ {
Movie = movie; Movie = movie;
Tv = tv; Tv = tv;
Music = music;
} }
private IMovieRequestRepository Movie { get; } private IMovieRequestRepository Movie { get; }
private IMusicRequestRepository Music { get; }
private ITvRequestRepository Tv { get; } private ITvRequestRepository Tv { get; }
public async Task<RuleResult> Execute(SearchViewModel obj) public async Task<RuleResult> Execute(SearchViewModel obj)
@ -37,7 +39,7 @@ namespace Ombi.Core.Rule.Rules.Search
} }
return Success(); return Success();
} }
else if (obj.Type == RequestType.Album) if (obj.Type == RequestType.TvShow)
{ {
//var tvRequests = Tv.GetRequest(obj.Id); //var tvRequests = Tv.GetRequest(obj.Id);
//if (tvRequests != null) // Do we already have a request for this? //if (tvRequests != null) // Do we already have a request for this?
@ -96,6 +98,21 @@ namespace Ombi.Core.Rule.Rules.Search
return Success(); return Success();
} }
if (obj.Type == RequestType.Album)
{
var album = (SearchAlbumViewModel) obj;
var albumRequest = await Music.GetRequestAsync(album.ForeignAlbumId);
if (albumRequest != null) // Do we already have a request for this?
{
obj.Requested = true;
obj.RequestId = albumRequest.Id;
obj.Approved = albumRequest.Approved;
obj.Available = albumRequest.Available;
return Success();
}
return Success();
}
return Success(); return Success();
} }
} }

View file

@ -0,0 +1,36 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Ombi.Core.Models.Search;
using Ombi.Core.Rule.Interfaces;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
namespace Ombi.Core.Rule.Rules.Search
{
public class LidarrAlbumCacheRule : SpecificRule, ISpecificRule<object>
{
public LidarrAlbumCacheRule(IRepository<LidarrAlbumCache> db)
{
_db = db;
}
private readonly IRepository<LidarrAlbumCache> _db;
public Task<RuleResult> Execute(object objec)
{
var obj = (SearchAlbumViewModel) objec;
// Check if it's in Lidarr
var result = _db.GetAll().FirstOrDefault(x => x.ForeignAlbumId.Equals(obj.ForeignAlbumId, StringComparison.InvariantCultureIgnoreCase));
if (result != null)
{
obj.PercentOfTracks = result.PercentOfTracks;
obj.Monitored = true; // It's in Lidarr so it's monitored
}
return Task.FromResult(Success());
}
public override SpecificRules Rule => SpecificRules.LidarrAlbum;
}
}

View file

@ -0,0 +1,35 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Ombi.Core.Models.Search;
using Ombi.Core.Rule.Interfaces;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
namespace Ombi.Core.Rule.Rules.Search
{
public class LidarrArtistCacheRule : SpecificRule, ISpecificRule<object>
{
public LidarrArtistCacheRule(IRepository<LidarrArtistCache> db)
{
_db = db;
}
private readonly IRepository<LidarrArtistCache> _db;
public Task<RuleResult> Execute(object objec)
{
var obj = (SearchArtistViewModel) objec;
// Check if it's in Lidarr
var result = _db.GetAll().FirstOrDefault(x => x.ForeignArtistId.Equals(obj.ForignArtistId, StringComparison.InvariantCultureIgnoreCase));
if (result != null)
{
obj.Monitored = true; // It's in Lidarr so it's monitored
}
return Task.FromResult(Success());
}
public override SpecificRules Rule => SpecificRules.LidarrArtist;
}
}

View file

@ -48,23 +48,24 @@ namespace Ombi.Schedule.Jobs.Lidarr
// Let's remove the old cached data // Let's remove the old cached data
await _ctx.Database.ExecuteSqlCommandAsync("DELETE FROM LidarrAlbumCache"); await _ctx.Database.ExecuteSqlCommandAsync("DELETE FROM LidarrAlbumCache");
var artistCache = new List<LidarrAlbumCache>(); var albumCache = new List<LidarrAlbumCache>();
foreach (var a in albums) foreach (var a in albums)
{ {
if (a.id > 0) if (a.id > 0)
{ {
artistCache.Add(new LidarrAlbumCache albumCache.Add(new LidarrAlbumCache
{ {
ArtistId = a.artistId, ArtistId = a.artistId,
ForeignAlbumId = a.foreignAlbumId, ForeignAlbumId = a.foreignAlbumId,
ReleaseDate = a.releaseDate, ReleaseDate = a.releaseDate,
TrackCount = a.currentRelease.trackCount, TrackCount = a.currentRelease.trackCount,
Monitored = a.monitored, Monitored = a.monitored,
Title = a.title Title = a.title,
PercentOfTracks = a.statistics?.percentOfEpisodes ?? 0m
}); });
} }
} }
await _ctx.LidarrAlbumCache.AddRangeAsync(artistCache); await _ctx.LidarrAlbumCache.AddRangeAsync(albumCache);
await _ctx.SaveChangesAsync(); await _ctx.SaveChangesAsync();
} }

View file

@ -12,8 +12,6 @@ namespace Ombi.Store.Entities
public DateTime ReleaseDate { get; set; } public DateTime ReleaseDate { get; set; }
public bool Monitored { get; set; } public bool Monitored { get; set; }
public string Title { get; set; } public string Title { get; set; }
public decimal PercentOfTracks { get; set; }
[ForeignKey(nameof(ArtistId))]
public LidarrArtistCache Artist { get; set; }
} }
} }

View file

@ -6,12 +6,9 @@ namespace Ombi.Store.Entities
[Table("LidarrArtistCache")] [Table("LidarrArtistCache")]
public class LidarrArtistCache : Entity public class LidarrArtistCache : Entity
{ {
[ForeignKey(nameof(ArtistId))]
public int ArtistId { get; set; } public int ArtistId { get; set; }
public string ArtistName { get; set; } public string ArtistName { get; set; }
public string ForeignArtistId { get; set; } public string ForeignArtistId { get; set; }
public bool Monitored { get; set; } public bool Monitored { get; set; }
public List<LidarrAlbumCache> Albums { get; set; }
} }
} }

View file

@ -9,7 +9,7 @@ using Ombi.Store.Context;
namespace Ombi.Store.Migrations namespace Ombi.Store.Migrations
{ {
[DbContext(typeof(OmbiContext))] [DbContext(typeof(OmbiContext))]
[Migration("20180824202308_LidarrSyncJobs")] [Migration("20180824211553_LidarrSyncJobs")]
partial class LidarrSyncJobs partial class LidarrSyncJobs
{ {
protected override void BuildTargetModel(ModelBuilder modelBuilder) protected override void BuildTargetModel(ModelBuilder modelBuilder)
@ -257,6 +257,8 @@ namespace Ombi.Store.Migrations
b.Property<bool>("Monitored"); b.Property<bool>("Monitored");
b.Property<decimal>("PercentOfTracks");
b.Property<DateTime>("ReleaseDate"); b.Property<DateTime>("ReleaseDate");
b.Property<string>("Title"); b.Property<string>("Title");
@ -265,8 +267,6 @@ namespace Ombi.Store.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("ArtistId");
b.ToTable("LidarrAlbumCache"); b.ToTable("LidarrAlbumCache");
}); });
@ -965,14 +965,6 @@ namespace Ombi.Store.Migrations
.HasPrincipalKey("EmbyId"); .HasPrincipalKey("EmbyId");
}); });
modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b =>
{
b.HasOne("Ombi.Store.Entities.LidarrArtistCache", "Artist")
.WithMany("Albums")
.HasForeignKey("ArtistId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b =>
{ {
b.HasOne("Ombi.Store.Entities.OmbiUser", "User") b.HasOne("Ombi.Store.Entities.OmbiUser", "User")

View file

@ -7,6 +7,25 @@ namespace Ombi.Store.Migrations
{ {
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)
{ {
migrationBuilder.CreateTable(
name: "LidarrAlbumCache",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
ArtistId = table.Column<int>(nullable: false),
ForeignAlbumId = table.Column<string>(nullable: true),
TrackCount = table.Column<int>(nullable: false),
ReleaseDate = table.Column<DateTime>(nullable: false),
Monitored = table.Column<bool>(nullable: false),
Title = table.Column<string>(nullable: true),
PercentOfTracks = table.Column<decimal>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_LidarrAlbumCache", x => x.Id);
});
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "LidarrArtistCache", name: "LidarrArtistCache",
columns: table => new columns: table => new
@ -22,35 +41,6 @@ namespace Ombi.Store.Migrations
{ {
table.PrimaryKey("PK_LidarrArtistCache", x => x.Id); table.PrimaryKey("PK_LidarrArtistCache", x => x.Id);
}); });
migrationBuilder.CreateTable(
name: "LidarrAlbumCache",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
ArtistId = table.Column<int>(nullable: false),
ForeignAlbumId = table.Column<string>(nullable: true),
TrackCount = table.Column<int>(nullable: false),
ReleaseDate = table.Column<DateTime>(nullable: false),
Monitored = table.Column<bool>(nullable: false),
Title = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_LidarrAlbumCache", x => x.Id);
table.ForeignKey(
name: "FK_LidarrAlbumCache_LidarrArtistCache_ArtistId",
column: x => x.ArtistId,
principalTable: "LidarrArtistCache",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_LidarrAlbumCache_ArtistId",
table: "LidarrAlbumCache",
column: "ArtistId");
} }
protected override void Down(MigrationBuilder migrationBuilder) protected override void Down(MigrationBuilder migrationBuilder)

View file

@ -255,6 +255,8 @@ namespace Ombi.Store.Migrations
b.Property<bool>("Monitored"); b.Property<bool>("Monitored");
b.Property<decimal>("PercentOfTracks");
b.Property<DateTime>("ReleaseDate"); b.Property<DateTime>("ReleaseDate");
b.Property<string>("Title"); b.Property<string>("Title");
@ -263,8 +265,6 @@ namespace Ombi.Store.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("ArtistId");
b.ToTable("LidarrAlbumCache"); b.ToTable("LidarrAlbumCache");
}); });
@ -963,14 +963,6 @@ namespace Ombi.Store.Migrations
.HasPrincipalKey("EmbyId"); .HasPrincipalKey("EmbyId");
}); });
modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b =>
{
b.HasOne("Ombi.Store.Entities.LidarrArtistCache", "Artist")
.WithMany("Albums")
.HasForeignKey("ArtistId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b =>
{ {
b.HasOne("Ombi.Store.Entities.OmbiUser", "User") b.HasOne("Ombi.Store.Entities.OmbiUser", "User")

View file

@ -29,6 +29,8 @@ export interface ILink {
} }
export interface ISearchAlbumResult { export interface ISearchAlbumResult {
id: number;
requestId: number;
albumType: string; albumType: string;
artistName: string; artistName: string;
cover: string; cover: string;
@ -39,10 +41,11 @@ export interface ISearchAlbumResult {
rating: number; rating: number;
releaseDate: Date; releaseDate: Date;
title: string; title: string;
approved: boolean; fullyAvailable: boolean;
partiallyAvailable: boolean;
requested: boolean; requested: boolean;
requestId: number; approved: boolean;
available: boolean; subscribed: boolean;
// for the UI // for the UI
showSubscribe: boolean; showSubscribe: boolean;

View file

@ -33,6 +33,25 @@
<a *ngIf="result.homepage" href="{{result.homepage}}" id="homePageLabel" target="_blank"><span class="label label-info" [translate]="'Search.Movies.HomePage'"></span></a> <a *ngIf="result.homepage" href="{{result.homepage}}" id="homePageLabel" target="_blank"><span class="label label-info" [translate]="'Search.Movies.HomePage'"></span></a>
<a *ngIf="result.trailer" href="{{result.trailer}}" id="trailerLabel" target="_blank"><span class="label label-info" [translate]="'Search.Movies.Trailer'"></span></a> --> <a *ngIf="result.trailer" href="{{result.trailer}}" id="trailerLabel" target="_blank"><span class="label label-info" [translate]="'Search.Movies.Trailer'"></span></a> -->
<ng-template [ngIf]="!result.requested && !result.fullyAvailable && !result.approved">
<span class="label label-danger" id="notRequestedLabel" [translate]="'Common.NotRequested'"></span>
</ng-template>
<ng-template [ngIf]="result.fullyAvailable">
<span class="label label-success" id="availableLabel" [translate]="'Common.Available'"></span>
</ng-template>
<ng-template [ngIf]="result.partiallyAvailable">
<span class="label label-info" id="availableLabel" [translate]="'Common.PartiallyAvailable'"></span>
</ng-template>
<ng-template [ngIf]="result.monitored && !result.fullyAvailable">
<span class="label label-info" id="processingRequestLabel" [translate]="'Common.Monitored'"></span>
</ng-template>
<ng-template [ngIf]="result.requested && !result.approved && !result.available">
<span class="label label-warning" id="pendingApprovalLabel" [translate]="'Common.PendingApproval'"></span>
</ng-template>
<ng-template [ngIf]="result.approved && !result.available"><span class="label label-info" id="processingRequestLabel" [translate]="'Common.ProcessingRequest'"></span></ng-template>
<ng-template [ngIf]="result.releaseDate"> <ng-template [ngIf]="result.releaseDate">
<span class="label label-info" id="availableLabel">Release Date: {{result.releaseDate | date:'yyyy-MM-dd'}}</span> <span class="label label-info" id="availableLabel">Release Date: {{result.releaseDate | date:'yyyy-MM-dd'}}</span>
@ -42,20 +61,6 @@
</ng-template> </ng-template>
<ng-template [ngIf]="result.available">
<span class="label label-success" id="availableLabel" [translate]="'Common.Available'"></span>
</ng-template>
<ng-template [ngIf]="result.approved && !result.available">
<span class="label label-info" id="processingRequestLabel" [translate]="'Common.ProcessingRequest'"></span>
</ng-template>
<ng-template [ngIf]="result.requested && !result.approved && !result.available">
<span class="label label-warning" id="pendingApprovalLabel" [translate]="'Common.PendingApproval'"></span>
</ng-template>
<ng-template [ngIf]="!result.requested && !result.available && !result.approved">
<span class="label label-danger" id="notRequestedLabel" [translate]="'Common.NotRequested'"></span>
</ng-template>
</span> </span>
</div> </div>

View file

@ -34,6 +34,7 @@ export class JobsComponent implements OnInit {
refreshMetadata: [x.refreshMetadata, Validators.required], refreshMetadata: [x.refreshMetadata, Validators.required],
newsletter: [x.newsletter, Validators.required], newsletter: [x.newsletter, Validators.required],
plexRecentlyAddedSync: [x.plexRecentlyAddedSync, Validators.required], plexRecentlyAddedSync: [x.plexRecentlyAddedSync, Validators.required],
lidarrArtistSync: [x.lidarrArtistSync, Validators.required],
}); });
}); });
} }

View file

@ -3,14 +3,14 @@
"windowsAuthentication": false, "windowsAuthentication": false,
"anonymousAuthentication": true, "anonymousAuthentication": true,
"iisExpress": { "iisExpress": {
"applicationUrl": "http://localhost:3579/", "applicationUrl": "http://localhost:3577/",
"sslPort": 0 "sslPort": 0
} }
}, },
"profiles": { "profiles": {
"IIS Express": { "IIS Express": {
"commandName": "IISExpress", "commandName": "IISExpress",
"commandLineArgs": "--host http://*:3579", "commandLineArgs": "--host http://*:3577",
"launchBrowser": true, "launchBrowser": true,
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"

View file

@ -12,6 +12,8 @@
"Common": { "Common": {
"ContinueButton": "Continue", "ContinueButton": "Continue",
"Available": "Available", "Available": "Available",
"PartiallyAvailable": "Partially Available",
"Monitored": "Monitored",
"NotAvailable": "Not Available", "NotAvailable": "Not Available",
"ProcessingRequest": "Processing Request", "ProcessingRequest": "Processing Request",
"PendingApproval": "Pending Approval", "PendingApproval": "Pending Approval",