Browse Source

use artwork for channel logo

pull/31/head
Jason Dove 6 years ago
parent
commit
25422747d5
  1. 34
      ErsatzTV.Application/Channels/Commands/UpdateChannelHandler.cs
  2. 16
      ErsatzTV.Application/Channels/Mapper.cs
  3. 3
      ErsatzTV.Application/Images/Commands/SaveArtworkToDisk.cs
  4. 19
      ErsatzTV.Application/Images/Commands/SaveArtworkToDiskHandler.cs
  5. 20
      ErsatzTV.Application/Images/Commands/SaveImageToDiskHandler.cs
  6. 1
      ErsatzTV.Application/Images/Queries/GetImageContentsHandler.cs
  7. 3
      ErsatzTV.Core.Tests/Metadata/MovieFolderScannerTests.cs
  8. 5
      ErsatzTV.Core/Domain/Channel.cs
  9. 1
      ErsatzTV.Core/FileSystemLayout.cs
  10. 3
      ErsatzTV.Core/Interfaces/Images/IImageCache.cs
  11. 13
      ErsatzTV.Core/Iptv/ChannelGuide.cs
  12. 10
      ErsatzTV.Core/Iptv/ChannelPlaylist.cs
  13. 4
      ErsatzTV.Infrastructure/Data/Configurations/ChannelConfiguration.cs
  14. 6
      ErsatzTV.Infrastructure/Data/Repositories/ChannelRepository.cs
  15. 43
      ErsatzTV.Infrastructure/Images/ImageCache.cs
  16. 1474
      ErsatzTV.Infrastructure/Migrations/20210228155457_Add_ChannelArtwork.Designer.cs
  17. 44
      ErsatzTV.Infrastructure/Migrations/20210228155457_Add_ChannelArtwork.cs
  18. 1474
      ErsatzTV.Infrastructure/Migrations/20210228155627_Update_ChannelArtwork.Designer.cs
  19. 23
      ErsatzTV.Infrastructure/Migrations/20210228155627_Update_ChannelArtwork.cs
  20. 1471
      ErsatzTV.Infrastructure/Migrations/20210228163013_Remove_ChannelLogo.Designer.cs
  21. 19
      ErsatzTV.Infrastructure/Migrations/20210228163013_Remove_ChannelLogo.cs
  22. 385
      ErsatzTV.Infrastructure/Migrations/TvContextModelSnapshot.cs
  23. 2
      ErsatzTV/Controllers/IptvController.cs
  24. 10
      ErsatzTV/Pages/ChannelEditor.razor
  25. 2
      ErsatzTV/Pages/Channels.razor

34
ErsatzTV.Application/Channels/Commands/UpdateChannelHandler.cs

