mirror of https://github.com/ErsatzTV/ErsatzTV.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
415 lines
15 KiB
415 lines
15 KiB
using System.Runtime.CompilerServices; |
|
using Dapper; |
|
using ErsatzTV.Core.Domain; |
|
using ErsatzTV.Core.Interfaces.Repositories; |
|
using ErsatzTV.Infrastructure.Extensions; |
|
using Microsoft.EntityFrameworkCore; |
|
|
|
namespace ErsatzTV.Infrastructure.Data.Repositories; |
|
|
|
public class SearchRepository(IDbContextFactory<TvContext> dbContextFactory) : ISearchRepository |
|
{ |
|
public async Task<Option<MediaItem>> GetItemToIndex(int id, CancellationToken cancellationToken) |
|
{ |
|
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken); |
|
|
|
var baseItem = await dbContext.MediaItems |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.SingleOrDefaultAsync(mi => mi.Id == id, cancellationToken); |
|
|
|
if (baseItem is null) |
|
{ |
|
return Option<MediaItem>.None; |
|
} |
|
|
|
switch (baseItem) |
|
{ |
|
case Movie: |
|
return await dbContext.Movies |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.IncludeForSearch() |
|
.AsSplitQuery() |
|
.SingleOrDefaultAsync(mi => mi.Id == id, cancellationToken); |
|
case Episode: |
|
return await dbContext.Episodes |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.IncludeForSearch() |
|
.AsSplitQuery() |
|
.SingleOrDefaultAsync(mi => mi.Id == id, cancellationToken); |
|
case Season: |
|
return await dbContext.Seasons |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.IncludeForSearch() |
|
.AsSplitQuery() |
|
.SingleOrDefaultAsync(mi => mi.Id == id, cancellationToken); |
|
case Show: |
|
return await dbContext.Shows |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.IncludeForSearch() |
|
.AsSplitQuery() |
|
.SingleOrDefaultAsync(mi => mi.Id == id, cancellationToken); |
|
case MusicVideo: |
|
return await dbContext.MusicVideos |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.IncludeForSearch() |
|
.AsSplitQuery() |
|
.SingleOrDefaultAsync(mi => mi.Id == id, cancellationToken); |
|
case Artist: |
|
return await dbContext.Artists |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.IncludeForSearch() |
|
.AsSplitQuery() |
|
.SingleOrDefaultAsync(mi => mi.Id == id, cancellationToken); |
|
case OtherVideo: |
|
return await dbContext.OtherVideos |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.IncludeForSearch() |
|
.AsSplitQuery() |
|
.SingleOrDefaultAsync(mi => mi.Id == id, cancellationToken); |
|
case Song: |
|
return await dbContext.Songs |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.IncludeForSearch() |
|
.AsSplitQuery() |
|
.SingleOrDefaultAsync(mi => mi.Id == id, cancellationToken); |
|
case Image: |
|
return await dbContext.Images |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.IncludeForSearch() |
|
.AsSplitQuery() |
|
.SingleOrDefaultAsync(mi => mi.Id == id, cancellationToken); |
|
case RemoteStream: |
|
return await dbContext.RemoteStreams |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.IncludeForSearch() |
|
.AsSplitQuery() |
|
.SingleOrDefaultAsync(mi => mi.Id == id, cancellationToken); |
|
} |
|
|
|
return Option<MediaItem>.None; |
|
} |
|
|
|
public async Task<List<string>> GetLanguagesForShow(Show show) |
|
{ |
|
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(); |
|
return await dbContext.Connection.QueryAsync<string>( |
|
@"SELECT DISTINCT Language |
|
FROM MediaStream |
|
INNER JOIN MediaVersion MV ON MediaStream.MediaVersionId = MV.Id |
|
INNER JOIN Episode E ON MV.EpisodeId = E.Id |
|
INNER JOIN Season S ON E.SeasonId = S.Id |
|
WHERE MediaStreamKind = 2 AND S.ShowId = @ShowId", |
|
new { ShowId = show.Id }).Map(result => result.ToList()); |
|
} |
|
|
|
public async Task<List<string>> GetSubLanguagesForShow(Show show) |
|
{ |
|
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(); |
|
return await dbContext.Connection.QueryAsync<string>( |
|
@"SELECT DISTINCT Language |
|
FROM MediaStream |
|
INNER JOIN MediaVersion MV ON MediaStream.MediaVersionId = MV.Id |
|
INNER JOIN Episode E ON MV.EpisodeId = E.Id |
|
INNER JOIN Season S ON E.SeasonId = S.Id |
|
WHERE MediaStreamKind = 3 AND S.ShowId = @ShowId", |
|
new { ShowId = show.Id }).Map(result => result.ToList()); |
|
} |
|
|
|
public async Task<List<string>> GetLanguagesForSeason(Season season) |
|
{ |
|
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(); |
|
return await dbContext.Connection.QueryAsync<string>( |
|
@"SELECT DISTINCT Language |
|
FROM MediaStream |
|
INNER JOIN MediaVersion MV ON MediaStream.MediaVersionId = MV.Id |
|
INNER JOIN Episode E ON MV.EpisodeId = E.Id |
|
WHERE MediaStreamKind = 2 AND E.SeasonId = @SeasonId", |
|
new { SeasonId = season.Id }).Map(result => result.ToList()); |
|
} |
|
|
|
public async Task<List<string>> GetSubLanguagesForSeason(Season season) |
|
{ |
|
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(); |
|
return await dbContext.Connection.QueryAsync<string>( |
|
@"SELECT DISTINCT Language |
|
FROM MediaStream |
|
INNER JOIN MediaVersion MV ON MediaStream.MediaVersionId = MV.Id |
|
INNER JOIN Episode E ON MV.EpisodeId = E.Id |
|
WHERE MediaStreamKind = 3 AND E.SeasonId = @SeasonId", |
|
new { SeasonId = season.Id }).Map(result => result.ToList()); |
|
} |
|
|
|
public async Task<List<string>> GetLanguagesForArtist(Artist artist) |
|
{ |
|
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(); |
|
return await dbContext.Connection.QueryAsync<string>( |
|
@"SELECT DISTINCT Language |
|
FROM MediaStream |
|
INNER JOIN MediaVersion V ON MediaStream.MediaVersionId = V.Id |
|
INNER JOIN MusicVideo MV ON V.MusicVideoId = MV.Id |
|
INNER JOIN Artist A on MV.ArtistId = A.Id |
|
WHERE MediaStreamKind = 2 AND A.Id = @ArtistId", |
|
new { ArtistId = artist.Id }).Map(result => result.ToList()); |
|
} |
|
|
|
public async Task<List<string>> GetSubLanguagesForArtist(Artist artist) |
|
{ |
|
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(); |
|
return await dbContext.Connection.QueryAsync<string>( |
|
@"SELECT DISTINCT Language |
|
FROM MediaStream |
|
INNER JOIN MediaVersion V ON MediaStream.MediaVersionId = V.Id |
|
INNER JOIN MusicVideo MV ON V.MusicVideoId = MV.Id |
|
INNER JOIN Artist A on MV.ArtistId = A.Id |
|
WHERE MediaStreamKind = 3 AND A.Id = @ArtistId", |
|
new { ArtistId = artist.Id }).Map(result => result.ToList()); |
|
} |
|
|
|
public async IAsyncEnumerable<MediaItem> GetAllMediaItems( |
|
[EnumeratorCancellation] CancellationToken cancellationToken = default) |
|
{ |
|
await foreach (var item in GetAllMovies(cancellationToken)) |
|
{ |
|
yield return item; |
|
} |
|
|
|
await foreach (var item in GetAllShows(cancellationToken)) |
|
{ |
|
yield return item; |
|
} |
|
|
|
await foreach (var item in GetAllSeasons(cancellationToken)) |
|
{ |
|
yield return item; |
|
} |
|
|
|
await foreach (var item in GetAllEpisodes(cancellationToken)) |
|
{ |
|
yield return item; |
|
} |
|
|
|
await foreach (var item in GetAllMusicVideos(cancellationToken)) |
|
{ |
|
yield return item; |
|
} |
|
|
|
await foreach (var item in GetAllArtists(cancellationToken)) |
|
{ |
|
yield return item; |
|
} |
|
|
|
await foreach (var item in GetAllOtherVideos(cancellationToken)) |
|
{ |
|
yield return item; |
|
} |
|
|
|
await foreach (var item in GetAllSongs(cancellationToken)) |
|
{ |
|
yield return item; |
|
} |
|
|
|
await foreach (var item in GetAllImages(cancellationToken)) |
|
{ |
|
yield return item; |
|
} |
|
|
|
await foreach (var item in GetAllRemoteStreams(cancellationToken)) |
|
{ |
|
yield return item; |
|
} |
|
} |
|
|
|
private async IAsyncEnumerable<Movie> GetAllMovies([EnumeratorCancellation] CancellationToken cancellationToken) |
|
{ |
|
await using var dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken); |
|
|
|
ConfiguredCancelableAsyncEnumerable<Movie> movies = dbContext.Movies |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.IncludeForSearch() |
|
.AsSplitQuery() |
|
.AsAsyncEnumerable() |
|
.WithCancellation(cancellationToken); |
|
|
|
await foreach (var movie in movies) |
|
{ |
|
yield return movie; |
|
} |
|
} |
|
|
|
private async IAsyncEnumerable<Show> GetAllShows([EnumeratorCancellation] CancellationToken cancellationToken) |
|
{ |
|
await using var dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken); |
|
|
|
ConfiguredCancelableAsyncEnumerable<Show> shows = dbContext.Shows |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.IncludeForSearch() |
|
.AsSplitQuery() |
|
.AsAsyncEnumerable() |
|
.WithCancellation(cancellationToken); |
|
|
|
await foreach (var movie in shows) |
|
{ |
|
yield return movie; |
|
} |
|
} |
|
|
|
private async IAsyncEnumerable<Season> GetAllSeasons([EnumeratorCancellation] CancellationToken cancellationToken) |
|
{ |
|
await using var dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken); |
|
|
|
ConfiguredCancelableAsyncEnumerable<Season> seasons = dbContext.Seasons |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.IncludeForSearch() |
|
.AsSplitQuery() |
|
.AsAsyncEnumerable() |
|
.WithCancellation(cancellationToken); |
|
|
|
await foreach (var movie in seasons) |
|
{ |
|
yield return movie; |
|
} |
|
} |
|
|
|
private async IAsyncEnumerable<Episode> GetAllEpisodes([EnumeratorCancellation] CancellationToken cancellationToken) |
|
{ |
|
await using var dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken); |
|
|
|
ConfiguredCancelableAsyncEnumerable<Episode> episodes = dbContext.Episodes |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.IncludeForSearch() |
|
.AsSplitQuery() |
|
.AsAsyncEnumerable() |
|
.WithCancellation(cancellationToken); |
|
|
|
await foreach (var movie in episodes) |
|
{ |
|
yield return movie; |
|
} |
|
} |
|
|
|
private async IAsyncEnumerable<MusicVideo> GetAllMusicVideos( |
|
[EnumeratorCancellation] CancellationToken cancellationToken) |
|
{ |
|
await using var dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken); |
|
|
|
ConfiguredCancelableAsyncEnumerable<MusicVideo> musicVideos = dbContext.MusicVideos |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.IncludeForSearch() |
|
.AsSplitQuery() |
|
.AsAsyncEnumerable() |
|
.WithCancellation(cancellationToken); |
|
|
|
await foreach (var movie in musicVideos) |
|
{ |
|
yield return movie; |
|
} |
|
} |
|
|
|
private async IAsyncEnumerable<Artist> GetAllArtists([EnumeratorCancellation] CancellationToken cancellationToken) |
|
{ |
|
await using var dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken); |
|
|
|
ConfiguredCancelableAsyncEnumerable<Artist> artists = dbContext.Artists |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.IncludeForSearch() |
|
.AsSplitQuery() |
|
.AsAsyncEnumerable() |
|
.WithCancellation(cancellationToken); |
|
|
|
await foreach (var movie in artists) |
|
{ |
|
yield return movie; |
|
} |
|
} |
|
|
|
private async IAsyncEnumerable<OtherVideo> GetAllOtherVideos( |
|
[EnumeratorCancellation] CancellationToken cancellationToken) |
|
{ |
|
await using var dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken); |
|
|
|
ConfiguredCancelableAsyncEnumerable<OtherVideo> otherVideos = dbContext.OtherVideos |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.IncludeForSearch() |
|
.AsSplitQuery() |
|
.AsAsyncEnumerable() |
|
.WithCancellation(cancellationToken); |
|
|
|
await foreach (var movie in otherVideos) |
|
{ |
|
yield return movie; |
|
} |
|
} |
|
|
|
private async IAsyncEnumerable<Song> GetAllSongs([EnumeratorCancellation] CancellationToken cancellationToken) |
|
{ |
|
await using var dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken); |
|
|
|
ConfiguredCancelableAsyncEnumerable<Song> songs = dbContext.Songs |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.IncludeForSearch() |
|
.AsSplitQuery() |
|
.AsAsyncEnumerable() |
|
.WithCancellation(cancellationToken); |
|
|
|
await foreach (var movie in songs) |
|
{ |
|
yield return movie; |
|
} |
|
} |
|
|
|
private async IAsyncEnumerable<Image> GetAllImages([EnumeratorCancellation] CancellationToken cancellationToken) |
|
{ |
|
await using var dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken); |
|
|
|
ConfiguredCancelableAsyncEnumerable<Image> images = dbContext.Images |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.IncludeForSearch() |
|
.AsSplitQuery() |
|
.AsAsyncEnumerable() |
|
.WithCancellation(cancellationToken); |
|
|
|
await foreach (var movie in images) |
|
{ |
|
yield return movie; |
|
} |
|
} |
|
|
|
private async IAsyncEnumerable<RemoteStream> GetAllRemoteStreams( |
|
[EnumeratorCancellation] CancellationToken cancellationToken) |
|
{ |
|
await using var dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken); |
|
|
|
ConfiguredCancelableAsyncEnumerable<RemoteStream> remoteStreams = dbContext.RemoteStreams |
|
.AsNoTracking() |
|
.TagWithCallSite() |
|
.IncludeForSearch() |
|
.AsSplitQuery() |
|
.AsAsyncEnumerable() |
|
.WithCancellation(cancellationToken); |
|
|
|
await foreach (var movie in remoteStreams) |
|
{ |
|
yield return movie; |
|
} |
|
} |
|
}
|
|
|