mirror of
https://github.com/sphildreth/roadie
synced 2024-11-22 04:03:10 +00:00
work for #18
This commit is contained in:
parent
1d4e051ff1
commit
97300534a4
30 changed files with 370 additions and 349 deletions
|
@ -21,7 +21,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="2.4.3" />
|
<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="2.4.4" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
@ -55,173 +55,5 @@ namespace Roadie.Library.Tests
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Log Level [{ e.Level }] Log Message [{ e.Message }] ");
|
Console.WriteLine($"Log Level [{ e.Level }] Log Message [{ e.Message }] ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//[Fact]
|
|
||||||
//public void Update_Genre_Normalized_Name()
|
|
||||||
//{
|
|
||||||
// var optionsBuilder = new DbContextOptionsBuilder<RoadieDbContext>();
|
|
||||||
// optionsBuilder.UseMySql("server=viking;userid=roadie;password=MenAtW0rk668;persistsecurityinfo=True;database=roadie;ConvertZeroDateTime=true");
|
|
||||||
|
|
||||||
// using (var context = new RoadieDbContext(optionsBuilder.Options))
|
|
||||||
// {
|
|
||||||
// var now = DateTime.UtcNow;
|
|
||||||
// foreach (var genre in context.Genres)
|
|
||||||
// {
|
|
||||||
// genre.NormalizedName = genre.Name.ToAlphanumericName();
|
|
||||||
// genre.LastUpdated = now;
|
|
||||||
// }
|
|
||||||
// context.SaveChanges();
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//[Fact]
|
|
||||||
//public void Merge_Genres()
|
|
||||||
//{
|
|
||||||
// var optionsBuilder = new DbContextOptionsBuilder<RoadieDbContext>();
|
|
||||||
// optionsBuilder.UseMySql("server=viking;userid=roadie;password=MenAtW0rk668;persistsecurityinfo=True;database=roadie;ConvertZeroDateTime=true");
|
|
||||||
|
|
||||||
// using (var context = new RoadieDbContext(optionsBuilder.Options))
|
|
||||||
// {
|
|
||||||
// var addedArtistToGenre = new List<KeyValuePair<int, int>>();
|
|
||||||
// var addedReleaseToGenre = new List<KeyValuePair<int, int>>();
|
|
||||||
// var now = DateTime.UtcNow;
|
|
||||||
// var groupedGenres = context.Genres.GroupBy(x => x.NormalizedName).ToArray();
|
|
||||||
// foreach (var genreGroup in groupedGenres)
|
|
||||||
// {
|
|
||||||
// var genre = genreGroup.OrderBy(x => x.Id).First();
|
|
||||||
// foreach (var gg in genreGroup.OrderBy(x => x.Id).Skip(1))
|
|
||||||
// {
|
|
||||||
// var artistIdsInDups = (from g in context.Genres
|
|
||||||
// join ag in context.ArtistGenres on g.Id equals ag.GenreId
|
|
||||||
// where g.Id == gg.Id
|
|
||||||
// select ag.ArtistId).Distinct().ToArray();
|
|
||||||
|
|
||||||
// var releaseIdsInDups = (from g in context.Genres
|
|
||||||
// join rg in context.ReleaseGenres on g.Id equals rg.GenreId
|
|
||||||
// where g.Id == gg.Id
|
|
||||||
// select rg.ReleaseId).Distinct().ToArray();
|
|
||||||
|
|
||||||
// if (artistIdsInDups != null && artistIdsInDups.Any())
|
|
||||||
// {
|
|
||||||
// foreach (var artistIdsInDup in artistIdsInDups)
|
|
||||||
// {
|
|
||||||
// if (!addedArtistToGenre.Any(x => x.Key == artistIdsInDup && x.Value == genre.Id))
|
|
||||||
// {
|
|
||||||
// context.ArtistGenres.Add(new ArtistGenre
|
|
||||||
// {
|
|
||||||
// ArtistId = artistIdsInDup,
|
|
||||||
// GenreId = genre.Id
|
|
||||||
// });
|
|
||||||
// addedArtistToGenre.Add(new KeyValuePair<int, int>(artistIdsInDup, genre.Id));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (releaseIdsInDups != null && releaseIdsInDups.Any())
|
|
||||||
// {
|
|
||||||
// foreach (var releaseIdsInDup in releaseIdsInDups)
|
|
||||||
// {
|
|
||||||
// if (!addedReleaseToGenre.Any(x => x.Key == releaseIdsInDup && x.Value == genre.Id))
|
|
||||||
// {
|
|
||||||
// context.ReleaseGenres.Add(new ReleaseGenre
|
|
||||||
// {
|
|
||||||
// ReleaseId = releaseIdsInDup,
|
|
||||||
// GenreId = genre.Id
|
|
||||||
// });
|
|
||||||
// addedReleaseToGenre.Add(new KeyValuePair<int, int>(releaseIdsInDup, genre.Id));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// context.Genres.Remove(gg);
|
|
||||||
// context.SaveChanges();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
//[Fact]
|
|
||||||
//public void Update_Releases_Special_Name()
|
|
||||||
//{
|
|
||||||
// var optionsBuilder = new DbContextOptionsBuilder<RoadieDbContext>();
|
|
||||||
// optionsBuilder.UseMySql("server=viking;userid=roadie;password=MenAtW0rk668;persistsecurityinfo=True;database=roadie;ConvertZeroDateTime=true");
|
|
||||||
|
|
||||||
// using (var context = new RoadieDbContext(optionsBuilder.Options))
|
|
||||||
// {
|
|
||||||
// var now = DateTime.UtcNow;
|
|
||||||
// foreach (var release in context.Releases)
|
|
||||||
// {
|
|
||||||
// var releaseModel = release.Adapt<Roadie.Library.Models.Releases.Release>();
|
|
||||||
// var specialReleaseTitle = release.Title.ToAlphanumericName();
|
|
||||||
// if (!releaseModel.AlternateNamesList.Contains(specialReleaseTitle, StringComparer.OrdinalIgnoreCase))
|
|
||||||
// {
|
|
||||||
// var alt = new List<string>(releaseModel.AlternateNamesList)
|
|
||||||
// {
|
|
||||||
// specialReleaseTitle
|
|
||||||
// };
|
|
||||||
// release.AlternateNames = alt.ToDelimitedList();
|
|
||||||
// release.LastUpdated = now;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// context.SaveChanges();
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//[Fact]
|
|
||||||
//public void Update_Artist_Special_Name()
|
|
||||||
//{
|
|
||||||
// var optionsBuilder = new DbContextOptionsBuilder<RoadieDbContext>();
|
|
||||||
// optionsBuilder.UseMySql("server=viking;userid=roadie;password=MenAtW0rk668;persistsecurityinfo=True;database=roadie;ConvertZeroDateTime=true");
|
|
||||||
|
|
||||||
// using (var context = new RoadieDbContext(optionsBuilder.Options))
|
|
||||||
// {
|
|
||||||
// var now = DateTime.UtcNow;
|
|
||||||
// foreach (var artist in context.Artists)
|
|
||||||
// {
|
|
||||||
// var artistModel = artist.Adapt<Roadie.Library.Models.Artist>();
|
|
||||||
// var specialArtistName = artist.Name.ToAlphanumericName();
|
|
||||||
// if (!artistModel.AlternateNamesList.Contains(specialArtistName, StringComparer.OrdinalIgnoreCase))
|
|
||||||
// {
|
|
||||||
// var alt = new List<string>(artistModel.AlternateNamesList)
|
|
||||||
// {
|
|
||||||
// specialArtistName
|
|
||||||
// };
|
|
||||||
// artist.AlternateNames = alt.ToDelimitedList();
|
|
||||||
// artist.LastUpdated = now;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// context.SaveChanges();
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//[Fact]
|
|
||||||
//public void Update_Label_Special_Name()
|
|
||||||
//{
|
|
||||||
// var optionsBuilder = new DbContextOptionsBuilder<RoadieDbContext>();
|
|
||||||
// optionsBuilder.UseMySql("server=viking;userid=roadie;password=MenAtW0rk668;persistsecurityinfo=True;database=roadie;ConvertZeroDateTime=true");
|
|
||||||
|
|
||||||
// using (var context = new RoadieDbContext(optionsBuilder.Options))
|
|
||||||
// {
|
|
||||||
// var now = DateTime.UtcNow;
|
|
||||||
// foreach (var label in context.Labels)
|
|
||||||
// {
|
|
||||||
// var labelModel = label.Adapt<Roadie.Library.Models.Label>();
|
|
||||||
// var specialLabelName = labelModel.Name.ToAlphanumericName();
|
|
||||||
// if (!labelModel.AlternateNamesList.Contains(specialLabelName, StringComparer.OrdinalIgnoreCase))
|
|
||||||
// {
|
|
||||||
// var alt = new List<string>(labelModel.AlternateNamesList)
|
|
||||||
// {
|
|
||||||
// specialLabelName
|
|
||||||
// };
|
|
||||||
// label.AlternateNames = alt.ToDelimitedList();
|
|
||||||
// label.LastUpdated = now;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// context.SaveChanges();
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -312,8 +312,6 @@ namespace Roadie.Library.Tests
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0618 // Type or member is obsolete
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
var now = DateTime.UtcNow;
|
var now = DateTime.UtcNow;
|
||||||
var optionsBuilder = new DbContextOptionsBuilder<RoadieDbContext>();
|
|
||||||
optionsBuilder.UseMySql("server=viking;userid=roadie;password=MenAtW0rk668;persistsecurityinfo=True;database=roadie_dev;ConvertZeroDateTime=true");
|
|
||||||
|
|
||||||
var settings = new RoadieSettings();
|
var settings = new RoadieSettings();
|
||||||
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
|
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
|
||||||
|
@ -322,7 +320,7 @@ namespace Roadie.Library.Tests
|
||||||
configuration.GetSection("RoadieSettings").Bind(settings);
|
configuration.GetSection("RoadieSettings").Bind(settings);
|
||||||
settings.ConnectionString = configuration.GetConnectionString("RoadieDatabaseConnection");
|
settings.ConnectionString = configuration.GetConnectionString("RoadieDatabaseConnection");
|
||||||
|
|
||||||
using (var context = new RoadieDbContext(optionsBuilder.Options))
|
using (var context = DbContextFactory.Create(settings))
|
||||||
{
|
{
|
||||||
foreach (var artist in context.Artists.Where(x => x.Thumbnail != null).OrderBy(x => x.SortName ?? x.Name))
|
foreach (var artist in context.Artists.Where(x => x.Thumbnail != null).OrderBy(x => x.SortName ?? x.Name))
|
||||||
{
|
{
|
||||||
|
|
26
Roadie.Api.Library/Data/DbContextFactory.cs
Normal file
26
Roadie.Api.Library/Data/DbContextFactory.cs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Pomelo.EntityFrameworkCore.MySql.Infrastructure;
|
||||||
|
using Roadie.Library.Configuration;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Roadie.Library.Data
|
||||||
|
{
|
||||||
|
public static class DbContextFactory
|
||||||
|
{
|
||||||
|
public static IRoadieDbContext Create(IRoadieSettings configuration)
|
||||||
|
{
|
||||||
|
var optionsBuilder = new DbContextOptionsBuilder<MySQLRoadieDbContext>();
|
||||||
|
optionsBuilder.UseMySql(configuration.ConnectionString, mySqlOptions =>
|
||||||
|
{
|
||||||
|
mySqlOptions.ServerVersion(new Version(5, 5), ServerType.MariaDb);
|
||||||
|
mySqlOptions.EnableRetryOnFailure(
|
||||||
|
10,
|
||||||
|
TimeSpan.FromSeconds(30),
|
||||||
|
null);
|
||||||
|
});
|
||||||
|
return new MySQLRoadieDbContext(optionsBuilder.Options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,7 +10,7 @@ using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Roadie.Library.Data
|
namespace Roadie.Library.Data
|
||||||
{
|
{
|
||||||
public interface IRoadieDbContext : IDisposable, IInfrastructure<IServiceProvider>, IDbContextDependencies, IDbSetCache, IDbContextPoolable
|
public interface IRoadieDbContext : IRoadieDbRandomizer, IRoadieDbUserStats, IDisposable, IInfrastructure<IServiceProvider>, IDbContextDependencies, IDbSetCache, IDbContextPoolable
|
||||||
{
|
{
|
||||||
DbSet<ArtistAssociation> ArtistAssociations { get; set; }
|
DbSet<ArtistAssociation> ArtistAssociations { get; set; }
|
||||||
DbSet<ArtistGenre> ArtistGenres { get; set; }
|
DbSet<ArtistGenre> ArtistGenres { get; set; }
|
||||||
|
@ -105,8 +105,7 @@ namespace Roadie.Library.Data
|
||||||
|
|
||||||
int SaveChanges();
|
int SaveChanges();
|
||||||
|
|
||||||
Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess,
|
Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken));
|
||||||
CancellationToken cancellationToken = default(CancellationToken));
|
|
||||||
|
|
||||||
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken));
|
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken));
|
||||||
|
|
||||||
|
|
17
Roadie.Api.Library/Data/IRoadieDbRandomizer.cs
Normal file
17
Roadie.Api.Library/Data/IRoadieDbRandomizer.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Roadie.Library.Data
|
||||||
|
{
|
||||||
|
public interface IRoadieDbRandomizer
|
||||||
|
{
|
||||||
|
SortedDictionary<int, int> RandomArtistIds(int userId, int randomLimit, bool doOnlyFavorites = false, bool doOnlyRated = false);
|
||||||
|
|
||||||
|
SortedDictionary<int, int> RandomGenreIds(int userId, int randomLimit, bool doOnlyFavorites = false, bool doOnlyRated = false);
|
||||||
|
|
||||||
|
SortedDictionary<int, int> RandomLabelIds(int userId, int randomLimit, bool doOnlyFavorites = false, bool doOnlyRated = false);
|
||||||
|
|
||||||
|
SortedDictionary<int, int> RandomReleaseIds(int userId, int randomLimit, bool doOnlyFavorites = false, bool doOnlyRated = false);
|
||||||
|
|
||||||
|
SortedDictionary<int, int> RandomTrackIds(int userId, int randomLimit, bool doOnlyFavorites = false, bool doOnlyRated = false);
|
||||||
|
}
|
||||||
|
}
|
19
Roadie.Api.Library/Data/IRoadieDbUserStats.cs
Normal file
19
Roadie.Api.Library/Data/IRoadieDbUserStats.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Roadie.Library.Data
|
||||||
|
{
|
||||||
|
public interface IRoadieDbUserStats
|
||||||
|
{
|
||||||
|
Task<Artist> MostPlayedArtist(int userId);
|
||||||
|
|
||||||
|
Task<Release> MostPlayedRelease(int userId);
|
||||||
|
|
||||||
|
Task<Track> MostPlayedTrack(int userId);
|
||||||
|
|
||||||
|
Task<Artist> LastPlayedArtist(int userId);
|
||||||
|
|
||||||
|
Task<Release> LastPlayedRelease(int userId);
|
||||||
|
|
||||||
|
Task<Track> LastPlayedTrack(int userId);
|
||||||
|
}
|
||||||
|
}
|
197
Roadie.Api.Library/Data/MysqlRoadieDbContext.cs
Normal file
197
Roadie.Api.Library/Data/MysqlRoadieDbContext.cs
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Roadie.Library.Data
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// MySQL/MariaDB implementation of DbContext
|
||||||
|
/// </summary>
|
||||||
|
public sealed class MySQLRoadieDbContext : RoadieDbContext
|
||||||
|
{
|
||||||
|
public MySQLRoadieDbContext(DbContextOptions options)
|
||||||
|
: base(options)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<Artist> LastPlayedArtist(int userId)
|
||||||
|
{
|
||||||
|
var sql = @"SELECT a.*
|
||||||
|
FROM `usertrack` ut
|
||||||
|
join `track` t on (ut.trackId = t.id)
|
||||||
|
join `releasemedia` rm on (t.releaseMediaId = rm.id)
|
||||||
|
join `release` r on (rm.releaseId = r.id)
|
||||||
|
join `artist` a on (r.artistId = a.id)
|
||||||
|
where ut.userId = {0}
|
||||||
|
ORDER by ut.lastPlayed desc
|
||||||
|
LIMIT 1";
|
||||||
|
return await Artists.FromSqlRaw(sql, userId).FirstOrDefaultAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<Release> LastPlayedRelease(int userId)
|
||||||
|
{
|
||||||
|
var sql = @"SELECT r.*
|
||||||
|
FROM `usertrack` ut
|
||||||
|
join `track` t on (ut.trackId = t.id)
|
||||||
|
join `releasemedia` rm on (t.releaseMediaId = rm.id)
|
||||||
|
join `release` r on (rm.releaseId = r.id)
|
||||||
|
WHERE ut.userId = {0}
|
||||||
|
ORDER by ut.lastPlayed desc
|
||||||
|
LIMIT 1";
|
||||||
|
return await Releases.FromSqlRaw(sql, userId)
|
||||||
|
.Include(x => x.Artist)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<Track> LastPlayedTrack(int userId)
|
||||||
|
{
|
||||||
|
var sql = @"SELECT t.*
|
||||||
|
FROM `usertrack` ut
|
||||||
|
join `track` t on (ut.trackId = t.id)
|
||||||
|
WHERE ut.userId = {0}
|
||||||
|
ORDER by ut.lastPlayed desc
|
||||||
|
LIMIT 1";
|
||||||
|
return await Tracks.FromSqlRaw(sql, userId)
|
||||||
|
.Include(x => x.TrackArtist)
|
||||||
|
.Include(x => x.ReleaseMedia)
|
||||||
|
.Include("ReleaseMedia.Release")
|
||||||
|
.Include("ReleaseMedia.Release.Artist")
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<Artist> MostPlayedArtist(int userId)
|
||||||
|
{
|
||||||
|
var sql = @"SELECT a.*
|
||||||
|
FROM `usertrack` ut
|
||||||
|
join `track` t on (ut.trackId = t.id)
|
||||||
|
join `releasemedia` rm on (t.releaseMediaId = rm.id)
|
||||||
|
join `release` r on (rm.releaseId = r.id)
|
||||||
|
join `artist` a on (r.artistId = a.id)
|
||||||
|
where ut.userId = {0}
|
||||||
|
group by r.id
|
||||||
|
order by SUM(ut.playedCount) desc
|
||||||
|
LIMIT 1";
|
||||||
|
return await Artists.FromSqlRaw(sql, userId).FirstOrDefaultAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<Release> MostPlayedRelease(int userId)
|
||||||
|
{
|
||||||
|
var sql = @"SELECT r.*
|
||||||
|
FROM `usertrack` ut
|
||||||
|
join `track` t on (ut.trackId = t.id)
|
||||||
|
join `releasemedia` rm on (t.releaseMediaId = rm.id)
|
||||||
|
join `release` r on (rm.releaseId = r.id)
|
||||||
|
WHERE ut.userId = {0}
|
||||||
|
GROUP by r.id
|
||||||
|
ORDER by SUM(ut.playedCount) desc
|
||||||
|
LIMIT 1";
|
||||||
|
return await Releases.FromSqlRaw(sql, userId)
|
||||||
|
.Include(x => x.Artist)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<Track> MostPlayedTrack(int userId)
|
||||||
|
{
|
||||||
|
var sql = @"SELECT t.*
|
||||||
|
FROM `usertrack` ut
|
||||||
|
join `track` t on (ut.trackId = t.id)
|
||||||
|
WHERE ut.userId = {0}
|
||||||
|
GROUP by t.id
|
||||||
|
ORDER by SUM(ut.playedCount) desc
|
||||||
|
LIMIT 1";
|
||||||
|
return await Tracks.FromSqlRaw(sql, userId)
|
||||||
|
.Include(x => x.TrackArtist)
|
||||||
|
.Include(x => x.ReleaseMedia)
|
||||||
|
.Include("ReleaseMedia.Release")
|
||||||
|
.Include("ReleaseMedia.Release.Artist")
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override SortedDictionary<int, int> RandomArtistIds(int userId, int randomLimit, bool doOnlyFavorites = false, bool doOnlyRated = false)
|
||||||
|
{
|
||||||
|
var sql = @"SELECT a.id
|
||||||
|
FROM `artist` a
|
||||||
|
WHERE(a.id NOT IN(select artistId FROM `userartist` where userId = {1} and isDisliked = 1))
|
||||||
|
OR(a.id IN(select artistId FROM `userartist` where userId = {1} and isFavorite = 1)
|
||||||
|
AND {2} = 1)
|
||||||
|
order BY RIGHT(HEX((1 << 24) * (1 + RAND())), 6)
|
||||||
|
LIMIT 0, {0}";
|
||||||
|
var ids = Artists.FromSqlRaw(sql, randomLimit, userId, doOnlyFavorites ? "1" : "0").Select(x => x.Id).ToList();
|
||||||
|
var dict = ids.Select((id, i) => new { key = i, value = id }).ToDictionary(x => x.key, x => x.value);
|
||||||
|
return new SortedDictionary<int, int>(dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override SortedDictionary<int, int> RandomGenreIds(int userId, int randomLimit, bool doOnlyFavorites = false, bool doOnlyRated = false)
|
||||||
|
{
|
||||||
|
var sql = @"SELECT g.id
|
||||||
|
FROM `genre` g
|
||||||
|
ORDER BY RIGHT( HEX( (1<<24) * (1+RAND()) ), 6)
|
||||||
|
LIMIT 0, {0}";
|
||||||
|
var ids = Genres.FromSqlRaw(sql, randomLimit).Select(x => x.Id).ToList();
|
||||||
|
var dict = ids.Select((id, i) => new { key = i, value = id }).ToDictionary(x => x.key, x => x.value);
|
||||||
|
return new SortedDictionary<int, int>(dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override SortedDictionary<int, int> RandomLabelIds(int userId, int randomLimit, bool doOnlyFavorites = false, bool doOnlyRated = false)
|
||||||
|
{
|
||||||
|
var sql = @"SELECT l.id
|
||||||
|
FROM `label` l
|
||||||
|
ORDER BY RIGHT( HEX( (1<<24) * (1+RAND()) ), 6)
|
||||||
|
LIMIT 0, {0}";
|
||||||
|
var ids = Labels.FromSqlRaw(sql, randomLimit).Select(x => x.Id).ToList();
|
||||||
|
var dict = ids.Select((id, i) => new { key = i, value = id }).ToDictionary(x => x.key, x => x.value);
|
||||||
|
return new SortedDictionary<int, int>(dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override SortedDictionary<int, int> RandomReleaseIds(int userId, int randomLimit, bool doOnlyFavorites = false, bool doOnlyRated = false)
|
||||||
|
{
|
||||||
|
var sql = @"SELECT r.id
|
||||||
|
FROM `release` r
|
||||||
|
WHERE (r.id NOT IN (select releaseId FROM `userrelease` where userId = {1} and isDisliked = 1))
|
||||||
|
OR (r.id IN (select releaseId FROM `userrelease` where userId = {1} and isFavorite = 1)
|
||||||
|
AND {2} = 1)
|
||||||
|
ORDER BY RIGHT( HEX( (1<<24) * (1+RAND()) ), 6)
|
||||||
|
LIMIT 0, {0}";
|
||||||
|
var ids = Releases.FromSqlRaw(sql, randomLimit, userId, doOnlyFavorites ? "1" : "0").Select(x => x.Id).ToList();
|
||||||
|
var dict = ids.Select((id, i) => new { key = i, value = id }).ToDictionary(x => x.key, x => x.value);
|
||||||
|
return new SortedDictionary<int, int>(dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override SortedDictionary<int, int> RandomTrackIds(int userId, int randomLimit, bool doOnlyFavorites = false, bool doOnlyRated = false)
|
||||||
|
{
|
||||||
|
var sql = @"SELECT t.id
|
||||||
|
FROM `track` t
|
||||||
|
# Rated filter
|
||||||
|
WHERE ((t.rating > 0 AND {3} = 1) OR {3} = 0)
|
||||||
|
# Artist is not disliked
|
||||||
|
AND ((t.id NOT IN (select tt.id
|
||||||
|
FROM `track` tt
|
||||||
|
JOIN `releasemedia` rm on (tt.releaseMediaId = rm.id)
|
||||||
|
JOIN `userartist` ua on (rm.id = ua.artistId)
|
||||||
|
WHERE ua.userId = {1} AND ua.isDisliked = 1))
|
||||||
|
# Release is not disliked
|
||||||
|
AND (t.id NOT IN (select tt.id
|
||||||
|
FROM `track` tt
|
||||||
|
JOIN `releasemedia` rm on (tt.releaseMediaId = rm.id)
|
||||||
|
JOIN `userrelease` ur on (rm.releaseId = ur.releaseId)
|
||||||
|
WHERE ur.userId = {1} AND ur.isDisliked = 1))
|
||||||
|
# Track is not disliked
|
||||||
|
AND (t.id NOT IN (select tt.id
|
||||||
|
FROM `track` tt
|
||||||
|
JOIN `usertrack` ut on (tt.id = ut.trackId)
|
||||||
|
WHERE ut.userId = {1} AND ut.isDisliked = 1)))
|
||||||
|
# If toggled then only favorites
|
||||||
|
AND ((t.id IN (select tt.id
|
||||||
|
FROM `track` tt
|
||||||
|
JOIN `usertrack` ut on (tt.id = ut.trackId)
|
||||||
|
WHERE ut.userId = {1} AND ut.isFavorite = 1) AND {2} = 1) OR {2} = 0)
|
||||||
|
order BY RIGHT( HEX( (1<<24) * (1+RAND()) ), 6)
|
||||||
|
LIMIT 0, {0}";
|
||||||
|
var ids = Releases.FromSqlRaw(sql, randomLimit, userId, doOnlyFavorites ? "1" : "0", doOnlyRated ? "1" : "0").Select(x => x.Id).ToList();
|
||||||
|
var dict = ids.Select((id, i) => new { key = i, value = id }).ToDictionary(x => x.key, x => x.value);
|
||||||
|
return new SortedDictionary<int, int>(dict);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,12 +3,13 @@ using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||||
using Roadie.Library.Enums;
|
using Roadie.Library.Enums;
|
||||||
using Roadie.Library.Identity;
|
using Roadie.Library.Identity;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Roadie.Library.Data
|
namespace Roadie.Library.Data
|
||||||
{
|
{
|
||||||
public class RoadieDbContext : DbContext, IRoadieDbContext
|
public abstract partial class RoadieDbContext : DbContext, IRoadieDbContext
|
||||||
{
|
{
|
||||||
public DbSet<ArtistAssociation> ArtistAssociations { get; set; }
|
public DbSet<ArtistAssociation> ArtistAssociations { get; set; }
|
||||||
|
|
||||||
|
@ -71,8 +72,8 @@ namespace Roadie.Library.Data
|
||||||
public DbSet<UserTrack> UserTracks { get; set; }
|
public DbSet<UserTrack> UserTracks { get; set; }
|
||||||
public DbSet<InviteToken> InviteTokens { get; set; }
|
public DbSet<InviteToken> InviteTokens { get; set; }
|
||||||
|
|
||||||
public RoadieDbContext(DbContextOptions<RoadieDbContext> options)
|
public RoadieDbContext(DbContextOptions options)
|
||||||
: base(options)
|
: base(options)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
31
Roadie.Api.Library/Data/RoadieDbContextPartial.cs
Normal file
31
Roadie.Api.Library/Data/RoadieDbContextPartial.cs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Roadie.Library.Data
|
||||||
|
{
|
||||||
|
public abstract partial class RoadieDbContext : DbContext, IRoadieDbContext
|
||||||
|
{
|
||||||
|
public abstract SortedDictionary<int, int> RandomArtistIds(int userId, int randomLimit, bool doOnlyFavorites = false, bool doOnlyRated = false);
|
||||||
|
|
||||||
|
public abstract SortedDictionary<int, int> RandomGenreIds(int userId, int randomLimit, bool doOnlyFavorites = false, bool doOnlyRated = false);
|
||||||
|
|
||||||
|
public abstract SortedDictionary<int, int> RandomLabelIds(int userId, int randomLimit, bool doOnlyFavorites = false, bool doOnlyRated = false);
|
||||||
|
|
||||||
|
public abstract SortedDictionary<int, int> RandomReleaseIds(int userId, int randomLimit, bool doOnlyFavorites = false, bool doOnlyRated = false);
|
||||||
|
|
||||||
|
public abstract SortedDictionary<int, int> RandomTrackIds(int userId, int randomLimit, bool doOnlyFavorites = false, bool doOnlyRated = false);
|
||||||
|
|
||||||
|
public abstract Task<Artist> MostPlayedArtist(int userId);
|
||||||
|
|
||||||
|
public abstract Task<Release> MostPlayedRelease(int userId);
|
||||||
|
|
||||||
|
public abstract Task<Track> MostPlayedTrack(int userId);
|
||||||
|
|
||||||
|
public abstract Task<Track> LastPlayedTrack(int userId);
|
||||||
|
|
||||||
|
public abstract Task<Artist> LastPlayedArtist(int userId);
|
||||||
|
|
||||||
|
public abstract Task<Release> LastPlayedRelease(int userId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,7 +10,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AutoCompare.Core" Version="1.0.0" />
|
<PackageReference Include="AutoCompare.Core" Version="1.0.0" />
|
||||||
<PackageReference Include="CsvHelper" Version="12.2.1" />
|
<PackageReference Include="CsvHelper" Version="12.2.1" />
|
||||||
<PackageReference Include="EFCore.BulkExtensions" Version="3.0.0" />
|
<PackageReference Include="EFCore.BulkExtensions" Version="3.0.2" />
|
||||||
<PackageReference Include="FluentFTP" Version="28.0.1" />
|
<PackageReference Include="FluentFTP" Version="28.0.1" />
|
||||||
<PackageReference Include="Hashids.net" Version="1.3.0" />
|
<PackageReference Include="Hashids.net" Version="1.3.0" />
|
||||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.16" />
|
<PackageReference Include="HtmlAgilityPack" Version="1.11.16" />
|
||||||
|
|
|
@ -247,21 +247,12 @@ namespace Roadie.Api.Services
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
int[] randomArtistIds = null;
|
int[] randomArtistIds = null;
|
||||||
|
SortedDictionary<int, int> randomArtistData = null;
|
||||||
if (doRandomize ?? false)
|
if (doRandomize ?? false)
|
||||||
{
|
{
|
||||||
var randomLimit = request.Limit ?? roadieUser?.RandomReleaseLimit ?? request.LimitValue;
|
var randomLimit = request.Limit ?? roadieUser?.RandomReleaseLimit ?? request.LimitValue;
|
||||||
var userId = roadieUser?.Id ?? -1;
|
randomArtistData = DbContext.RandomArtistIds(roadieUser?.Id ?? -1, randomLimit, request.FilterFavoriteOnly, request.FilterRatedOnly);
|
||||||
|
randomArtistIds = randomArtistData.Select(x => x.Value).ToArray();
|
||||||
//// This is MySQL specific but I can't figure out how else to get random without throwing EF local evaluate warnings.
|
|
||||||
var sql = @"select a.id
|
|
||||||
FROM `artist` a
|
|
||||||
WHERE(a.id NOT IN(select artistId FROM `userartist` where userId = {1} and isDisliked = 1))
|
|
||||||
OR(a.id IN(select artistId FROM `userartist` where userId = {1} and isFavorite = 1)
|
|
||||||
AND {2} = 1)
|
|
||||||
order BY RIGHT(HEX((1 << 24) * (1 + RAND())), 6)
|
|
||||||
LIMIT 0, {0}";
|
|
||||||
randomArtistIds = (from a in DbContext.Artists.FromSqlRaw(sql, randomLimit, userId, request.FilterFavoriteOnly ? "1" : "0")
|
|
||||||
select a.Id).ToArray();
|
|
||||||
rowCount = DbContext.Artists.Count();
|
rowCount = DbContext.Artists.Count();
|
||||||
}
|
}
|
||||||
var result = (from a in DbContext.Artists
|
var result = (from a in DbContext.Artists
|
||||||
|
@ -311,7 +302,12 @@ namespace Roadie.Api.Services
|
||||||
|
|
||||||
if (doRandomize ?? false)
|
if (doRandomize ?? false)
|
||||||
{
|
{
|
||||||
rows = result.ToArray();
|
var resultData = result.ToArray();
|
||||||
|
rows = (from r in resultData
|
||||||
|
join ra in randomArtistData on r.DatabaseId equals ra.Value
|
||||||
|
orderby ra.Key
|
||||||
|
select r
|
||||||
|
).ToArray();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -96,16 +96,12 @@ namespace Roadie.Api.Services
|
||||||
}
|
}
|
||||||
|
|
||||||
int[] randomGenreIds = null;
|
int[] randomGenreIds = null;
|
||||||
|
SortedDictionary<int, int> randomGenreData = null;
|
||||||
if (doRandomize ?? false)
|
if (doRandomize ?? false)
|
||||||
{
|
{
|
||||||
var randomLimit = request.Limit ?? roadieUser?.RandomReleaseLimit ?? request.LimitValue;
|
var randomLimit = request.Limit ?? roadieUser?.RandomReleaseLimit ?? request.LimitValue;
|
||||||
// This is MySQL specific but I can't figure out how else to get random without throwing EF local evaluate warnings.
|
randomGenreData = DbContext.RandomGenreIds(roadieUser?.Id ?? -1, randomLimit, request.FilterFavoriteOnly, request.FilterRatedOnly);
|
||||||
var sql = @"select g.id
|
randomGenreIds = randomGenreData.Select(x => x.Value).ToArray();
|
||||||
FROM `genre` g
|
|
||||||
order BY RIGHT( HEX( (1<<24) * (1+RAND()) ), 6)
|
|
||||||
LIMIT 0, {0}";
|
|
||||||
randomGenreIds = (from l in DbContext.Genres.FromSqlRaw(sql, randomLimit)
|
|
||||||
select l.Id).ToArray();
|
|
||||||
rowCount = DbContext.Genres.Count();
|
rowCount = DbContext.Genres.Count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +134,12 @@ namespace Roadie.Api.Services
|
||||||
rowCount = rowCount ?? result.Count();
|
rowCount = rowCount ?? result.Count();
|
||||||
if (doRandomize ?? false)
|
if (doRandomize ?? false)
|
||||||
{
|
{
|
||||||
rows = result.ToArray();
|
var resultData = result.ToArray();
|
||||||
|
rows = (from r in resultData
|
||||||
|
join ra in randomGenreData on r.DatabaseId equals ra.Value
|
||||||
|
orderby ra.Key
|
||||||
|
select r
|
||||||
|
).ToArray();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -131,16 +131,12 @@ namespace Roadie.Api.Services
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
int[] randomLabelIds = null;
|
int[] randomLabelIds = null;
|
||||||
|
SortedDictionary<int, int> randomLabelData = null;
|
||||||
if (doRandomize ?? false)
|
if (doRandomize ?? false)
|
||||||
{
|
{
|
||||||
var randomLimit = request.Limit ?? roadieUser?.RandomReleaseLimit ?? request.LimitValue;
|
var randomLimit = request.Limit ?? roadieUser?.RandomReleaseLimit ?? request.LimitValue;
|
||||||
// This is MySQL specific but I can't figure out how else to get random without throwing EF local evaluate warnings.
|
randomLabelData = DbContext.RandomLabelIds(roadieUser?.Id ?? -1, randomLimit, request.FilterFavoriteOnly, request.FilterRatedOnly);
|
||||||
var sql = @"select l.id
|
randomLabelIds = randomLabelData.Select(x => x.Value).ToArray();
|
||||||
FROM `label` l
|
|
||||||
order BY RIGHT( HEX( (1<<24) * (1+RAND()) ), 6)
|
|
||||||
LIMIT 0, {0}";
|
|
||||||
randomLabelIds = (from l in DbContext.Labels.FromSqlRaw(sql, randomLimit)
|
|
||||||
select l.Id).ToArray();
|
|
||||||
rowCount = DbContext.Labels.Count();
|
rowCount = DbContext.Labels.Count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +169,12 @@ namespace Roadie.Api.Services
|
||||||
rowCount = rowCount ?? result.Count();
|
rowCount = rowCount ?? result.Count();
|
||||||
if (doRandomize ?? false)
|
if (doRandomize ?? false)
|
||||||
{
|
{
|
||||||
rows = result.ToArray();
|
var resultData = result.ToArray();
|
||||||
|
rows = (from r in resultData
|
||||||
|
join ra in randomLabelData on r.DatabaseId equals ra.Value
|
||||||
|
orderby ra.Key
|
||||||
|
select r
|
||||||
|
).ToArray();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -481,21 +481,12 @@ namespace Roadie.Api.Services
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
int[] randomReleaseIds = null;
|
int[] randomReleaseIds = null;
|
||||||
|
SortedDictionary<int, int> randomReleaseData = null;
|
||||||
if (doRandomize ?? false)
|
if (doRandomize ?? false)
|
||||||
{
|
{
|
||||||
var randomLimit = request.Limit ?? roadieUser?.RandomReleaseLimit ?? request.LimitValue;
|
var randomLimit = request.Limit ?? roadieUser?.RandomReleaseLimit ?? request.LimitValue;
|
||||||
var userId = roadieUser?.Id ?? -1;
|
randomReleaseData = DbContext.RandomReleaseIds(roadieUser?.Id ?? -1, randomLimit, request.FilterFavoriteOnly, request.FilterRatedOnly);
|
||||||
|
randomReleaseIds = randomReleaseData.Select(x => x.Value).ToArray();
|
||||||
// This is MySQL specific but I can't figure out how else to get random without throwing EF local evaluate warnings.
|
|
||||||
var sql = @"select r.id
|
|
||||||
FROM `release` r
|
|
||||||
WHERE (r.id NOT IN (select releaseId FROM `userrelease` where userId = {1} and isDisliked = 1))
|
|
||||||
OR (r.id IN (select releaseId FROM `userrelease` where userId = {1} and isFavorite = 1)
|
|
||||||
AND {2} = 1)
|
|
||||||
order BY RIGHT( HEX( (1<<24) * (1+RAND()) ), 6)
|
|
||||||
LIMIT 0, {0}";
|
|
||||||
randomReleaseIds = (from a in DbContext.Releases.FromSqlRaw(sql, randomLimit, userId, request.FilterFavoriteOnly ? "1" : "0")
|
|
||||||
select a.Id).ToArray();
|
|
||||||
rowCount = DbContext.Releases.Count();
|
rowCount = DbContext.Releases.Count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,7 +547,12 @@ namespace Roadie.Api.Services
|
||||||
|
|
||||||
if (doRandomize ?? false)
|
if (doRandomize ?? false)
|
||||||
{
|
{
|
||||||
rows = result.ToArray();
|
var resultData = result.ToArray();
|
||||||
|
rows = (from r in resultData
|
||||||
|
join ra in randomReleaseData on r.DatabaseId equals ra.Value
|
||||||
|
orderby ra.Key
|
||||||
|
select r
|
||||||
|
).ToArray();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -284,45 +284,13 @@ namespace Roadie.Api.Services
|
||||||
}
|
}
|
||||||
|
|
||||||
int[] randomTrackIds = null;
|
int[] randomTrackIds = null;
|
||||||
|
SortedDictionary<int, int> randomTrackData = null;
|
||||||
if (doRandomize ?? false)
|
if (doRandomize ?? false)
|
||||||
{
|
{
|
||||||
var randomLimit = roadieUser?.RandomReleaseLimit ?? request.LimitValue;
|
var randomLimit = request.Limit ?? roadieUser?.RandomReleaseLimit ?? request.LimitValue;
|
||||||
var userId = roadieUser?.Id ?? -1;
|
randomTrackData = DbContext.RandomTrackIds(roadieUser?.Id ?? -1, randomLimit, request.FilterFavoriteOnly, request.FilterRatedOnly);
|
||||||
|
randomTrackIds = randomTrackData.Select(x => x.Value).ToArray();
|
||||||
// This is MySQL specific but I can't figure out how else to get random without throwing EF local evaluate warnings.
|
|
||||||
var sql = @"SELECT t.id
|
|
||||||
FROM `track` t
|
|
||||||
# Rated filter
|
|
||||||
WHERE ((t.rating > 0 AND {3} = 1) OR {3} = 0)
|
|
||||||
# Artist is not disliked
|
|
||||||
AND ((t.id NOT IN (select tt.id
|
|
||||||
FROM `track` tt
|
|
||||||
JOIN `releasemedia` rm on (tt.releaseMediaId = rm.id)
|
|
||||||
JOIN `userartist` ua on (rm.id = ua.artistId)
|
|
||||||
WHERE ua.userId = {1} AND ua.isDisliked = 1))
|
|
||||||
# Release is not disliked
|
|
||||||
AND (t.id NOT IN (select tt.id
|
|
||||||
FROM `track` tt
|
|
||||||
JOIN `releasemedia` rm on (tt.releaseMediaId = rm.id)
|
|
||||||
JOIN `userrelease` ur on (rm.releaseId = ur.releaseId)
|
|
||||||
WHERE ur.userId = {1} AND ur.isDisliked = 1))
|
|
||||||
# Track is not disliked
|
|
||||||
AND (t.id NOT IN (select tt.id
|
|
||||||
FROM `track` tt
|
|
||||||
JOIN `usertrack` ut on (tt.id = ut.trackId)
|
|
||||||
WHERE ut.userId = {1} AND ut.isDisliked = 1)))
|
|
||||||
# If toggled then only favorites
|
|
||||||
AND ((t.id IN (select tt.id
|
|
||||||
FROM `track` tt
|
|
||||||
JOIN `usertrack` ut on (tt.id = ut.trackId)
|
|
||||||
WHERE ut.userId = {1} AND ut.isFavorite = 1) AND {2} = 1) OR {2} = 0)
|
|
||||||
order BY RIGHT( HEX( (1<<24) * (1+RAND()) ), 6)
|
|
||||||
LIMIT 0, {0};";
|
|
||||||
randomTrackIds = (from a in DbContext.Releases.FromSqlRaw(sql, randomLimit, userId, request.FilterFavoriteOnly ? "1" : "0", request.FilterRatedOnly ? "1" : "0")
|
|
||||||
select a.Id).ToArray();
|
|
||||||
rowCount = DbContext.Releases.Count();
|
rowCount = DbContext.Releases.Count();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Guid?[] filterToTrackIds = null;
|
Guid?[] filterToTrackIds = null;
|
||||||
|
@ -518,30 +486,38 @@ namespace Roadie.Api.Services
|
||||||
rowCount = rowCount ?? result.Count();
|
rowCount = rowCount ?? result.Count();
|
||||||
TrackList[] rows = null;
|
TrackList[] rows = null;
|
||||||
|
|
||||||
if (request.Action == User.ActionKeyUserRated)
|
if (!doRandomize ?? false)
|
||||||
{
|
{
|
||||||
sortBy = string.IsNullOrEmpty(request.Sort)
|
if (request.Action == User.ActionKeyUserRated)
|
||||||
? request.OrderValue(new Dictionary<string, string> { { "UserTrack.Rating", "DESC" }, { "MediaNumber", "ASC" }, { "TrackNumber", "ASC" } })
|
|
||||||
: request.OrderValue();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (request.Sort == "Rating")
|
|
||||||
{
|
{
|
||||||
// The request is to sort tracks by Rating if the artist only has a few tracks rated then order by those then order by played (put most popular after top rated)
|
sortBy = string.IsNullOrEmpty(request.Sort)
|
||||||
sortBy = request.OrderValue(new Dictionary<string, string> { { "Rating", request.Order }, { "PlayedCount", request.Order } });
|
? request.OrderValue(new Dictionary<string, string> { { "UserTrack.Rating", "DESC" }, { "MediaNumber", "ASC" }, { "TrackNumber", "ASC" } })
|
||||||
|
: request.OrderValue();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sortBy = string.IsNullOrEmpty(request.Sort)
|
if (request.Sort == "Rating")
|
||||||
? request.OrderValue(new Dictionary<string, string> { { "Release.Release.Text", "ASC" }, { "MediaNumber", "ASC" }, { "TrackNumber", "ASC" } })
|
{
|
||||||
: request.OrderValue();
|
// The request is to sort tracks by Rating if the artist only has a few tracks rated then order by those then order by played (put most popular after top rated)
|
||||||
|
sortBy = request.OrderValue(new Dictionary<string, string> { { "Rating", request.Order }, { "PlayedCount", request.Order } });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sortBy = string.IsNullOrEmpty(request.Sort)
|
||||||
|
? request.OrderValue(new Dictionary<string, string> { { "Release.Release.Text", "ASC" }, { "MediaNumber", "ASC" }, { "TrackNumber", "ASC" } })
|
||||||
|
: request.OrderValue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doRandomize ?? false)
|
if (doRandomize ?? false)
|
||||||
{
|
{
|
||||||
rows = TrackList.Shuffle(result).ToArray();
|
var resultData = result.ToArray();
|
||||||
|
rows = (from r in resultData
|
||||||
|
join ra in randomTrackData on r.DatabaseId equals ra.Value
|
||||||
|
orderby ra.Key
|
||||||
|
select r
|
||||||
|
).ToArray();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -640,52 +640,10 @@ namespace Roadie.Api.Services
|
||||||
var userReleases = DbContext.UserReleases.Include(x => x.Release).Where(x => x.UserId == user.Id).ToArray() ?? new data.UserRelease[0];
|
var userReleases = DbContext.UserReleases.Include(x => x.Release).Where(x => x.UserId == user.Id).ToArray() ?? new data.UserRelease[0];
|
||||||
var userTracks = DbContext.UserTracks.Include(x => x.Track).Where(x => x.UserId == user.Id).ToArray() ?? new data.UserTrack[0];
|
var userTracks = DbContext.UserTracks.Include(x => x.Track).Where(x => x.UserId == user.Id).ToArray() ?? new data.UserTrack[0];
|
||||||
|
|
||||||
// This is MySQL specific
|
var mostPlayedArtist = await DbContext.MostPlayedArtist(user.Id);
|
||||||
var sql = @"select a.*
|
var mostPlayedRelease = await DbContext.MostPlayedRelease(user.Id);
|
||||||
FROM `usertrack` ut
|
var lastPlayedTrack = await DbContext.MostPlayedTrack(user.Id);
|
||||||
join `track` t on (ut.trackId = t.id)
|
var mostPlayedTrack = await DbContext.LastPlayedTrack(user.Id);
|
||||||
join `releasemedia` rm on (t.releaseMediaId = rm.id)
|
|
||||||
join `release` r on (rm.releaseId = r.id)
|
|
||||||
join `artist` a on (r.artistId = a.id)
|
|
||||||
where ut.userId = {0}
|
|
||||||
group by r.id
|
|
||||||
order by SUM(ut.playedCount) desc
|
|
||||||
LIMIT 1";
|
|
||||||
var mostPlayedArtist = await DbContext.Artists.FromSqlRaw(sql, user.Id).FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
// This is MySQL specific
|
|
||||||
sql = @"SELECT r.*
|
|
||||||
FROM `usertrack` ut
|
|
||||||
join `track` t on (ut.trackId = t.id)
|
|
||||||
join `releasemedia` rm on (t.releaseMediaId = rm.id)
|
|
||||||
join `release` r on (rm.releaseId = r.id)
|
|
||||||
WHERE ut.userId = {0}
|
|
||||||
GROUP by r.id
|
|
||||||
ORDER by SUM(ut.playedCount) desc
|
|
||||||
LIMIT 1";
|
|
||||||
var mostPlayedRelease = await DbContext.Releases.FromSqlRaw(sql, user.Id).FirstOrDefaultAsync();
|
|
||||||
var mostPlayedTrackUserTrack = userTracks.OrderByDescending(x => x.PlayedCount)
|
|
||||||
.FirstOrDefault();
|
|
||||||
var lastPlayedTrackUserTrack = userTracks.OrderByDescending(x => x.LastPlayed)
|
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
var lastPlayedTrack = lastPlayedTrackUserTrack == null
|
|
||||||
? null
|
|
||||||
: DbContext.Tracks
|
|
||||||
.Include(x => x.TrackArtist)
|
|
||||||
.Include(x => x.ReleaseMedia)
|
|
||||||
.Include("ReleaseMedia.Release")
|
|
||||||
.Include("ReleaseMedia.Release.Artist")
|
|
||||||
.FirstOrDefault(x => x.Id == lastPlayedTrackUserTrack.TrackId);
|
|
||||||
var mostPlayedTrack = mostPlayedTrackUserTrack == null
|
|
||||||
? null
|
|
||||||
: DbContext.Tracks
|
|
||||||
.Include(x => x.TrackArtist)
|
|
||||||
.Include(x => x.ReleaseMedia)
|
|
||||||
.Include("ReleaseMedia.Release")
|
|
||||||
.Include("ReleaseMedia.Release.Artist")
|
|
||||||
.FirstOrDefault(x => x.Id == mostPlayedTrackUserTrack.TrackId);
|
|
||||||
|
|
||||||
model.Statistics = new UserStatistics
|
model.Statistics = new UserStatistics
|
||||||
{
|
{
|
||||||
LastPlayedTrack = lastPlayedTrack == null
|
LastPlayedTrack = lastPlayedTrack == null
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.0.0" />
|
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.0.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="3.1.0" />
|
<PackageReference Include="Serilog.AspNetCore" Version="3.2.0" />
|
||||||
<PackageReference Include="Serilog.Enrichers.Environment" Version="2.1.3" />
|
<PackageReference Include="Serilog.Enrichers.Environment" Version="2.1.3" />
|
||||||
<PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" />
|
<PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" />
|
||||||
<PackageReference Include="Serilog.Exceptions" Version="5.3.1" />
|
<PackageReference Include="Serilog.Exceptions" Version="5.3.1" />
|
||||||
|
|
|
@ -127,7 +127,7 @@ namespace Roadie.Api
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
services.AddDbContextPool<IRoadieDbContext, RoadieDbContext>(
|
services.AddDbContextPool<IRoadieDbContext, MySQLRoadieDbContext>(
|
||||||
options => options.UseMySql(_configuration.GetConnectionString("RoadieDatabaseConnection"),
|
options => options.UseMySql(_configuration.GetConnectionString("RoadieDatabaseConnection"),
|
||||||
mySqlOptions =>
|
mySqlOptions =>
|
||||||
{
|
{
|
||||||
|
@ -173,8 +173,7 @@ namespace Roadie.Api
|
||||||
settings.ConnectionString = _configuration.GetConnectionString("RoadieDatabaseConnection");
|
settings.ConnectionString = _configuration.GetConnectionString("RoadieDatabaseConnection");
|
||||||
|
|
||||||
// This is so 'User Secrets' can be used in Debugging
|
// This is so 'User Secrets' can be used in Debugging
|
||||||
var integrationKeys = _configuration.GetSection("IntegrationKeys")
|
var integrationKeys = _configuration.GetSection("IntegrationKeys").Get<IntegrationKey>();
|
||||||
.Get<IntegrationKey>();
|
|
||||||
if (integrationKeys != null)
|
if (integrationKeys != null)
|
||||||
settings.Integrations.ApiKeys = new List<ApiKey>
|
settings.Integrations.ApiKeys = new List<ApiKey>
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Pomelo.EntityFrameworkCore.MySql.Infrastructure;
|
|
||||||
using Roadie.Api.Services;
|
using Roadie.Api.Services;
|
||||||
using Roadie.Dlna.Server;
|
using Roadie.Dlna.Server;
|
||||||
using Roadie.Library.Caching;
|
using Roadie.Library.Caching;
|
||||||
|
@ -58,18 +56,7 @@ namespace Roadie.Dlna.Services
|
||||||
{
|
{
|
||||||
_authorizer.AddMethod(new UserAgentAuthorizer(Configuration.Dlna.AllowedUserAgents));
|
_authorizer.AddMethod(new UserAgentAuthorizer(Configuration.Dlna.AllowedUserAgents));
|
||||||
}
|
}
|
||||||
var types = new DlnaMediaTypes[] { DlnaMediaTypes.Image, DlnaMediaTypes.Audio };
|
DbContext = data.DbContextFactory.Create(Configuration);
|
||||||
var optionsBuilder = new DbContextOptionsBuilder<data.RoadieDbContext>();
|
|
||||||
optionsBuilder.UseMySql(Configuration.ConnectionString, mySqlOptions =>
|
|
||||||
{
|
|
||||||
mySqlOptions.ServerVersion(new Version(5, 5), ServerType.MariaDb);
|
|
||||||
mySqlOptions.EnableRetryOnFailure(
|
|
||||||
10,
|
|
||||||
TimeSpan.FromSeconds(30),
|
|
||||||
null);
|
|
||||||
});
|
|
||||||
|
|
||||||
DbContext = new data.RoadieDbContext(optionsBuilder.Options);
|
|
||||||
|
|
||||||
var defaultNotFoundImages = new DefaultNotFoundImages(LoggerFactory.CreateLogger("DefaultNotFoundImages"), Configuration);
|
var defaultNotFoundImages = new DefaultNotFoundImages(LoggerFactory.CreateLogger("DefaultNotFoundImages"), Configuration);
|
||||||
var imageService = new ImageService(Configuration, DbContext, CacheManager, LoggerFactory.CreateLogger("ImageService"), defaultNotFoundImages);
|
var imageService = new ImageService(Configuration, DbContext, CacheManager, LoggerFactory.CreateLogger("ImageService"), defaultNotFoundImages);
|
||||||
|
|
13
Roadie.sln
13
Roadie.sln
|
@ -9,19 +9,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Roadie.Library", "Roadie.Ap
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Roadie.Library.Tests", "Roadie.Api.Library.Tests\Roadie.Library.Tests.csproj", "{52E58F4B-88F0-4336-AD06-1184E857FA2C}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Roadie.Library.Tests", "Roadie.Api.Library.Tests\Roadie.Library.Tests.csproj", "{52E58F4B-88F0-4336-AD06-1184E857FA2C}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{1BA7115B-6E37-4546-BBD6-C8B0787A3FE0}"
|
|
||||||
ProjectSection(SolutionItems) = preProject
|
|
||||||
roadie.sql = roadie.sql
|
|
||||||
Upgrade0001.sql = Upgrade0001.sql
|
|
||||||
Upgrade0002.sql = Upgrade0002.sql
|
|
||||||
Upgrade0003.sql = Upgrade0003.sql
|
|
||||||
Upgrade0004.sql = Upgrade0004.sql
|
|
||||||
Upgrade0005.sql = Upgrade0005.sql
|
|
||||||
Upgrade0006.sql = Upgrade0006.sql
|
|
||||||
Upgrade0007.sql = Upgrade0007.sql
|
|
||||||
Upgrade0008.sql = Upgrade0008.sql
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Roadie.Api.Services", "Roadie.Api.Services\Roadie.Api.Services.csproj", "{7B37031E-F2AE-4BE2-9F6F-005CA7A6FDF1}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Roadie.Api.Services", "Roadie.Api.Services\Roadie.Api.Services.csproj", "{7B37031E-F2AE-4BE2-9F6F-005CA7A6FDF1}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Roadie.Api.Hubs", "Roadie.Api.Hubs\Roadie.Api.Hubs.csproj", "{E740C89E-3363-4577-873B-0871823E252C}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Roadie.Api.Hubs", "Roadie.Api.Hubs\Roadie.Api.Hubs.csproj", "{E740C89E-3363-4577-873B-0871823E252C}"
|
||||||
|
|
Loading…
Reference in a new issue