@ -1,4 +1,7 @@ @@ -1,4 +1,7 @@
using System.Threading;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ErsatzTV.Core;
using ErsatzTV.Core.Domain;
@ -6,6 +9,7 @@ using ErsatzTV.Core.Interfaces.Repositories; @@ -6,6 +9,7 @@ using ErsatzTV.Core.Interfaces.Repositories;
using LanguageExt;
using MediatR;
using static ErsatzTV.Application.Channels.Mapper;
using static LanguageExt.Prelude;
namespace ErsatzTV.Application.Channels.Commands
{
@ -27,7 +31,33 @@ namespace ErsatzTV.Application.Channels.Commands @@ -27,7 +31,33 @@ namespace ErsatzTV.Application.Channels.Commands
c.Name = update.Name;
c.Number = update.Number;
c.FFmpegProfileId = update.FFmpegProfileId;
c.Logo = update.Logo;
if (!string.IsNullOrWhiteSpace(update.Logo))
{
c.Artwork ??= new List<Artwork>();
Option<Artwork> maybeLogo =
Optional(c.Artwork).Flatten().FirstOrDefault(a => a.ArtworkKind == ArtworkKind.Logo);
maybeLogo.Match(
artwork =>
{
artwork.Path = update.Logo;
artwork.DateUpdated = DateTime.UtcNow;
},
() =>
{
var artwork = new Artwork
{
Path = update.Logo,
DateAdded = DateTime.UtcNow,
DateUpdated = DateTime.UtcNow,
ArtworkKind = ArtworkKind.Logo
};
c.Artwork.Add(artwork);
});
}
c.StreamingMode = update.StreamingMode;
await _channelRepository.Update(c);
return ProjectToViewModel(c);

16
ErsatzTV.Application/Channels/Mapper.cs

@ -1,10 +1,22 @@ @@ -1,10 +1,22 @@
using ErsatzTV.Core.Domain;
using System.Linq;
using ErsatzTV.Core.Domain;
using static LanguageExt.Prelude;
namespace ErsatzTV.Application.Channels
{
internal static class Mapper
{
internal static ChannelViewModel ProjectToViewModel(Channel channel) =>
new(channel.Id, channel.Number, channel.Name, channel.FFmpegProfileId, channel.Logo, channel.StreamingMode);
new(
channel.Id,
channel.Number,
channel.Name,
channel.FFmpegProfileId,
GetLogo(channel),
channel.StreamingMode);
private static string GetLogo(Channel channel) =>
Optional(channel.Artwork.FirstOrDefault(a => a.ArtworkKind == ArtworkKind.Logo))
.Match(a => a.Path, string.Empty);
}
}

3
ErsatzTV.Application/Images/Commands/SaveImageToDisk.cs → ErsatzTV.Application/Images/Commands/SaveArtworkToDisk.cs

@ -1,9 +1,10 @@ @@ -1,9 +1,10 @@
using ErsatzTV.Core;
using ErsatzTV.Core.Domain;
using LanguageExt;
using MediatR;
namespace ErsatzTV.Application.Images.Commands
{
// ReSharper disable once SuggestBaseTypeForParameter
public record SaveImageToDisk(byte[] Buffer) : IRequest<Either<BaseError, string>>;
public record SaveArtworkToDisk(byte[] Buffer, ArtworkKind ArtworkKind) : IRequest<Either<BaseError, string>>;
}

19
ErsatzTV.Application/Images/Commands/SaveArtworkToDiskHandler.cs

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
using System.Threading;
using System.Threading.Tasks;
using ErsatzTV.Core;
using ErsatzTV.Core.Interfaces.Images;
using LanguageExt;
using MediatR;
namespace ErsatzTV.Application.Images.Commands
{
public class SaveArtworkToDiskHandler : IRequestHandler<SaveArtworkToDisk, Either<BaseError, string>>
{
private readonly IImageCache _imageCache;
public SaveArtworkToDiskHandler(IImageCache imageCache) => _imageCache = imageCache;
public Task<Either<BaseError, string>> Handle(SaveArtworkToDisk request, CancellationToken cancellationToken) =>
_imageCache.SaveArtworkToCache(request.Buffer, request.ArtworkKind);
}
}

20
ErsatzTV.Application/Images/Commands/SaveImageToDiskHandler.cs

@ -1,20 +0,0 @@ @@ -1,20 +0,0 @@
using System.Threading;
using System.Threading.Tasks;
using ErsatzTV.Core;
using ErsatzTV.Core.Interfaces.Images;
using LanguageExt;
using MediatR;
namespace ErsatzTV.Application.Images.Commands
{
public class SaveImageToDiskHandler : IRequestHandler<SaveImageToDisk, Either<BaseError, string>>
{
private readonly IImageCache _imageCache;
public SaveImageToDiskHandler(IImageCache imageCache) => _imageCache = imageCache;
public Task<Either<BaseError, string>> Handle(
SaveImageToDisk request,
CancellationToken cancellationToken) => _imageCache.SaveImage(request.Buffer);
}
}

1
ErsatzTV.Application/Images/Queries/GetImageContentsHandler.cs

@ -41,6 +41,7 @@ namespace ErsatzTV.Application.Images.Queries @@ -41,6 +41,7 @@ namespace ErsatzTV.Application.Images.Queries
{
ArtworkKind.Poster => Path.Combine(FileSystemLayout.PosterCacheFolder, subfolder),
ArtworkKind.Thumbnail => Path.Combine(FileSystemLayout.ThumbnailCacheFolder, subfolder),
ArtworkKind.Logo => Path.Combine(FileSystemLayout.LogoCacheFolder, subfolder),
_ => FileSystemLayout.ImageCacheFolder
};

3
ErsatzTV.Core.Tests/Metadata/MovieFolderScannerTests.cs

@ -58,9 +58,6 @@ namespace ErsatzTV.Core.Tests.Metadata @@ -58,9 +58,6 @@ namespace ErsatzTV.Core.Tests.Metadata
});
_imageCache = new Mock<IImageCache>();
_imageCache.Setup(
x => x.ResizeAndSaveImage(FakeLocalFileSystem.TestBytes, It.IsAny<int?>(), It.IsAny<int?>()))
.Returns(Right<BaseError, string>("poster").AsTask());
}
private Mock<IMovieRepository> _movieRepository;

5
ErsatzTV.Core/Domain/Channel.cs

@ -6,17 +6,16 @@ namespace ErsatzTV.Core.Domain @@ -6,17 +6,16 @@ namespace ErsatzTV.Core.Domain
public class Channel
{
public Channel(Guid uniqueId) => UniqueId = uniqueId;
public int Id { get; set; }
public Guid UniqueId { get; init; }
public int Number { get; set; }
public string Name { get; set; }
public string Logo { get; set; }
public int FFmpegProfileId { get; set; }
public FFmpegProfile FFmpegProfile { get; set; }
public StreamingMode StreamingMode { get; set; }
public List<Playout> Playouts { get; set; }
public List<Artwork> Artwork { get; set; }
// public SourceMode Mode { get; set; }
}
}

1
ErsatzTV.Core/FileSystemLayout.cs

@ -23,5 +23,6 @@ namespace ErsatzTV.Core @@ -23,5 +23,6 @@ namespace ErsatzTV.Core
public static readonly string PosterCacheFolder = Path.Combine(ArtworkCacheFolder, "posters");
public static readonly string ThumbnailCacheFolder = Path.Combine(ArtworkCacheFolder, "thumbnails");
public static readonly string LogoCacheFolder = Path.Combine(ArtworkCacheFolder, "logos");
}
}

3
ErsatzTV.Core/Interfaces/Images/IImageCache.cs

