using Dapper; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Repositories; using Microsoft.EntityFrameworkCore; namespace ErsatzTV.Infrastructure.Data.Repositories; public class PlexCollectionRepository : IPlexCollectionRepository { private readonly IDbContextFactory _dbContextFactory; public PlexCollectionRepository(IDbContextFactory dbContextFactory) => _dbContextFactory = dbContextFactory; public async Task> GetCollections() { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); return await dbContext.PlexCollections.ToListAsync(); } public async Task AddCollection(PlexCollection collection) { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); await dbContext.AddAsync(collection); return await dbContext.SaveChangesAsync() > 0; } public async Task RemoveCollection(PlexCollection collection) { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); dbContext.Remove(collection); // remove all tags that reference this collection await dbContext.Connection.ExecuteAsync( @"DELETE FROM Tag WHERE Name = @Name AND ExternalCollectionId = @Key", new { collection.Name, collection.Key }); return await dbContext.SaveChangesAsync() > 0; } public async Task> RemoveAllTags(PlexCollection collection) { var result = new List(); await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); // movies result.AddRange( await dbContext.Connection.QueryAsync( @"SELECT JM.Id FROM Tag T INNER JOIN MovieMetadata MM on T.MovieMetadataId = MM.Id INNER JOIN PlexMovie JM on JM.Id = MM.MovieId WHERE T.ExternalCollectionId = @Key", new { collection.Key })); // shows result.AddRange( await dbContext.Connection.QueryAsync( @"SELECT JS.Id FROM Tag T INNER JOIN ShowMetadata SM on T.ShowMetadataId = SM.Id INNER JOIN PlexShow JS on JS.Id = SM.ShowId WHERE T.ExternalCollectionId = @Key", new { collection.Key })); // seasons result.AddRange( await dbContext.Connection.QueryAsync( @"SELECT JS.Id FROM Tag T INNER JOIN SeasonMetadata SM on T.SeasonMetadataId = SM.Id INNER JOIN PlexSeason JS on JS.Id = SM.SeasonId WHERE T.ExternalCollectionId = @Key", new { collection.Key })); // episodes result.AddRange( await dbContext.Connection.QueryAsync( @"SELECT JE.Id FROM Tag T INNER JOIN EpisodeMetadata EM on T.EpisodeMetadataId = EM.Id INNER JOIN PlexEpisode JE on JE.Id = EM.EpisodeId WHERE T.ExternalCollectionId = @Key", new { collection.Key })); // delete all tags await dbContext.Connection.ExecuteAsync( @"DELETE FROM Tag WHERE Name = @Name AND ExternalCollectionId = @Key", new { collection.Name, collection.Key }); return result; } public async Task AddTag(MediaItem item, PlexCollection collection) { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); switch (item) { case PlexMovie movie: int movieId = await dbContext.Connection.ExecuteScalarAsync( @"SELECT Id FROM PlexMovie WHERE `Key` = @Key", new { movie.Key }); await dbContext.Connection.ExecuteAsync( @"INSERT INTO Tag (Name, ExternalCollectionId, MovieMetadataId) SELECT @Name, @Key, Id FROM (SELECT Id FROM MovieMetadata WHERE MovieId = @MovieId) AS A", new { collection.Name, collection.Key, MovieId = movieId }); return movieId; case PlexShow show: int showId = await dbContext.Connection.ExecuteScalarAsync( @"SELECT Id FROM PlexShow WHERE `Key` = @Key", new { show.Key }); await dbContext.Connection.ExecuteAsync( @"INSERT INTO Tag (Name, ExternalCollectionId, ShowMetadataId) SELECT @Name, @Key, Id FROM (SELECT Id FROM ShowMetadata WHERE ShowId = @ShowId) AS A", new { collection.Name, collection.Key, ShowId = showId }); return showId; case PlexSeason season: int seasonId = await dbContext.Connection.ExecuteScalarAsync( @"SELECT Id FROM PlexSeason WHERE `Key` = @Key", new { season.Key }); await dbContext.Connection.ExecuteAsync( @"INSERT INTO Tag (Name, ExternalCollectionId, SeasonMetadataId) SELECT @Name, @Key, Id FROM (SELECT Id FROM SeasonMetadata WHERE SeasonId = @SeasonId) AS A", new { collection.Name, collection.Key, SeasonId = seasonId }); return seasonId; case PlexEpisode episode: int episodeId = await dbContext.Connection.ExecuteScalarAsync( @"SELECT Id FROM PlexEpisode WHERE `Key` = @Key", new { episode.Key }); await dbContext.Connection.ExecuteAsync( @"INSERT INTO Tag (Name, ExternalCollectionId, EpisodeMetadataId) SELECT @Name, @Key, Id FROM (SELECT Id FROM EpisodeMetadata WHERE EpisodeId = @EpisodeId) AS A", new { collection.Name, collection.Key, EpisodeId = episodeId }); return episodeId; default: return 0; } } public async Task SetEtag(PlexCollection collection) { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); return await dbContext.Connection.ExecuteAsync( @"UPDATE PlexCollection SET Etag = @Etag WHERE `Key` = @Key", new { collection.Etag, collection.Key }) > 0; } }