mirror of
https://github.com/Radarr/Radarr
synced 2026-01-25 08:53:02 +01:00
feat(tv): add core TV entities (TVShow, Season, Episode)
Phase 5 Part 2: Creates foundational TV infrastructure with anime support from day 1. Entities: - TVShow: Parent entity with TvdbId, TmdbId, ImdbId, AniDbId - Season: Grouping layer with TVShowId foreign key - Episode: Extends MediaItem with scene/absolute numbering - EpisodeFile: Media file tracking Features: - SeriesType enum (Standard, Daily, Anime) - TVShowStatus enum (Continuing, Ended, Upcoming, Canceled) - Complete repository/service pattern - Full event system for CRUD operations - Migration 252 creates all tables with indexes Also fixes SA1210 using directive order in BookSeriesController.
This commit is contained in:
parent
398a4b4bdd
commit
230a01cced
24 changed files with 957 additions and 1 deletions
114
src/NzbDrone.Core/Datastore/Migration/252_add_tv_tables.cs
Normal file
114
src/NzbDrone.Core/Datastore/Migration/252_add_tv_tables.cs
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(252)]
|
||||
public class add_tv_tables : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Create.TableForModel("TVShows")
|
||||
.WithColumn("TvdbId").AsInt32().NotNullable()
|
||||
.WithColumn("TmdbId").AsInt32().Nullable()
|
||||
.WithColumn("ImdbId").AsString().Nullable()
|
||||
.WithColumn("AniDbId").AsInt32().Nullable()
|
||||
.WithColumn("Title").AsString().NotNullable()
|
||||
.WithColumn("SortTitle").AsString().Nullable()
|
||||
.WithColumn("CleanTitle").AsString().Nullable()
|
||||
.WithColumn("Overview").AsString().Nullable()
|
||||
.WithColumn("Network").AsString().Nullable()
|
||||
.WithColumn("Status").AsInt32().NotNullable()
|
||||
.WithColumn("Runtime").AsInt32().Nullable()
|
||||
.WithColumn("AirTime").AsString().Nullable()
|
||||
.WithColumn("Certification").AsString().Nullable()
|
||||
.WithColumn("FirstAired").AsDateTime().Nullable()
|
||||
.WithColumn("Year").AsInt32().NotNullable()
|
||||
.WithColumn("Genres").AsString().Nullable()
|
||||
.WithColumn("OriginalLanguage").AsString().Nullable()
|
||||
.WithColumn("IsAnime").AsBoolean().NotNullable().WithDefaultValue(false)
|
||||
.WithColumn("SeriesType").AsInt32().NotNullable().WithDefaultValue(0)
|
||||
.WithColumn("UseSceneNumbering").AsBoolean().NotNullable().WithDefaultValue(false)
|
||||
.WithColumn("Path").AsString().Nullable()
|
||||
.WithColumn("RootFolderPath").AsString().Nullable()
|
||||
.WithColumn("QualityProfileId").AsInt32().NotNullable()
|
||||
.WithColumn("SeasonFolder").AsBoolean().NotNullable().WithDefaultValue(true)
|
||||
.WithColumn("Monitored").AsBoolean().NotNullable().WithDefaultValue(true)
|
||||
.WithColumn("MonitorNewItems").AsBoolean().NotNullable().WithDefaultValue(true)
|
||||
.WithColumn("Tags").AsString().Nullable()
|
||||
.WithColumn("Added").AsDateTime().NotNullable()
|
||||
.WithColumn("LastSearchTime").AsDateTime().Nullable();
|
||||
|
||||
Create.Index("IX_TVShows_TvdbId").OnTable("TVShows").OnColumn("TvdbId");
|
||||
Create.Index("IX_TVShows_Path").OnTable("TVShows").OnColumn("Path");
|
||||
Create.Index("IX_TVShows_Monitored").OnTable("TVShows").OnColumn("Monitored");
|
||||
|
||||
Create.TableForModel("Seasons")
|
||||
.WithColumn("TVShowId").AsInt32().NotNullable()
|
||||
.WithColumn("SeasonNumber").AsInt32().NotNullable()
|
||||
.WithColumn("Title").AsString().Nullable()
|
||||
.WithColumn("Overview").AsString().Nullable()
|
||||
.WithColumn("Monitored").AsBoolean().NotNullable().WithDefaultValue(true);
|
||||
|
||||
Create.Index("IX_Seasons_TVShowId").OnTable("Seasons").OnColumn("TVShowId");
|
||||
Create.Index("IX_Seasons_TVShowId_SeasonNumber").OnTable("Seasons")
|
||||
.OnColumn("TVShowId").Ascending()
|
||||
.OnColumn("SeasonNumber").Ascending();
|
||||
|
||||
Create.TableForModel("Episodes")
|
||||
.WithColumn("TVShowId").AsInt32().NotNullable()
|
||||
.WithColumn("SeasonId").AsInt32().NotNullable()
|
||||
.WithColumn("SeasonNumber").AsInt32().NotNullable()
|
||||
.WithColumn("EpisodeNumber").AsInt32().NotNullable()
|
||||
.WithColumn("AbsoluteEpisodeNumber").AsInt32().Nullable()
|
||||
.WithColumn("SceneSeasonNumber").AsInt32().Nullable()
|
||||
.WithColumn("SceneEpisodeNumber").AsInt32().Nullable()
|
||||
.WithColumn("SceneAbsoluteEpisodeNumber").AsInt32().Nullable()
|
||||
.WithColumn("Title").AsString().Nullable()
|
||||
.WithColumn("Overview").AsString().Nullable()
|
||||
.WithColumn("AirDate").AsDateTime().Nullable()
|
||||
.WithColumn("AirDateUtc").AsDateTime().Nullable()
|
||||
.WithColumn("Runtime").AsInt32().Nullable()
|
||||
.WithColumn("UnverifiedSceneNumbering").AsBoolean().NotNullable().WithDefaultValue(false)
|
||||
.WithColumn("EpisodeFileId").AsInt32().Nullable()
|
||||
.WithColumn("Monitored").AsBoolean().NotNullable().WithDefaultValue(true)
|
||||
.WithColumn("QualityProfileId").AsInt32().NotNullable()
|
||||
.WithColumn("Path").AsString().Nullable()
|
||||
.WithColumn("RootFolderPath").AsString().Nullable()
|
||||
.WithColumn("Added").AsDateTime().NotNullable()
|
||||
.WithColumn("Tags").AsString().Nullable()
|
||||
.WithColumn("LastSearchTime").AsDateTime().Nullable()
|
||||
.WithColumn("AuthorId").AsInt32().Nullable()
|
||||
.WithColumn("BookSeriesId").AsInt32().Nullable();
|
||||
|
||||
Create.Index("IX_Episodes_TVShowId").OnTable("Episodes").OnColumn("TVShowId");
|
||||
Create.Index("IX_Episodes_SeasonId").OnTable("Episodes").OnColumn("SeasonId");
|
||||
Create.Index("IX_Episodes_TVShowId_SeasonNumber_EpisodeNumber").OnTable("Episodes")
|
||||
.OnColumn("TVShowId").Ascending()
|
||||
.OnColumn("SeasonNumber").Ascending()
|
||||
.OnColumn("EpisodeNumber").Ascending();
|
||||
Create.Index("IX_Episodes_TVShowId_AbsoluteEpisodeNumber").OnTable("Episodes")
|
||||
.OnColumn("TVShowId").Ascending()
|
||||
.OnColumn("AbsoluteEpisodeNumber").Ascending();
|
||||
Create.Index("IX_Episodes_Monitored").OnTable("Episodes").OnColumn("Monitored");
|
||||
|
||||
Create.TableForModel("EpisodeFiles")
|
||||
.WithColumn("TVShowId").AsInt32().NotNullable()
|
||||
.WithColumn("SeasonNumber").AsInt32().NotNullable()
|
||||
.WithColumn("RelativePath").AsString().Nullable()
|
||||
.WithColumn("Path").AsString().Nullable()
|
||||
.WithColumn("Size").AsInt64().NotNullable()
|
||||
.WithColumn("DateAdded").AsDateTime().NotNullable()
|
||||
.WithColumn("SceneName").AsString().Nullable()
|
||||
.WithColumn("ReleaseGroup").AsString().Nullable()
|
||||
.WithColumn("Quality").AsString().Nullable()
|
||||
.WithColumn("Language").AsString().Nullable()
|
||||
.WithColumn("MediaInfo").AsString().Nullable();
|
||||
|
||||
Create.Index("IX_EpisodeFiles_TVShowId").OnTable("EpisodeFiles").OnColumn("TVShowId");
|
||||
Create.Index("IX_EpisodeFiles_TVShowId_SeasonNumber").OnTable("EpisodeFiles")
|
||||
.OnColumn("TVShowId").Ascending()
|
||||
.OnColumn("SeasonNumber").Ascending();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -49,6 +49,7 @@
|
|||
using NzbDrone.Core.RootFolders;
|
||||
using NzbDrone.Core.Tags;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.TV;
|
||||
using NzbDrone.Core.Update.History;
|
||||
using static Dapper.SqlMapper;
|
||||
|
||||
|
|
@ -163,6 +164,15 @@ public static void Map()
|
|||
|
||||
Mapper.Entity<MusicFile>("MusicFiles").RegisterModel();
|
||||
|
||||
Mapper.Entity<TVShow>("TVShows").RegisterModel();
|
||||
|
||||
Mapper.Entity<Season>("Seasons").RegisterModel();
|
||||
|
||||
Mapper.Entity<Episode>("Episodes").RegisterModel();
|
||||
|
||||
Mapper.Entity<EpisodeFile>("EpisodeFiles").RegisterModel()
|
||||
.Ignore(f => f.Path);
|
||||
|
||||
Mapper.Entity<QualityDefinition>("QualityDefinitions").RegisterModel()
|
||||
.Ignore(d => d.GroupName)
|
||||
.Ignore(d => d.Weight);
|
||||
|
|
|
|||
50
src/NzbDrone.Core/TV/Episode.cs
Normal file
50
src/NzbDrone.Core/TV/Episode.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
using System;
|
||||
using NzbDrone.Core.MediaItems;
|
||||
using NzbDrone.Core.MediaTypes;
|
||||
|
||||
namespace NzbDrone.Core.TV
|
||||
{
|
||||
public class Episode : MediaItem
|
||||
{
|
||||
public Episode()
|
||||
{
|
||||
MediaType = MediaType.TV;
|
||||
}
|
||||
|
||||
public int TVShowId { get; set; }
|
||||
public int SeasonId { get; set; }
|
||||
|
||||
public int SeasonNumber { get; set; }
|
||||
public int EpisodeNumber { get; set; }
|
||||
public int? AbsoluteEpisodeNumber { get; set; }
|
||||
|
||||
public int? SceneSeasonNumber { get; set; }
|
||||
public int? SceneEpisodeNumber { get; set; }
|
||||
public int? SceneAbsoluteEpisodeNumber { get; set; }
|
||||
|
||||
public string Title { get; set; }
|
||||
public string Overview { get; set; }
|
||||
|
||||
public DateTime? AirDate { get; set; }
|
||||
public DateTime? AirDateUtc { get; set; }
|
||||
public int? Runtime { get; set; }
|
||||
|
||||
public bool IsSpecial => SeasonNumber == 0;
|
||||
public bool UnverifiedSceneNumbering { get; set; }
|
||||
|
||||
public int? EpisodeFileId { get; set; }
|
||||
|
||||
public override string GetTitle() => Title;
|
||||
public override int GetYear() => AirDate?.Year ?? 0;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (AbsoluteEpisodeNumber.HasValue && SeasonNumber > 0)
|
||||
{
|
||||
return $"{Title} - S{SeasonNumber:00}E{EpisodeNumber:00} ({AbsoluteEpisodeNumber})";
|
||||
}
|
||||
|
||||
return $"{Title} - S{SeasonNumber:00}E{EpisodeNumber:00}";
|
||||
}
|
||||
}
|
||||
}
|
||||
31
src/NzbDrone.Core/TV/EpisodeFile.cs
Normal file
31
src/NzbDrone.Core/TV/EpisodeFile.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
||||
namespace NzbDrone.Core.TV
|
||||
{
|
||||
public class EpisodeFile : ModelBase
|
||||
{
|
||||
public int TVShowId { get; set; }
|
||||
public int SeasonNumber { get; set; }
|
||||
|
||||
public string RelativePath { get; set; }
|
||||
public string Path { get; set; }
|
||||
public long Size { get; set; }
|
||||
public DateTime DateAdded { get; set; }
|
||||
|
||||
public string SceneName { get; set; }
|
||||
public string ReleaseGroup { get; set; }
|
||||
|
||||
public QualityModel Quality { get; set; }
|
||||
public Language Language { get; set; }
|
||||
|
||||
public string MediaInfo { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Path;
|
||||
}
|
||||
}
|
||||
}
|
||||
38
src/NzbDrone.Core/TV/EpisodeFileRepository.cs
Normal file
38
src/NzbDrone.Core/TV/EpisodeFileRepository.cs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
|
||||
namespace NzbDrone.Core.TV
|
||||
{
|
||||
public interface IEpisodeFileRepository : IBasicRepository<EpisodeFile>
|
||||
{
|
||||
List<EpisodeFile> FindByTVShowId(int tvShowId);
|
||||
List<EpisodeFile> FindByTVShowIdAndSeasonNumber(int tvShowId, int seasonNumber);
|
||||
EpisodeFile FindByPath(string path);
|
||||
}
|
||||
|
||||
public class EpisodeFileRepository : BasicRepository<EpisodeFile>, IEpisodeFileRepository
|
||||
{
|
||||
public EpisodeFileRepository(IMainDatabase database,
|
||||
IEventAggregator eventAggregator)
|
||||
: base(database, eventAggregator)
|
||||
{
|
||||
}
|
||||
|
||||
public List<EpisodeFile> FindByTVShowId(int tvShowId)
|
||||
{
|
||||
return Query(f => f.TVShowId == tvShowId);
|
||||
}
|
||||
|
||||
public List<EpisodeFile> FindByTVShowIdAndSeasonNumber(int tvShowId, int seasonNumber)
|
||||
{
|
||||
return Query(f => f.TVShowId == tvShowId && f.SeasonNumber == seasonNumber);
|
||||
}
|
||||
|
||||
public EpisodeFile FindByPath(string path)
|
||||
{
|
||||
return Query(f => f.Path == path).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
80
src/NzbDrone.Core/TV/EpisodeRepository.cs
Normal file
80
src/NzbDrone.Core/TV/EpisodeRepository.cs
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
|
||||
namespace NzbDrone.Core.TV
|
||||
{
|
||||
public interface IEpisodeRepository : IBasicRepository<Episode>
|
||||
{
|
||||
List<Episode> FindByTVShowId(int tvShowId);
|
||||
List<Episode> FindBySeasonId(int seasonId);
|
||||
List<Episode> FindByTVShowIdAndSeasonNumber(int tvShowId, int seasonNumber);
|
||||
Episode FindByTVShowIdAndEpisode(int tvShowId, int seasonNumber, int episodeNumber);
|
||||
Episode FindByTVShowIdAndAbsoluteNumber(int tvShowId, int absoluteNumber);
|
||||
List<Episode> EpisodesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored);
|
||||
Episode FindByPath(string path);
|
||||
Dictionary<int, string> AllEpisodePaths();
|
||||
}
|
||||
|
||||
public class EpisodeRepository : BasicRepository<Episode>, IEpisodeRepository
|
||||
{
|
||||
public EpisodeRepository(IMainDatabase database,
|
||||
IEventAggregator eventAggregator)
|
||||
: base(database, eventAggregator)
|
||||
{
|
||||
}
|
||||
|
||||
public List<Episode> FindByTVShowId(int tvShowId)
|
||||
{
|
||||
return Query(e => e.TVShowId == tvShowId);
|
||||
}
|
||||
|
||||
public List<Episode> FindBySeasonId(int seasonId)
|
||||
{
|
||||
return Query(e => e.SeasonId == seasonId);
|
||||
}
|
||||
|
||||
public List<Episode> FindByTVShowIdAndSeasonNumber(int tvShowId, int seasonNumber)
|
||||
{
|
||||
return Query(e => e.TVShowId == tvShowId && e.SeasonNumber == seasonNumber);
|
||||
}
|
||||
|
||||
public Episode FindByTVShowIdAndEpisode(int tvShowId, int seasonNumber, int episodeNumber)
|
||||
{
|
||||
return Query(e => e.TVShowId == tvShowId &&
|
||||
e.SeasonNumber == seasonNumber &&
|
||||
e.EpisodeNumber == episodeNumber).FirstOrDefault();
|
||||
}
|
||||
|
||||
public Episode FindByTVShowIdAndAbsoluteNumber(int tvShowId, int absoluteNumber)
|
||||
{
|
||||
return Query(e => e.TVShowId == tvShowId &&
|
||||
e.AbsoluteEpisodeNumber == absoluteNumber).FirstOrDefault();
|
||||
}
|
||||
|
||||
public List<Episode> EpisodesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored)
|
||||
{
|
||||
var query = Query(e => e.AirDateUtc >= start && e.AirDateUtc <= end);
|
||||
|
||||
if (!includeUnmonitored)
|
||||
{
|
||||
query = query.Where(e => e.Monitored).ToList();
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
public Episode FindByPath(string path)
|
||||
{
|
||||
return Query(e => e.Path == path).FirstOrDefault();
|
||||
}
|
||||
|
||||
public Dictionary<int, string> AllEpisodePaths()
|
||||
{
|
||||
var episodes = All();
|
||||
return episodes.ToDictionary(e => e.Id, e => e.Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
112
src/NzbDrone.Core/TV/EpisodeService.cs
Normal file
112
src/NzbDrone.Core/TV/EpisodeService.cs
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.TV.Events;
|
||||
|
||||
namespace NzbDrone.Core.TV
|
||||
{
|
||||
public interface IEpisodeService
|
||||
{
|
||||
Episode GetEpisode(int episodeId);
|
||||
List<Episode> GetEpisodes(IEnumerable<int> episodeIds);
|
||||
List<Episode> GetEpisodesByTVShowId(int tvShowId);
|
||||
List<Episode> GetEpisodesBySeasonId(int seasonId);
|
||||
List<Episode> GetEpisodesByTVShowIdAndSeasonNumber(int tvShowId, int seasonNumber);
|
||||
Episode FindByTVShowIdAndEpisode(int tvShowId, int seasonNumber, int episodeNumber);
|
||||
Episode FindByTVShowIdAndAbsoluteNumber(int tvShowId, int absoluteNumber);
|
||||
Episode AddEpisode(Episode newEpisode);
|
||||
List<Episode> AddEpisodes(List<Episode> newEpisodes);
|
||||
void DeleteEpisode(int episodeId, bool deleteFiles);
|
||||
void DeleteEpisodes(List<int> episodeIds, bool deleteFiles);
|
||||
Episode UpdateEpisode(Episode episode);
|
||||
List<Episode> UpdateEpisodes(List<Episode> episodes);
|
||||
List<Episode> GetEpisodesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored);
|
||||
Episode FindByPath(string path);
|
||||
Dictionary<int, string> AllEpisodePaths();
|
||||
}
|
||||
|
||||
public class EpisodeService : IEpisodeService
|
||||
{
|
||||
private readonly IEpisodeRepository _episodeRepository;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public EpisodeService(IEpisodeRepository episodeRepository,
|
||||
IEventAggregator eventAggregator,
|
||||
Logger logger)
|
||||
{
|
||||
_episodeRepository = episodeRepository;
|
||||
_eventAggregator = eventAggregator;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public Episode GetEpisode(int episodeId) => _episodeRepository.Get(episodeId);
|
||||
public List<Episode> GetEpisodes(IEnumerable<int> episodeIds) => _episodeRepository.Get(episodeIds).ToList();
|
||||
public List<Episode> GetEpisodesByTVShowId(int tvShowId) => _episodeRepository.FindByTVShowId(tvShowId);
|
||||
public List<Episode> GetEpisodesBySeasonId(int seasonId) => _episodeRepository.FindBySeasonId(seasonId);
|
||||
public List<Episode> GetEpisodesByTVShowIdAndSeasonNumber(int tvShowId, int seasonNumber)
|
||||
=> _episodeRepository.FindByTVShowIdAndSeasonNumber(tvShowId, seasonNumber);
|
||||
public Episode FindByTVShowIdAndEpisode(int tvShowId, int seasonNumber, int episodeNumber)
|
||||
=> _episodeRepository.FindByTVShowIdAndEpisode(tvShowId, seasonNumber, episodeNumber);
|
||||
public Episode FindByTVShowIdAndAbsoluteNumber(int tvShowId, int absoluteNumber)
|
||||
=> _episodeRepository.FindByTVShowIdAndAbsoluteNumber(tvShowId, absoluteNumber);
|
||||
public Episode FindByPath(string path) => _episodeRepository.FindByPath(path);
|
||||
public Dictionary<int, string> AllEpisodePaths() => _episodeRepository.AllEpisodePaths();
|
||||
public List<Episode> GetEpisodesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored)
|
||||
=> _episodeRepository.EpisodesBetweenDates(start, end, includeUnmonitored);
|
||||
|
||||
public Episode AddEpisode(Episode newEpisode)
|
||||
{
|
||||
var episode = _episodeRepository.Insert(newEpisode);
|
||||
_eventAggregator.PublishEvent(new EpisodeAddedEvent(episode));
|
||||
return episode;
|
||||
}
|
||||
|
||||
public List<Episode> AddEpisodes(List<Episode> newEpisodes)
|
||||
{
|
||||
_episodeRepository.InsertMany(newEpisodes);
|
||||
|
||||
foreach (var episode in newEpisodes)
|
||||
{
|
||||
_eventAggregator.PublishEvent(new EpisodeAddedEvent(episode));
|
||||
}
|
||||
|
||||
return newEpisodes;
|
||||
}
|
||||
|
||||
public void DeleteEpisode(int episodeId, bool deleteFiles)
|
||||
{
|
||||
var episode = _episodeRepository.Get(episodeId);
|
||||
_episodeRepository.Delete(episodeId);
|
||||
_eventAggregator.PublishEvent(new EpisodeDeletedEvent(episode, deleteFiles));
|
||||
}
|
||||
|
||||
public void DeleteEpisodes(List<int> episodeIds, bool deleteFiles)
|
||||
{
|
||||
var episodes = _episodeRepository.Get(episodeIds).ToList();
|
||||
_episodeRepository.DeleteMany(episodeIds);
|
||||
|
||||
foreach (var episode in episodes)
|
||||
{
|
||||
_eventAggregator.PublishEvent(new EpisodeDeletedEvent(episode, deleteFiles));
|
||||
}
|
||||
}
|
||||
|
||||
public Episode UpdateEpisode(Episode episode)
|
||||
{
|
||||
var storedEpisode = _episodeRepository.Get(episode.Id);
|
||||
_episodeRepository.Update(episode);
|
||||
_eventAggregator.PublishEvent(new EpisodeEditedEvent(episode, storedEpisode));
|
||||
return episode;
|
||||
}
|
||||
|
||||
public List<Episode> UpdateEpisodes(List<Episode> episodes)
|
||||
{
|
||||
_episodeRepository.UpdateMany(episodes);
|
||||
_eventAggregator.PublishEvent(new EpisodesBulkEditedEvent(episodes));
|
||||
return episodes;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/NzbDrone.Core/TV/Events/EpisodeAddedEvent.cs
Normal file
14
src/NzbDrone.Core/TV/Events/EpisodeAddedEvent.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
using NzbDrone.Common.Messaging;
|
||||
|
||||
namespace NzbDrone.Core.TV.Events
|
||||
{
|
||||
public class EpisodeAddedEvent : IEvent
|
||||
{
|
||||
public Episode Episode { get; private set; }
|
||||
|
||||
public EpisodeAddedEvent(Episode episode)
|
||||
{
|
||||
Episode = episode;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
src/NzbDrone.Core/TV/Events/EpisodeDeletedEvent.cs
Normal file
16
src/NzbDrone.Core/TV/Events/EpisodeDeletedEvent.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using NzbDrone.Common.Messaging;
|
||||
|
||||
namespace NzbDrone.Core.TV.Events
|
||||
{
|
||||
public class EpisodeDeletedEvent : IEvent
|
||||
{
|
||||
public Episode Episode { get; private set; }
|
||||
public bool DeleteFiles { get; private set; }
|
||||
|
||||
public EpisodeDeletedEvent(Episode episode, bool deleteFiles)
|
||||
{
|
||||
Episode = episode;
|
||||
DeleteFiles = deleteFiles;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
src/NzbDrone.Core/TV/Events/EpisodeEditedEvent.cs
Normal file
16
src/NzbDrone.Core/TV/Events/EpisodeEditedEvent.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using NzbDrone.Common.Messaging;
|
||||
|
||||
namespace NzbDrone.Core.TV.Events
|
||||
{
|
||||
public class EpisodeEditedEvent : IEvent
|
||||
{
|
||||
public Episode Episode { get; private set; }
|
||||
public Episode OldEpisode { get; private set; }
|
||||
|
||||
public EpisodeEditedEvent(Episode episode, Episode oldEpisode)
|
||||
{
|
||||
Episode = episode;
|
||||
OldEpisode = oldEpisode;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
src/NzbDrone.Core/TV/Events/EpisodesBulkEditedEvent.cs
Normal file
15
src/NzbDrone.Core/TV/Events/EpisodesBulkEditedEvent.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
using System.Collections.Generic;
|
||||
using NzbDrone.Common.Messaging;
|
||||
|
||||
namespace NzbDrone.Core.TV.Events
|
||||
{
|
||||
public class EpisodesBulkEditedEvent : IEvent
|
||||
{
|
||||
public List<Episode> Episodes { get; private set; }
|
||||
|
||||
public EpisodesBulkEditedEvent(List<Episode> episodes)
|
||||
{
|
||||
Episodes = episodes;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/NzbDrone.Core/TV/Events/TVShowAddedEvent.cs
Normal file
14
src/NzbDrone.Core/TV/Events/TVShowAddedEvent.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
using NzbDrone.Common.Messaging;
|
||||
|
||||
namespace NzbDrone.Core.TV.Events
|
||||
{
|
||||
public class TVShowAddedEvent : IEvent
|
||||
{
|
||||
public TVShow TVShow { get; private set; }
|
||||
|
||||
public TVShowAddedEvent(TVShow tvShow)
|
||||
{
|
||||
TVShow = tvShow;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
src/NzbDrone.Core/TV/Events/TVShowDeletedEvent.cs
Normal file
16
src/NzbDrone.Core/TV/Events/TVShowDeletedEvent.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using NzbDrone.Common.Messaging;
|
||||
|
||||
namespace NzbDrone.Core.TV.Events
|
||||
{
|
||||
public class TVShowDeletedEvent : IEvent
|
||||
{
|
||||
public TVShow TVShow { get; private set; }
|
||||
public bool DeleteFiles { get; private set; }
|
||||
|
||||
public TVShowDeletedEvent(TVShow tvShow, bool deleteFiles)
|
||||
{
|
||||
TVShow = tvShow;
|
||||
DeleteFiles = deleteFiles;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
src/NzbDrone.Core/TV/Events/TVShowEditedEvent.cs
Normal file
16
src/NzbDrone.Core/TV/Events/TVShowEditedEvent.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using NzbDrone.Common.Messaging;
|
||||
|
||||
namespace NzbDrone.Core.TV.Events
|
||||
{
|
||||
public class TVShowEditedEvent : IEvent
|
||||
{
|
||||
public TVShow TVShow { get; private set; }
|
||||
public TVShow OldTVShow { get; private set; }
|
||||
|
||||
public TVShowEditedEvent(TVShow tvShow, TVShow oldTVShow)
|
||||
{
|
||||
TVShow = tvShow;
|
||||
OldTVShow = oldTVShow;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
src/NzbDrone.Core/TV/Events/TVShowsBulkEditedEvent.cs
Normal file
15
src/NzbDrone.Core/TV/Events/TVShowsBulkEditedEvent.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
using System.Collections.Generic;
|
||||
using NzbDrone.Common.Messaging;
|
||||
|
||||
namespace NzbDrone.Core.TV.Events
|
||||
{
|
||||
public class TVShowsBulkEditedEvent : IEvent
|
||||
{
|
||||
public List<TVShow> TVShows { get; private set; }
|
||||
|
||||
public TVShowsBulkEditedEvent(List<TVShow> tvShows)
|
||||
{
|
||||
TVShows = tvShows;
|
||||
}
|
||||
}
|
||||
}
|
||||
20
src/NzbDrone.Core/TV/Season.cs
Normal file
20
src/NzbDrone.Core/TV/Season.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
using NzbDrone.Core.Datastore;
|
||||
|
||||
namespace NzbDrone.Core.TV
|
||||
{
|
||||
public class Season : ModelBase
|
||||
{
|
||||
public int TVShowId { get; set; }
|
||||
public int SeasonNumber { get; set; }
|
||||
|
||||
public string Title { get; set; }
|
||||
public string Overview { get; set; }
|
||||
|
||||
public bool Monitored { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return SeasonNumber == 0 ? "Specials" : $"Season {SeasonNumber}";
|
||||
}
|
||||
}
|
||||
}
|
||||
38
src/NzbDrone.Core/TV/SeasonRepository.cs
Normal file
38
src/NzbDrone.Core/TV/SeasonRepository.cs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
|
||||
namespace NzbDrone.Core.TV
|
||||
{
|
||||
public interface ISeasonRepository : IBasicRepository<Season>
|
||||
{
|
||||
List<Season> FindByTVShowId(int tvShowId);
|
||||
Season FindByTVShowIdAndSeasonNumber(int tvShowId, int seasonNumber);
|
||||
List<Season> GetMonitored();
|
||||
}
|
||||
|
||||
public class SeasonRepository : BasicRepository<Season>, ISeasonRepository
|
||||
{
|
||||
public SeasonRepository(IMainDatabase database,
|
||||
IEventAggregator eventAggregator)
|
||||
: base(database, eventAggregator)
|
||||
{
|
||||
}
|
||||
|
||||
public List<Season> FindByTVShowId(int tvShowId)
|
||||
{
|
||||
return Query(s => s.TVShowId == tvShowId);
|
||||
}
|
||||
|
||||
public Season FindByTVShowIdAndSeasonNumber(int tvShowId, int seasonNumber)
|
||||
{
|
||||
return Query(s => s.TVShowId == tvShowId && s.SeasonNumber == seasonNumber).FirstOrDefault();
|
||||
}
|
||||
|
||||
public List<Season> GetMonitored()
|
||||
{
|
||||
return Query(s => s.Monitored);
|
||||
}
|
||||
}
|
||||
}
|
||||
78
src/NzbDrone.Core/TV/SeasonService.cs
Normal file
78
src/NzbDrone.Core/TV/SeasonService.cs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
|
||||
namespace NzbDrone.Core.TV
|
||||
{
|
||||
public interface ISeasonService
|
||||
{
|
||||
Season GetSeason(int seasonId);
|
||||
List<Season> GetSeasons(IEnumerable<int> seasonIds);
|
||||
List<Season> GetSeasonsByTVShowId(int tvShowId);
|
||||
Season FindByTVShowIdAndSeasonNumber(int tvShowId, int seasonNumber);
|
||||
Season AddSeason(Season newSeason);
|
||||
List<Season> AddSeasons(List<Season> newSeasons);
|
||||
void DeleteSeason(int seasonId);
|
||||
void DeleteSeasons(List<int> seasonIds);
|
||||
Season UpdateSeason(Season season);
|
||||
List<Season> UpdateSeasons(List<Season> seasons);
|
||||
List<Season> GetMonitored();
|
||||
}
|
||||
|
||||
public class SeasonService : ISeasonService
|
||||
{
|
||||
private readonly ISeasonRepository _seasonRepository;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public SeasonService(ISeasonRepository seasonRepository,
|
||||
IEventAggregator eventAggregator,
|
||||
Logger logger)
|
||||
{
|
||||
_seasonRepository = seasonRepository;
|
||||
_eventAggregator = eventAggregator;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public Season GetSeason(int seasonId) => _seasonRepository.Get(seasonId);
|
||||
public List<Season> GetSeasons(IEnumerable<int> seasonIds) => _seasonRepository.Get(seasonIds).ToList();
|
||||
public List<Season> GetSeasonsByTVShowId(int tvShowId) => _seasonRepository.FindByTVShowId(tvShowId);
|
||||
public Season FindByTVShowIdAndSeasonNumber(int tvShowId, int seasonNumber)
|
||||
=> _seasonRepository.FindByTVShowIdAndSeasonNumber(tvShowId, seasonNumber);
|
||||
public List<Season> GetMonitored() => _seasonRepository.GetMonitored();
|
||||
|
||||
public Season AddSeason(Season newSeason)
|
||||
{
|
||||
return _seasonRepository.Insert(newSeason);
|
||||
}
|
||||
|
||||
public List<Season> AddSeasons(List<Season> newSeasons)
|
||||
{
|
||||
_seasonRepository.InsertMany(newSeasons);
|
||||
return newSeasons;
|
||||
}
|
||||
|
||||
public void DeleteSeason(int seasonId)
|
||||
{
|
||||
_seasonRepository.Delete(seasonId);
|
||||
}
|
||||
|
||||
public void DeleteSeasons(List<int> seasonIds)
|
||||
{
|
||||
_seasonRepository.DeleteMany(seasonIds);
|
||||
}
|
||||
|
||||
public Season UpdateSeason(Season season)
|
||||
{
|
||||
_seasonRepository.Update(season);
|
||||
return season;
|
||||
}
|
||||
|
||||
public List<Season> UpdateSeasons(List<Season> seasons)
|
||||
{
|
||||
_seasonRepository.UpdateMany(seasons);
|
||||
return seasons;
|
||||
}
|
||||
}
|
||||
}
|
||||
9
src/NzbDrone.Core/TV/SeriesType.cs
Normal file
9
src/NzbDrone.Core/TV/SeriesType.cs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
namespace NzbDrone.Core.TV
|
||||
{
|
||||
public enum SeriesType
|
||||
{
|
||||
Standard = 0,
|
||||
Daily = 1,
|
||||
Anime = 2
|
||||
}
|
||||
}
|
||||
56
src/NzbDrone.Core/TV/TVShow.cs
Normal file
56
src/NzbDrone.Core/TV/TVShow.cs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Datastore;
|
||||
|
||||
namespace NzbDrone.Core.TV
|
||||
{
|
||||
public class TVShow : ModelBase
|
||||
{
|
||||
public TVShow()
|
||||
{
|
||||
Tags = new HashSet<int>();
|
||||
Genres = new List<string>();
|
||||
}
|
||||
|
||||
public int TvdbId { get; set; }
|
||||
public int? TmdbId { get; set; }
|
||||
public string ImdbId { get; set; }
|
||||
public int? AniDbId { get; set; }
|
||||
|
||||
public string Title { get; set; }
|
||||
public string SortTitle { get; set; }
|
||||
public string CleanTitle { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public string Network { get; set; }
|
||||
public TVShowStatus Status { get; set; }
|
||||
|
||||
public int? Runtime { get; set; }
|
||||
public string AirTime { get; set; }
|
||||
public string Certification { get; set; }
|
||||
public DateTime? FirstAired { get; set; }
|
||||
public int Year { get; set; }
|
||||
|
||||
public List<string> Genres { get; set; }
|
||||
public string OriginalLanguage { get; set; }
|
||||
|
||||
public bool IsAnime { get; set; }
|
||||
public SeriesType SeriesType { get; set; }
|
||||
public bool UseSceneNumbering { get; set; }
|
||||
|
||||
public string Path { get; set; }
|
||||
public string RootFolderPath { get; set; }
|
||||
public int QualityProfileId { get; set; }
|
||||
public bool SeasonFolder { get; set; }
|
||||
|
||||
public bool Monitored { get; set; }
|
||||
public bool MonitorNewItems { get; set; }
|
||||
public HashSet<int> Tags { get; set; }
|
||||
public DateTime Added { get; set; }
|
||||
public DateTime? LastSearchTime { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Title} ({Year})";
|
||||
}
|
||||
}
|
||||
}
|
||||
76
src/NzbDrone.Core/TV/TVShowRepository.cs
Normal file
76
src/NzbDrone.Core/TV/TVShowRepository.cs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
|
||||
namespace NzbDrone.Core.TV
|
||||
{
|
||||
public interface ITVShowRepository : IBasicRepository<TVShow>
|
||||
{
|
||||
bool TVShowPathExists(string path);
|
||||
TVShow FindByTvdbId(int tvdbId);
|
||||
TVShow FindByImdbId(string imdbId);
|
||||
TVShow FindByAniDbId(int aniDbId);
|
||||
TVShow FindByTitle(string title);
|
||||
TVShow FindByPath(string path);
|
||||
List<TVShow> GetMonitored();
|
||||
Dictionary<int, string> AllTVShowPaths();
|
||||
Dictionary<int, List<int>> AllTVShowTags();
|
||||
}
|
||||
|
||||
public class TVShowRepository : BasicRepository<TVShow>, ITVShowRepository
|
||||
{
|
||||
public TVShowRepository(IMainDatabase database,
|
||||
IEventAggregator eventAggregator)
|
||||
: base(database, eventAggregator)
|
||||
{
|
||||
}
|
||||
|
||||
public bool TVShowPathExists(string path)
|
||||
{
|
||||
return Query(s => s.Path == path).Any();
|
||||
}
|
||||
|
||||
public TVShow FindByTvdbId(int tvdbId)
|
||||
{
|
||||
return Query(s => s.TvdbId == tvdbId).FirstOrDefault();
|
||||
}
|
||||
|
||||
public TVShow FindByImdbId(string imdbId)
|
||||
{
|
||||
return Query(s => s.ImdbId == imdbId).FirstOrDefault();
|
||||
}
|
||||
|
||||
public TVShow FindByAniDbId(int aniDbId)
|
||||
{
|
||||
return Query(s => s.AniDbId == aniDbId).FirstOrDefault();
|
||||
}
|
||||
|
||||
public TVShow FindByTitle(string title)
|
||||
{
|
||||
return Query(s => s.Title == title).FirstOrDefault();
|
||||
}
|
||||
|
||||
public TVShow FindByPath(string path)
|
||||
{
|
||||
return Query(s => s.Path == path).FirstOrDefault();
|
||||
}
|
||||
|
||||
public List<TVShow> GetMonitored()
|
||||
{
|
||||
return Query(s => s.Monitored);
|
||||
}
|
||||
|
||||
public Dictionary<int, string> AllTVShowPaths()
|
||||
{
|
||||
var tvShows = All();
|
||||
return tvShows.ToDictionary(s => s.Id, s => s.Path);
|
||||
}
|
||||
|
||||
public Dictionary<int, List<int>> AllTVShowTags()
|
||||
{
|
||||
var tvShows = All();
|
||||
return tvShows.ToDictionary(s => s.Id, s => s.Tags.ToList());
|
||||
}
|
||||
}
|
||||
}
|
||||
112
src/NzbDrone.Core/TV/TVShowService.cs
Normal file
112
src/NzbDrone.Core/TV/TVShowService.cs
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.TV.Events;
|
||||
|
||||
namespace NzbDrone.Core.TV
|
||||
{
|
||||
public interface ITVShowService
|
||||
{
|
||||
TVShow GetTVShow(int tvShowId);
|
||||
List<TVShow> GetTVShows(IEnumerable<int> tvShowIds);
|
||||
TVShow AddTVShow(TVShow newTVShow);
|
||||
List<TVShow> AddTVShows(List<TVShow> newTVShows);
|
||||
TVShow FindByTvdbId(int tvdbId);
|
||||
TVShow FindByImdbId(string imdbId);
|
||||
TVShow FindByAniDbId(int aniDbId);
|
||||
TVShow FindByTitle(string title);
|
||||
TVShow FindByPath(string path);
|
||||
List<TVShow> GetMonitored();
|
||||
Dictionary<int, string> AllTVShowPaths();
|
||||
void DeleteTVShow(int tvShowId, bool deleteFiles);
|
||||
void DeleteTVShows(List<int> tvShowIds, bool deleteFiles);
|
||||
List<TVShow> GetAllTVShows();
|
||||
Dictionary<int, List<int>> AllTVShowTags();
|
||||
TVShow UpdateTVShow(TVShow tvShow);
|
||||
List<TVShow> UpdateTVShows(List<TVShow> tvShows);
|
||||
bool TVShowPathExists(string folder);
|
||||
}
|
||||
|
||||
public class TVShowService : ITVShowService
|
||||
{
|
||||
private readonly ITVShowRepository _tvShowRepository;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public TVShowService(ITVShowRepository tvShowRepository,
|
||||
IEventAggregator eventAggregator,
|
||||
Logger logger)
|
||||
{
|
||||
_tvShowRepository = tvShowRepository;
|
||||
_eventAggregator = eventAggregator;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public TVShow GetTVShow(int tvShowId) => _tvShowRepository.Get(tvShowId);
|
||||
public List<TVShow> GetTVShows(IEnumerable<int> tvShowIds) => _tvShowRepository.Get(tvShowIds).ToList();
|
||||
|
||||
public TVShow AddTVShow(TVShow newTVShow)
|
||||
{
|
||||
var tvShow = _tvShowRepository.Insert(newTVShow);
|
||||
_eventAggregator.PublishEvent(new TVShowAddedEvent(tvShow));
|
||||
return tvShow;
|
||||
}
|
||||
|
||||
public List<TVShow> AddTVShows(List<TVShow> newTVShows)
|
||||
{
|
||||
_tvShowRepository.InsertMany(newTVShows);
|
||||
|
||||
foreach (var tvShow in newTVShows)
|
||||
{
|
||||
_eventAggregator.PublishEvent(new TVShowAddedEvent(tvShow));
|
||||
}
|
||||
|
||||
return newTVShows;
|
||||
}
|
||||
|
||||
public TVShow FindByTvdbId(int tvdbId) => _tvShowRepository.FindByTvdbId(tvdbId);
|
||||
public TVShow FindByImdbId(string imdbId) => _tvShowRepository.FindByImdbId(imdbId);
|
||||
public TVShow FindByAniDbId(int aniDbId) => _tvShowRepository.FindByAniDbId(aniDbId);
|
||||
public TVShow FindByTitle(string title) => _tvShowRepository.FindByTitle(title);
|
||||
public TVShow FindByPath(string path) => _tvShowRepository.FindByPath(path);
|
||||
public List<TVShow> GetMonitored() => _tvShowRepository.GetMonitored();
|
||||
public Dictionary<int, string> AllTVShowPaths() => _tvShowRepository.AllTVShowPaths();
|
||||
public Dictionary<int, List<int>> AllTVShowTags() => _tvShowRepository.AllTVShowTags();
|
||||
public bool TVShowPathExists(string folder) => _tvShowRepository.TVShowPathExists(folder);
|
||||
public List<TVShow> GetAllTVShows() => _tvShowRepository.All().ToList();
|
||||
|
||||
public void DeleteTVShow(int tvShowId, bool deleteFiles)
|
||||
{
|
||||
var tvShow = _tvShowRepository.Get(tvShowId);
|
||||
_tvShowRepository.Delete(tvShowId);
|
||||
_eventAggregator.PublishEvent(new TVShowDeletedEvent(tvShow, deleteFiles));
|
||||
}
|
||||
|
||||
public void DeleteTVShows(List<int> tvShowIds, bool deleteFiles)
|
||||
{
|
||||
var tvShows = _tvShowRepository.Get(tvShowIds).ToList();
|
||||
_tvShowRepository.DeleteMany(tvShowIds);
|
||||
|
||||
foreach (var tvShow in tvShows)
|
||||
{
|
||||
_eventAggregator.PublishEvent(new TVShowDeletedEvent(tvShow, deleteFiles));
|
||||
}
|
||||
}
|
||||
|
||||
public TVShow UpdateTVShow(TVShow tvShow)
|
||||
{
|
||||
var storedTVShow = _tvShowRepository.Get(tvShow.Id);
|
||||
_tvShowRepository.Update(tvShow);
|
||||
_eventAggregator.PublishEvent(new TVShowEditedEvent(tvShow, storedTVShow));
|
||||
return tvShow;
|
||||
}
|
||||
|
||||
public List<TVShow> UpdateTVShows(List<TVShow> tvShows)
|
||||
{
|
||||
_tvShowRepository.UpdateMany(tvShows);
|
||||
_eventAggregator.PublishEvent(new TVShowsBulkEditedEvent(tvShows));
|
||||
return tvShows;
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/NzbDrone.Core/TV/TVShowStatus.cs
Normal file
10
src/NzbDrone.Core/TV/TVShowStatus.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
namespace NzbDrone.Core.TV
|
||||
{
|
||||
public enum TVShowStatus
|
||||
{
|
||||
Continuing = 0,
|
||||
Ended = 1,
|
||||
Upcoming = 2,
|
||||
Canceled = 3
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.Core.BookSeries;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.SignalR;
|
||||
using Radarr.Http;
|
||||
using Radarr.Http.REST;
|
||||
|
|
|
|||
Loading…
Reference in a new issue