@ -7,8 +7,7 @@ namespace ErsatzTV.Core.Interfaces.Images @@ -7,8 +7,7 @@ namespace ErsatzTV.Core.Interfaces.Images
public interface IImageCache
{
Task<Either<BaseError, byte[]>> ResizeImage(byte[] imageBuffer, int height);
Task<Either<BaseError, string>> ResizeAndSaveImage(byte[] imageBuffer, int? height, int? width);
Task<Either<BaseError, string>> SaveImage(byte[] imageBuffer);
Task<Either<BaseError, string>> SaveArtworkToCache(byte[] imageBuffer, ArtworkKind artworkKind);
string CopyArtworkToCache(string path, ArtworkKind artworkKind);
}
}

13
ErsatzTV.Core/Iptv/ChannelGuide.cs

@ -4,6 +4,7 @@ using System.Linq; @@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using System.Xml;
using ErsatzTV.Core.Domain;
using LanguageExt;
using static LanguageExt.Prelude;
namespace ErsatzTV.Core.Iptv
@ -41,11 +42,13 @@ namespace ErsatzTV.Core.Iptv @@ -41,11 +42,13 @@ namespace ErsatzTV.Core.Iptv
xml.WriteEndElement(); // display-name
xml.WriteStartElement("icon");
xml.WriteAttributeString(
"src",
!string.IsNullOrWhiteSpace(channel.Logo)
? $"{_scheme}://{_host}/iptv/images/{channel.Logo}"
: $"{_scheme}://{_host}/images/ersatztv-500.png");
string logo = Optional(channel.Artwork).Flatten()
.Filter(a => a.ArtworkKind == ArtworkKind.Logo)
.HeadOrNone()
.Match(
artwork => $"{_scheme}://{_host}/iptv/logos/{artwork.Path}",
() => $"{_scheme}://{_host}/images/ersatztv-500.png");
xml.WriteAttributeString("src", logo);
xml.WriteEndElement(); // icon
xml.WriteEndElement(); // channel

10
ErsatzTV.Core/Iptv/ChannelPlaylist.cs

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Text;
using ErsatzTV.Core.Domain;
using static LanguageExt.Prelude;
namespace ErsatzTV.Core.Iptv
{
@ -26,9 +27,12 @@ namespace ErsatzTV.Core.Iptv @@ -26,9 +27,12 @@ namespace ErsatzTV.Core.Iptv
sb.AppendLine($"#EXTM3U url-tvg=\"{xmltv}\" x-tvg-url=\"{xmltv}\"");
foreach (Channel channel in _channels)
{
string logo = !string.IsNullOrWhiteSpace(channel.Logo)
? $"{_scheme}://{_host}/iptv/images/{channel.Logo}"
: $"{_scheme}://{_host}/images/ersatztv-500.png";
string logo = Optional(channel.Artwork).Flatten()
.Filter(a => a.ArtworkKind == ArtworkKind.Logo)
.HeadOrNone()
.Match(
artwork => $"{_scheme}://{_host}/iptv/logos/{artwork.Path}",
() => $"{_scheme}://{_host}/images/ersatztv-500.png");
string shortUniqueId = Convert.ToBase64String(channel.UniqueId.ToByteArray())
.TrimEnd('=')

4
ErsatzTV.Infrastructure/Data/Configurations/ChannelConfiguration.cs

@ -17,6 +17,10 @@ namespace ErsatzTV.Infrastructure.Data.Configurations @@ -17,6 +17,10 @@ namespace ErsatzTV.Infrastructure.Data.Configurations
.WithOne(p => p.Channel)
.HasForeignKey(p => p.ChannelId)
.OnDelete(DeleteBehavior.Cascade);
builder.HasMany(c => c.Artwork)
.WithOne()
.OnDelete(DeleteBehavior.Cascade);
}
}
}

6
ErsatzTV.Infrastructure/Data/Repositories/ChannelRepository.cs

@ -24,6 +24,7 @@ namespace ErsatzTV.Infrastructure.Data.Repositories @@ -24,6 +24,7 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
public Task<Option<Channel>> Get(int id) =>
_dbContext.Channels
.Include(c => c.Artwork)
.OrderBy(c => c.Id)
.SingleOrDefaultAsync(c => c.Id == id)
.Map(Optional);
@ -36,7 +37,10 @@ namespace ErsatzTV.Infrastructure.Data.Repositories @@ -36,7 +37,10 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
.SingleOrDefaultAsync(c => c.Number == number)
.Map(Optional);
public Task<List<Channel>> GetAll() => _dbContext.Channels.ToListAsync();
public Task<List<Channel>> GetAll() =>
_dbContext.Channels
.Include(c => c.Artwork)
.ToListAsync();
public Task<List<Channel>> GetAllForGuide() =>
_dbContext.Channels

43
ErsatzTV.Infrastructure/Images/ImageCache.cs

@ -44,42 +44,28 @@ namespace ErsatzTV.Infrastructure.Images @@ -44,42 +44,28 @@ namespace ErsatzTV.Infrastructure.Images
return outStream.ToArray();
}
public async Task<Either<BaseError, string>> ResizeAndSaveImage(byte[] imageBuffer, int? height, int? width)
{
await using var inStream = new MemoryStream(imageBuffer);
using var image = await Image.LoadAsync(inStream);
Size size = height.HasValue ? new Size { Height = height.Value } : new Size { Width = width.Value };
image.Mutate(
i => i.Resize(
new ResizeOptions
{
Mode = ResizeMode.Max,
Size = size
}));
await using var outStream = new MemoryStream();
await image.SaveAsync(outStream, new JpegEncoder { Quality = 90 });
return await SaveImage(outStream.ToArray());
}
public async Task<Either<BaseError, string>> SaveImage(byte[] imageBuffer)
public async Task<Either<BaseError, string>> SaveArtworkToCache(byte[] imageBuffer, ArtworkKind artworkKind)
{
try
{
byte[] hash = Crypto.ComputeHash(imageBuffer);
string hex = BitConverter.ToString(hash).Replace("-", string.Empty);
string fileName = Path.Combine(FileSystemLayout.ImageCacheFolder, hex);
if (!Directory.Exists(FileSystemLayout.ImageCacheFolder))
string subfolder = hex.Substring(0, 2);
string baseFolder = artworkKind switch
{
ArtworkKind.Poster => Path.Combine(FileSystemLayout.PosterCacheFolder, subfolder),
ArtworkKind.Thumbnail => Path.Combine(FileSystemLayout.ThumbnailCacheFolder, subfolder),
ArtworkKind.Logo => Path.Combine(FileSystemLayout.LogoCacheFolder, subfolder),
_ => FileSystemLayout.ImageCacheFolder
};
string target = Path.Combine(baseFolder, hex);
if (!Directory.Exists(baseFolder))
{
Directory.CreateDirectory(FileSystemLayout.ImageCacheFolder);
Directory.CreateDirectory(baseFolder);
}
await File.WriteAllBytesAsync(fileName, imageBuffer);
await File.WriteAllBytesAsync(target, imageBuffer);
return hex;
}
catch (Exception ex)
@ -98,6 +84,7 @@ namespace ErsatzTV.Infrastructure.Images @@ -98,6 +84,7 @@ namespace ErsatzTV.Infrastructure.Images
{
ArtworkKind.Poster => Path.Combine(FileSystemLayout.PosterCacheFolder, subfolder),
ArtworkKind.Thumbnail => Path.Combine(FileSystemLayout.ThumbnailCacheFolder, subfolder),
ArtworkKind.Logo => Path.Combine(FileSystemLayout.LogoCacheFolder, subfolder),
_ => FileSystemLayout.ImageCacheFolder
};
string target = Path.Combine(baseFolder, hex);

1474
ErsatzTV.Infrastructure/Migrations/20210228155457_Add_ChannelArtwork.Designer.cs generated

File diff suppressed because it is too large Load Diff

44
ErsatzTV.Infrastructure/Migrations/20210228155457_Add_ChannelArtwork.cs

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace ErsatzTV.Infrastructure.Migrations
{
public partial class Add_ChannelArtwork : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
"ChannelId",
"Artwork",
"INTEGER",
nullable: true);
migrationBuilder.CreateIndex(
"IX_Artwork_ChannelId",
"Artwork",
"ChannelId");
migrationBuilder.AddForeignKey(
"FK_Artwork_Channel_ChannelId",
"Artwork",
"ChannelId",
"Channel",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
"FK_Artwork_Channel_ChannelId",
"Artwork");
migrationBuilder.DropIndex(
"IX_Artwork_ChannelId",
"Artwork");
migrationBuilder.DropColumn(
"ChannelId",
"Artwork");
}
}
}

1474
ErsatzTV.Infrastructure/Migrations/20210228155627_Update_ChannelArtwork.Designer.cs generated

File diff suppressed because it is too large Load Diff

23
ErsatzTV.Infrastructure/Migrations/20210228155627_Update_ChannelArtwork.cs

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace ErsatzTV.Infrastructure.Migrations
{
public partial class Update_ChannelArtwork : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
var now = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.FFFFFFF");
migrationBuilder.Sql(
$@"INSERT INTO Artwork (ArtworkKind, ChannelId, DateAdded, DateUpdated, Path)
SELECT 2, c.Id, '{now}', '{now}', c.Logo
FROM Channel c
WHERE c.Logo is not null");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

1471
ErsatzTV.Infrastructure/Migrations/20210228163013_Remove_ChannelLogo.Designer.cs generated

File diff suppressed because it is too large Load Diff

19
ErsatzTV.Infrastructure/Migrations/20210228163013_Remove_ChannelLogo.cs

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace ErsatzTV.Infrastructure.Migrations
{
public partial class Remove_ChannelLogo : Migration
{
protected override void Up(MigrationBuilder migrationBuilder) =>
migrationBuilder.DropColumn(
"Logo",
"Channel");
protected override void Down(MigrationBuilder migrationBuilder) =>
migrationBuilder.AddColumn<string>(
"Logo",
"Channel",
"TEXT",
nullable: true);
}
}

385
ErsatzTV.Infrastructure/Migrations/TvContextModelSnapshot.cs

@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
// <auto-generated />
using System;
using ErsatzTV.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace ErsatzTV.Infrastructure.Migrations
{
[DbContext(typeof(TvContext))]
internal class TvContextModelSnapshot : ModelSnapshot
partial class TvContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
@ -16,9 +16,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -16,9 +16,7 @@ namespace ErsatzTV.Infrastructure.Migrations
modelBuilder
.HasAnnotation("ProductVersion", "5.0.3");
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Artwork",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Artwork", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -27,6 +25,9 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -27,6 +25,9 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Property<int>("ArtworkKind")
.HasColumnType("INTEGER");
b.Property<int?>("ChannelId")
.HasColumnType("INTEGER");
b.Property<DateTime>("DateAdded")
.HasColumnType("TEXT");
@ -50,6 +51,8 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -50,6 +51,8 @@ namespace ErsatzTV.Infrastructure.Migrations
b.HasKey("Id");
b.HasIndex("ChannelId");
b.HasIndex("EpisodeMetadataId");
b.HasIndex("MovieMetadataId");
@ -61,9 +64,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -61,9 +64,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("Artwork");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Channel",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Channel", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -72,9 +73,6 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -72,9 +73,6 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Property<int>("FFmpegProfileId")
.HasColumnType("INTEGER");
b.Property<string>("Logo")
.HasColumnType("TEXT");
b.Property<string>("Name")
.HasColumnType("TEXT");
@ -97,9 +95,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -97,9 +95,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("Channel");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Collection",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Collection", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -113,9 +109,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -113,9 +109,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("Collection");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.CollectionItem",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.CollectionItem", b =>
{
b.Property<int>("CollectionId")
.HasColumnType("INTEGER");
@ -130,9 +124,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -130,9 +124,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("CollectionItem");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.ConfigElement",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.ConfigElement", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -152,9 +144,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -152,9 +144,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("ConfigElement");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.EpisodeMetadata",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.EpisodeMetadata", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -203,9 +193,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -203,9 +193,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("EpisodeMetadata");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.FFmpegProfile",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.FFmpegProfile", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -269,9 +257,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -269,9 +257,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("FFmpegProfile");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Library",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Library", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -296,9 +282,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -296,9 +282,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("Library");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.LibraryPath",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryPath", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -317,9 +301,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -317,9 +301,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("LibraryPath");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.MediaFile",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.MediaFile", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -341,9 +323,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -341,9 +323,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("MediaFile");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.MediaItem",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.MediaItem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -359,9 +339,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -359,9 +339,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("MediaItem");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.MediaSource",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.MediaSource", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -372,9 +350,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -372,9 +350,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("MediaSource");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.MediaVersion",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.MediaVersion", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -428,9 +404,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -428,9 +404,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("MediaVersion");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.MovieMetadata",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.MovieMetadata", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -479,9 +453,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -479,9 +453,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("MovieMetadata");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Playout",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Playout", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -505,9 +477,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -505,9 +477,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("Playout");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.PlayoutItem",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutItem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -534,9 +504,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -534,9 +504,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("PlayoutItem");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.PlayoutProgramScheduleAnchor",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutProgramScheduleAnchor", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -570,9 +538,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -570,9 +538,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("PlayoutProgramScheduleAnchor");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.PlexConnection",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.PlexConnection", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -594,9 +560,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -594,9 +560,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("PlexConnection");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.PlexMediaItemPart",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMediaItemPart", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -622,9 +586,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -622,9 +586,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("PlexMediaItemPart");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.ProgramSchedule",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramSchedule", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -644,9 +606,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -644,9 +606,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("ProgramSchedule");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.ProgramScheduleItem",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -681,9 +641,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -681,9 +641,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("ProgramScheduleItem");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Resolution",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Resolution", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -703,9 +661,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -703,9 +661,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("Resolution");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.SeasonMetadata",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.SeasonMetadata", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -748,9 +704,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -748,9 +704,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("SeasonMetadata");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.ShowMetadata",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.ShowMetadata", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
@ -799,18 +753,14 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -799,18 +753,14 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("ShowMetadata");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.LocalLibrary",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.LocalLibrary", b =>
{
b.HasBaseType("ErsatzTV.Core.Domain.Library");
b.ToTable("LocalLibrary");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.PlexLibrary",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.PlexLibrary", b =>
{
b.HasBaseType("ErsatzTV.Core.Domain.Library");
@ -823,9 +773,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -823,9 +773,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("PlexLibrary");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Episode",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Episode", b =>
{
b.HasBaseType("ErsatzTV.Core.Domain.MediaItem");
@ -840,18 +788,14 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -840,18 +788,14 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("Episode");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Movie",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Movie", b =>
{
b.HasBaseType("ErsatzTV.Core.Domain.MediaItem");
b.ToTable("Movie");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Season",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Season", b =>
{
b.HasBaseType("ErsatzTV.Core.Domain.MediaItem");
@ -866,27 +810,21 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -866,27 +810,21 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("Season");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Show",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Show", b =>
{
b.HasBaseType("ErsatzTV.Core.Domain.MediaItem");
b.ToTable("Show");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.LocalMediaSource",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.LocalMediaSource", b =>
{
b.HasBaseType("ErsatzTV.Core.Domain.MediaSource");
b.ToTable("LocalMediaSource");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.PlexMediaSource",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMediaSource", b =>
{
b.HasBaseType("ErsatzTV.Core.Domain.MediaSource");
@ -902,9 +840,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -902,9 +840,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("PlexMediaSource");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.ProgramScheduleItemDuration",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemDuration", b =>
{
b.HasBaseType("ErsatzTV.Core.Domain.ProgramScheduleItem");
@ -917,18 +853,14 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -917,18 +853,14 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("ProgramScheduleDurationItem");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.ProgramScheduleItemFlood",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemFlood", b =>
{
b.HasBaseType("ErsatzTV.Core.Domain.ProgramScheduleItem");
b.ToTable("ProgramScheduleFloodItem");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.ProgramScheduleItemMultiple",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemMultiple", b =>
{
b.HasBaseType("ErsatzTV.Core.Domain.ProgramScheduleItem");
@ -938,18 +870,14 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -938,18 +870,14 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("ProgramScheduleMultipleItem");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.ProgramScheduleItemOne",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemOne", b =>
{
b.HasBaseType("ErsatzTV.Core.Domain.ProgramScheduleItem");
b.ToTable("ProgramScheduleOneItem");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.PlexMovie",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMovie", b =>
{
b.HasBaseType("ErsatzTV.Core.Domain.Movie");
@ -964,10 +892,13 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -964,10 +892,13 @@ namespace ErsatzTV.Infrastructure.Migrations
b.ToTable("PlexMovie");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Artwork",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Artwork", b =>
{
b.HasOne("ErsatzTV.Core.Domain.Channel", null)
.WithMany("Artwork")
.HasForeignKey("ChannelId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null)
.WithMany("Artwork")
.HasForeignKey("EpisodeMetadataId")
@ -989,9 +920,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -989,9 +920,7 @@ namespace ErsatzTV.Infrastructure.Migrations
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Channel",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Channel", b =>
{
b.HasOne("ErsatzTV.Core.Domain.FFmpegProfile", "FFmpegProfile")
.WithMany()
@ -1002,9 +931,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1002,9 +931,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Navigation("FFmpegProfile");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.CollectionItem",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.CollectionItem", b =>
{
b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection")
.WithMany("CollectionItems")
@ -1023,9 +950,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1023,9 +950,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Navigation("MediaItem");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.EpisodeMetadata",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.EpisodeMetadata", b =>
{
b.HasOne("ErsatzTV.Core.Domain.Episode", "Episode")
.WithMany("EpisodeMetadata")
@ -1036,9 +961,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1036,9 +961,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Navigation("Episode");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.FFmpegProfile",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.FFmpegProfile", b =>
{
b.HasOne("ErsatzTV.Core.Domain.Resolution", "Resolution")
.WithMany()
@ -1049,9 +972,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1049,9 +972,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Navigation("Resolution");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Library",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Library", b =>
{
b.HasOne("ErsatzTV.Core.Domain.MediaSource", "MediaSource")
.WithMany("Libraries")
@ -1062,9 +983,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1062,9 +983,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Navigation("MediaSource");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.LibraryPath",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryPath", b =>
{
b.HasOne("ErsatzTV.Core.Domain.Library", "Library")
.WithMany("Paths")
@ -1075,9 +994,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1075,9 +994,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Navigation("Library");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.MediaFile",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.MediaFile", b =>
{
b.HasOne("ErsatzTV.Core.Domain.MediaVersion", "MediaVersion")
.WithMany("MediaFiles")
@ -1088,9 +1005,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1088,9 +1005,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Navigation("MediaVersion");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.MediaItem",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.MediaItem", b =>
{
b.HasOne("ErsatzTV.Core.Domain.LibraryPath", "LibraryPath")
.WithMany("MediaItems")
@ -1101,9 +1016,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1101,9 +1016,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Navigation("LibraryPath");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.MediaVersion",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.MediaVersion", b =>
{
b.HasOne("ErsatzTV.Core.Domain.Episode", null)
.WithMany("MediaVersions")
@ -1116,9 +1029,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1116,9 +1029,7 @@ namespace ErsatzTV.Infrastructure.Migrations
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.MovieMetadata",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.MovieMetadata", b =>
{
b.HasOne("ErsatzTV.Core.Domain.Movie", "Movie")
.WithMany("MovieMetadata")
@ -1129,9 +1040,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1129,9 +1040,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Navigation("Movie");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Playout",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Playout", b =>
{
b.HasOne("ErsatzTV.Core.Domain.Channel", "Channel")
.WithMany("Playouts")
@ -1145,10 +1054,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1145,10 +1054,7 @@ namespace ErsatzTV.Infrastructure.Migrations
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.OwnsOne(
"ErsatzTV.Core.Domain.PlayoutAnchor",
"Anchor",
b1 =>
b.OwnsOne("ErsatzTV.Core.Domain.PlayoutAnchor", "Anchor", b1 =>
{
b1.Property<int>("PlayoutId")
.HasColumnType("INTEGER");
@ -1184,9 +1090,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1184,9 +1090,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Navigation("ProgramSchedule");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.PlayoutItem",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutItem", b =>
{
b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem")
.WithMany()
@ -1205,9 +1109,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1205,9 +1109,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Navigation("Playout");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.PlayoutProgramScheduleAnchor",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutProgramScheduleAnchor", b =>
{
b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection")
.WithMany()
@ -1231,10 +1133,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1231,10 +1133,7 @@ namespace ErsatzTV.Infrastructure.Migrations
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.OwnsOne(
"ErsatzTV.Core.Domain.CollectionEnumeratorState",
"EnumeratorState",
b1 =>
b.OwnsOne("ErsatzTV.Core.Domain.CollectionEnumeratorState", "EnumeratorState", b1 =>
{
b1.Property<int>("PlayoutProgramScheduleAnchorId")
.HasColumnType("INTEGER");
@ -1264,9 +1163,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1264,9 +1163,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Navigation("ProgramSchedule");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.PlexConnection",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.PlexConnection", b =>
{
b.HasOne("ErsatzTV.Core.Domain.PlexMediaSource", "PlexMediaSource")
.WithMany("Connections")
@ -1277,9 +1174,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1277,9 +1174,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Navigation("PlexMediaSource");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.ProgramScheduleItem",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItem", b =>
{
b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection")
.WithMany()
@ -1304,9 +1199,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1304,9 +1199,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Navigation("ProgramSchedule");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.SeasonMetadata",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.SeasonMetadata", b =>
{
b.HasOne("ErsatzTV.Core.Domain.Season", "Season")
.WithMany("SeasonMetadata")
@ -1317,9 +1210,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1317,9 +1210,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Navigation("Season");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.ShowMetadata",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.ShowMetadata", b =>
{
b.HasOne("ErsatzTV.Core.Domain.Show", "Show")
.WithMany("ShowMetadata")
@ -1330,9 +1221,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1330,9 +1221,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Navigation("Show");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.LocalLibrary",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.LocalLibrary", b =>
{
b.HasOne("ErsatzTV.Core.Domain.Library", null)
.WithOne()
@ -1341,9 +1230,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1341,9 +1230,7 @@ namespace ErsatzTV.Infrastructure.Migrations
.IsRequired();
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.PlexLibrary",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.PlexLibrary", b =>
{
b.HasOne("ErsatzTV.Core.Domain.Library", null)
.WithOne()
@ -1352,9 +1239,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1352,9 +1239,7 @@ namespace ErsatzTV.Infrastructure.Migrations
.IsRequired();
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Episode",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Episode", b =>
{
b.HasOne("ErsatzTV.Core.Domain.MediaItem", null)
.WithOne()
@ -1371,9 +1256,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1371,9 +1256,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Navigation("Season");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Movie",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Movie", b =>
{
b.HasOne("ErsatzTV.Core.Domain.MediaItem", null)
.WithOne()
@ -1382,9 +1265,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1382,9 +1265,7 @@ namespace ErsatzTV.Infrastructure.Migrations
.IsRequired();
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Season",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Season", b =>
{
b.HasOne("ErsatzTV.Core.Domain.MediaItem", null)
.WithOne()
@ -1401,9 +1282,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1401,9 +1282,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Navigation("Show");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Show",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Show", b =>
{
b.HasOne("ErsatzTV.Core.Domain.MediaItem", null)
.WithOne()
@ -1412,9 +1291,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1412,9 +1291,7 @@ namespace ErsatzTV.Infrastructure.Migrations
.IsRequired();
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.LocalMediaSource",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.LocalMediaSource", b =>
{
b.HasOne("ErsatzTV.Core.Domain.MediaSource", null)
.WithOne()
@ -1423,9 +1300,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1423,9 +1300,7 @@ namespace ErsatzTV.Infrastructure.Migrations
.IsRequired();
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.PlexMediaSource",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMediaSource", b =>
{
b.HasOne("ErsatzTV.Core.Domain.MediaSource", null)
.WithOne()
@ -1434,9 +1309,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1434,9 +1309,7 @@ namespace ErsatzTV.Infrastructure.Migrations
.IsRequired();
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.ProgramScheduleItemDuration",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemDuration", b =>
{
b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", null)
.WithOne()
@ -1445,9 +1318,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1445,9 +1318,7 @@ namespace ErsatzTV.Infrastructure.Migrations
.IsRequired();
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.ProgramScheduleItemFlood",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemFlood", b =>
{
b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", null)
.WithOne()
@ -1456,9 +1327,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1456,9 +1327,7 @@ namespace ErsatzTV.Infrastructure.Migrations
.IsRequired();
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.ProgramScheduleItemMultiple",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemMultiple", b =>
{
b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", null)
.WithOne()
@ -1467,9 +1336,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1467,9 +1336,7 @@ namespace ErsatzTV.Infrastructure.Migrations
.IsRequired();
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.ProgramScheduleItemOne",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemOne", b =>
{
b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", null)
.WithOne()
@ -1478,9 +1345,7 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1478,9 +1345,7 @@ namespace ErsatzTV.Infrastructure.Migrations
.IsRequired();
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.PlexMovie",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMovie", b =>
{
b.HasOne("ErsatzTV.Core.Domain.Movie", null)
.WithOne()
@ -1495,83 +1360,109 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -1495,83 +1360,109 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Navigation("Part");
});
modelBuilder.Entity("ErsatzTV.Core.Domain.Channel", b => { b.Navigation("Playouts"); });
modelBuilder.Entity("ErsatzTV.Core.Domain.Channel", b =>
{
b.Navigation("Artwork");
modelBuilder.Entity("ErsatzTV.Core.Domain.Collection", b => { b.Navigation("CollectionItems"); });
b.Navigation("Playouts");
});
modelBuilder.Entity("ErsatzTV.Core.Domain.EpisodeMetadata", b => { b.Navigation("Artwork"); });
modelBuilder.Entity("ErsatzTV.Core.Domain.Collection", b =>
{
b.Navigation("CollectionItems");
});
modelBuilder.Entity("ErsatzTV.Core.Domain.Library", b => { b.Navigation("Paths"); });
modelBuilder.Entity("ErsatzTV.Core.Domain.EpisodeMetadata", b =>
{
b.Navigation("Artwork");
});
modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryPath", b => { b.Navigation("MediaItems"); });
modelBuilder.Entity("ErsatzTV.Core.Domain.Library", b =>
{
b.Navigation("Paths");
});
modelBuilder.Entity("ErsatzTV.Core.Domain.MediaItem", b => { b.Navigation("CollectionItems"); });
modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryPath", b =>
{
b.Navigation("MediaItems");
});
modelBuilder.Entity("ErsatzTV.Core.Domain.MediaSource", b => { b.Navigation("Libraries"); });
modelBuilder.Entity("ErsatzTV.Core.Domain.MediaItem", b =>
{
b.Navigation("CollectionItems");
});
modelBuilder.Entity("ErsatzTV.Core.Domain.MediaVersion", b => { b.Navigation("MediaFiles"); });
modelBuilder.Entity("ErsatzTV.Core.Domain.MediaSource", b =>
{
b.Navigation("Libraries");
});
modelBuilder.Entity("ErsatzTV.Core.Domain.MediaVersion", b =>
{
b.Navigation("MediaFiles");
});
modelBuilder.Entity("ErsatzTV.Core.Domain.MovieMetadata", b => { b.Navigation("Artwork"); });
modelBuilder.Entity("ErsatzTV.Core.Domain.MovieMetadata", b =>
{
b.Navigation("Artwork");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Playout",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Playout", b =>
{
b.Navigation("Items");
b.Navigation("ProgramScheduleAnchors");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.ProgramSchedule",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramSchedule", b =>
{
b.Navigation("Items");
b.Navigation("Playouts");
});
modelBuilder.Entity("ErsatzTV.Core.Domain.SeasonMetadata", b => { b.Navigation("Artwork"); });
modelBuilder.Entity("ErsatzTV.Core.Domain.SeasonMetadata", b =>
{
b.Navigation("Artwork");
});
modelBuilder.Entity("ErsatzTV.Core.Domain.ShowMetadata", b => { b.Navigation("Artwork"); });
modelBuilder.Entity("ErsatzTV.Core.Domain.ShowMetadata", b =>
{
b.Navigation("Artwork");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Episode",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Episode", b =>
{
b.Navigation("EpisodeMetadata");
b.Navigation("MediaVersions");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Movie",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Movie", b =>
{
b.Navigation("MediaVersions");
b.Navigation("MovieMetadata");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Season",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Season", b =>
{
b.Navigation("Episodes");
b.Navigation("SeasonMetadata");
});
modelBuilder.Entity(
"ErsatzTV.Core.Domain.Show",
b =>
modelBuilder.Entity("ErsatzTV.Core.Domain.Show", b =>
{
b.Navigation("Seasons");
b.Navigation("ShowMetadata");
});
modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMediaSource", b => { b.Navigation("Connections"); });
modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMediaSource", b =>
{
b.Navigation("Connections");
});
#pragma warning restore 612, 618
}
}

2
ErsatzTV/Controllers/IptvController.cs

@ -61,7 +61,7 @@ namespace ErsatzTV.Controllers @@ -61,7 +61,7 @@ namespace ErsatzTV.Controllers
},
error => BadRequest(error.Value)));
[HttpGet("iptv/images/{fileName}")]
[HttpGet("iptv/logos/{fileName}")]
public async Task<IActionResult> GetImage(string fileName)
{
Either<BaseError, ImageViewModel> imageContents =

10
ErsatzTV/Pages/ChannelEditor.razor

@ -37,7 +37,7 @@ @@ -37,7 +37,7 @@
<InputFile id="fileInput" OnChange="UploadLogo" hidden/>
@if (!string.IsNullOrWhiteSpace(_model.Logo))
{
<MudElement HtmlTag="img" src="@($"iptv/images/{_model.Logo}")" Style="max-height: 50px"/>
<MudElement HtmlTag="img" src="@($"iptv/logos/{_model.Logo}")" Style="max-height: 50px"/>
}
</MudItem>
<MudItem xs="6">
@ -135,9 +135,13 @@ @@ -135,9 +135,13 @@
{
var buffer = new byte[e.File.Size];
await e.File.OpenReadStream().ReadAsync(buffer);
Either<BaseError, string> maybeCacheFileName = await Mediator.Send(new SaveImageToDisk(buffer));
Either<BaseError, string> maybeCacheFileName = await Mediator.Send(new SaveArtworkToDisk(buffer, ArtworkKind.Logo));
maybeCacheFileName.Match(
relativeFileName => _model.Logo = relativeFileName,
relativeFileName =>
{
_model.Logo = relativeFileName;
StateHasChanged();
},
error =>
{
Snackbar.Add($"Unexpected error saving channel logo: {error.Value}");

2
ErsatzTV/Pages/Channels.razor

@ -37,7 +37,7 @@ @@ -37,7 +37,7 @@
<MudTd DataLabel="Logo">
@if (!string.IsNullOrWhiteSpace(context.Logo))
{
<MudElement HtmlTag="img" src="@($"iptv/images/{context.Logo}")" Style="max-height: 50px"/>
<MudElement HtmlTag="img" src="@($"iptv/logos/{context.Logo}")" Style="max-height: 50px"/>
}
</MudTd>
<MudTd DataLabel="Name">@context.Name</MudTd>

Loading…
Cancel
Save