resolves #27; upgraded and reworked several EF statements to work with EF 3

This commit is contained in:
Steven Hildreth 2019-10-23 08:45:36 -05:00
parent a839cf844a
commit 43e20b9e8e
57 changed files with 485 additions and 483 deletions

View file

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework> <TargetFramework>netcoreapp3.0</TargetFramework>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
</PropertyGroup> </PropertyGroup>
@ -21,8 +21,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="2.4.1" /> <PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="2.4.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework> <TargetFramework>netcoreapp3.0</TargetFramework>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
</PropertyGroup> </PropertyGroup>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework> <TargetFramework>netcoreapp3.0</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
@ -19,7 +19,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit" Version="2.4.1" />

View file

@ -16,8 +16,8 @@ namespace Roadie.Library.Configuration
public string Description { get; set; } public string Description { get; set; }
public IEnumerable<string> AllowedIps { get; set; } = Enumerable.Empty<string>(); public IEnumerable<string> AllowedIps { get; set; } = new string[0];
public IEnumerable<string> AllowedUserAgents { get; set; } = Enumerable.Empty<string>(); public IEnumerable<string> AllowedUserAgents { get; set; } = new string[0];
public Dlna() public Dlna()
{ {

View file

@ -26,6 +26,8 @@ namespace Roadie.Library.Data
public string SortNameValue => string.IsNullOrEmpty(SortName) ? Name : SortName; public string SortNameValue => string.IsNullOrEmpty(SortName) ? Name : SortName;
public string GroupBy => SortNameValue.Substring(0, 1).ToUpper();
public static string CacheRegionUrn(Guid Id) public static string CacheRegionUrn(Guid Id)
{ {
return $"urn:artist:{Id}"; return $"urn:artist:{Id}";

View file

@ -10,7 +10,7 @@ using System.Threading.Tasks;
namespace Roadie.Library.Data namespace Roadie.Library.Data
{ {
public interface IRoadieDbContext : IDisposable, IInfrastructure<IServiceProvider>, IDbContextDependencies, IDbSetCache, IDbQueryCache, IDbContextPoolable public interface IRoadieDbContext : 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; }
@ -93,8 +93,6 @@ namespace Roadie.Library.Data
int GetHashCode(); int GetHashCode();
DbQuery<TQuery> Query<TQuery>() where TQuery : class;
EntityEntry Remove(object entity); EntityEntry Remove(object entity);
EntityEntry<TEntity> Remove<TEntity>(TEntity entity) where TEntity : class; EntityEntry<TEntity> Remove<TEntity>(TEntity entity) where TEntity : class;

View file

@ -21,6 +21,8 @@ namespace Roadie.Library.Data
} }
} }
public string GroupBy => Title.Substring(0, 1).ToUpper();
public bool IsCastRecording public bool IsCastRecording
{ {
get get

View file

@ -1,7 +1,10 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
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.Threading;
using System.Threading.Tasks;
namespace Roadie.Library.Data namespace Roadie.Library.Data
{ {
@ -212,5 +215,12 @@ namespace Roadie.Library.Data
// .WithMany(a => a.Tracks) // .WithMany(a => a.Tracks)
// .HasForeignKey(t => t.ArtistId); // .HasForeignKey(t => t.ArtistId);
} }
Task<EntityEntry> IRoadieDbContext.AddAsync(object entity, CancellationToken cancellationToken) => throw new NotImplementedException();
Task<EntityEntry<TEntity>> IRoadieDbContext.AddAsync<TEntity>(TEntity entity, CancellationToken cancellationToken) => throw new NotImplementedException();
Task<TEntity> IRoadieDbContext.FindAsync<TEntity>(params object[] keyValues) => throw new NotImplementedException();
Task<object> IRoadieDbContext.FindAsync(Type entityType, object[] keyValues, CancellationToken cancellationToken) => throw new NotImplementedException();
Task<TEntity> IRoadieDbContext.FindAsync<TEntity>(object[] keyValues, CancellationToken cancellationToken) => throw new NotImplementedException();
Task<object> IRoadieDbContext.FindAsync(Type entityType, params object[] keyValues) => throw new NotImplementedException();
} }
} }

View file

@ -1,7 +1,7 @@
using Microsoft.Net.Http.Headers; using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.Net.Http.Headers;
namespace Roadie.Library namespace Roadie.Library
{ {

View file

@ -136,11 +136,16 @@ namespace Roadie.Library.Imaging
return result.OrderBy(x => x.Name); return result.OrderBy(x => x.Name);
} }
public static string[] GetFiles(string path, string[] patterns = null, public static string[] GetFiles(string path, string[] patterns = null, SearchOption options = SearchOption.TopDirectoryOnly)
SearchOption options = SearchOption.TopDirectoryOnly)
{ {
if (patterns == null || patterns.Length == 0) return Directory.GetFiles(path, "*", options); if (patterns == null || patterns.Length == 0)
if (patterns.Length == 1) return Directory.GetFiles(path, patterns[0], options); {
return Directory.GetFiles(path, "*", options);
}
if (patterns.Length == 1)
{
return Directory.GetFiles(path, patterns[0], options);
}
return patterns.SelectMany(pattern => Directory.GetFiles(path, pattern, options)).Distinct().ToArray(); return patterns.SelectMany(pattern => Directory.GetFiles(path, pattern, options)).Distinct().ToArray();
} }

View file

@ -63,7 +63,7 @@ namespace Roadie.Library.Inspect.Plugins
Logger.LogError(ex); Logger.LogError(ex);
} }
return Enumerable.Empty<AudioMetaData>(); return new AudioMetaData[0];
} }
} }
} }

View file

@ -28,9 +28,13 @@ namespace Roadie.Library.Models
get get
{ {
if (_alternateNamesList == null) if (_alternateNamesList == null)
{
if (!string.IsNullOrEmpty(AlternateNames)) if (!string.IsNullOrEmpty(AlternateNames))
{
_alternateNamesList = AlternateNames.Split('|'); _alternateNamesList = AlternateNames.Split('|');
return _alternateNamesList ?? Enumerable.Empty<string>(); }
}
return _alternateNamesList ?? new string[0];
} }
set => _alternateNamesList = value; set => _alternateNamesList = value;
} }

View file

@ -10,6 +10,6 @@ namespace Roadie.Library.Models.Releases
public short? MediaNumber { get; set; } public short? MediaNumber { get; set; }
public string SubTitle { get; set; } public string SubTitle { get; set; }
public int? TrackCount { get; set; } public int? TrackCount { get; set; }
public IEnumerable<TrackList> Tracks { get; set; } = Enumerable.Empty<TrackList>(); public IEnumerable<TrackList> Tracks { get; set; } = new TrackList[0];
} }
} }

View file

@ -20,11 +20,9 @@ namespace Roadie.Library.Models
public ArtistList Artist { get; set; } public ArtistList Artist { get; set; }
public int? Duration { get; set; } public int? Duration { get; set; }
public string DurationTime => public string DurationTime => Duration.HasValue ? new TimeInfo(Duration.Value).ToFullFormattedString() : "--:--";
Duration.HasValue ? new TimeInfo(Duration.Value).ToFullFormattedString() : "--:--";
public string DurationTimeShort => public string DurationTimeShort => Duration.HasValue ? new TimeInfo(Duration.Value).ToShortFormattedString() : "--:--";
Duration.HasValue ? new TimeInfo(Duration.Value).ToShortFormattedString() : "--:--";
public int? FavoriteCount { get; set; } public int? FavoriteCount { get; set; }
public int? FileSize { get; set; } public int? FileSize { get; set; }
@ -81,7 +79,7 @@ namespace Roadie.Library.Models
{ {
if(tracks == null || !tracks.Any()) if(tracks == null || !tracks.Any())
{ {
return Enumerable.Empty<int>(); ; return new int[0];
} }
return tracks.Select((b, i) => b.Artist?.Artist?.Value == artistId ? i : -1).Where(i => i != -1).ToArray(); return tracks.Select((b, i) => b.Artist?.Artist?.Value == artistId ? i : -1).Where(i => i != -1).ToArray();
} }
@ -90,7 +88,7 @@ namespace Roadie.Library.Models
{ {
if (tracks == null || !tracks.Any()) if (tracks == null || !tracks.Any())
{ {
return Enumerable.Empty<int>(); ; return new int[0];
} }
return tracks.Select((b, i) => b.Release?.Release?.Value == releaseId ? i : -1).Where(i => i != -1).ToArray(); return tracks.Select((b, i) => b.Release?.Release?.Value == releaseId ? i : -1).Where(i => i != -1).ToArray();
} }

View file

@ -12,6 +12,7 @@ namespace Roadie.Library
private List<Exception> _errors; private List<Exception> _errors;
private List<string> _messages; private List<string> _messages;
[XmlIgnore]
public Dictionary<string, object> AdditionalClientData { get; set; } = new Dictionary<string, object>(); public Dictionary<string, object> AdditionalClientData { get; set; } = new Dictionary<string, object>();
[JsonIgnore] [JsonIgnore]

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework> <TargetFramework>netcoreapp3.0</TargetFramework>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Roadie.Library</AssemblyName> <AssemblyName>Roadie.Library</AssemblyName>
<RootNamespace>Roadie.Library</RootNamespace> <RootNamespace>Roadie.Library</RootNamespace>
@ -10,34 +10,35 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AutoCompare.Core" Version="1.0.0" /> <PackageReference Include="AutoCompare.Core" Version="1.0.0" />
<PackageReference Include="CsvHelper" Version="12.1.2" /> <PackageReference Include="CsvHelper" Version="12.1.2" />
<PackageReference Include="EFCore.BulkExtensions" Version="2.6.1" /> <PackageReference Include="EFCore.BulkExtensions" Version="3.0.0" />
<PackageReference Include="FluentFTP" Version="27.1.2" /> <PackageReference Include="FluentFTP" Version="28.0.0" />
<PackageReference Include="Hashids.net" Version="1.2.2" /> <PackageReference Include="Hashids.net" Version="1.2.2" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.12" /> <PackageReference Include="HtmlAgilityPack" Version="1.11.16" />
<PackageReference Include="IdSharp.Common" Version="1.0.1" /> <PackageReference Include="IdSharp.Common" Version="1.0.1" />
<PackageReference Include="IdSharp.Tagging" Version="1.0.0-rc3" /> <PackageReference Include="IdSharp.Tagging" Version="1.0.0-rc3" />
<PackageReference Include="Inflatable.Lastfm" Version="1.1.0.339" /> <PackageReference Include="Inflatable.Lastfm" Version="1.1.0.339" />
<PackageReference Include="LiteDB" Version="4.1.4" /> <PackageReference Include="LiteDB" Version="4.1.4" />
<PackageReference Include="Mapster" Version="4.1.0" /> <PackageReference Include="Mapster" Version="4.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Redis" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.Caching.Redis" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="1.2.2" /> <PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="1.3.0" />
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.0" />
<PackageReference Include="Microsoft.PowerShell.SDK" Version="6.2.3" /> <PackageReference Include="Microsoft.PowerShell.SDK" Version="6.2.3" />
<PackageReference Include="MimeMapping" Version="1.0.1.15" /> <PackageReference Include="MimeMapping" Version="1.0.1.17" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="NodaTime" Version="2.4.7" /> <PackageReference Include="NodaTime" Version="2.4.7" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="2.2.0" /> <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.0.0-rc1.final" />
<PackageReference Include="RestSharp" Version="106.6.10" /> <PackageReference Include="RestSharp" Version="106.6.10" />
<PackageReference Include="SixLabors.Core" Version="1.0.0-beta0006" /> <PackageReference Include="SixLabors.Core" Version="1.0.0-beta0006" />
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.0-beta0005" /> <PackageReference Include="SixLabors.ImageSharp" Version="1.0.0-beta0005" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta0005" /> <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta0005" />
<PackageReference Include="SixLabors.Shapes" Version="1.0.0-beta0007" /> <PackageReference Include="SixLabors.Shapes" Version="1.0.0-beta0007" />
<PackageReference Include="System.Drawing.Common" Version="4.5.1" /> <PackageReference Include="System.Drawing.Common" Version="4.6.0" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="4.5.0" /> <PackageReference Include="System.IO.FileSystem.AccessControl" Version="4.6.0" />
<PackageReference Include="System.Runtime.Caching" Version="4.5.0" /> <PackageReference Include="System.Runtime.Caching" Version="4.6.0" />
<PackageReference Include="z440.atl.core" Version="2.12.0" /> <PackageReference Include="z440.atl.core" Version="2.13.0" />
<PackageReference Include="zlib.net-mutliplatform" Version="1.0.4" /> <PackageReference Include="zlib.net-mutliplatform" Version="1.0.4" />
</ItemGroup> </ItemGroup>

View file

@ -253,10 +253,10 @@ namespace Roadie.Api.Services
FROM `artist` a FROM `artist` a
WHERE(a.id NOT IN(select artistId FROM `userartist` where userId = {1} and isDisliked = 1)) 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) OR(a.id IN(select artistId FROM `userartist` where userId = {1} and isFavorite = 1)
AND {2} = 0) AND {2} = 1)
order BY RIGHT(HEX((1 << 24) * (1 + RAND())), 6) order BY RIGHT(HEX((1 << 24) * (1 + RAND())), 6)
LIMIT 0, {0}"; LIMIT 0, {0}";
randomArtistIds = (from a in DbContext.Artists.FromSql(sql, randomLimit, userId, request.FilterFavoriteOnly ? "1" : "0") randomArtistIds = (from a in DbContext.Artists.FromSqlRaw(sql, randomLimit, userId, request.FilterFavoriteOnly ? "1" : "0")
select a.Id).ToArray(); select a.Id).ToArray();
rowCount = DbContext.Artists.Count(); rowCount = DbContext.Artists.Count();
} }
@ -289,7 +289,7 @@ namespace Roadie.Api.Services
Text = a.Name, Text = a.Name,
Value = a.RoadieId.ToString() Value = a.RoadieId.ToString()
}, },
Thumbnail = MakeArtistThumbnailImage(a.RoadieId), Thumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, a.RoadieId),
Rating = a.Rating, Rating = a.Rating,
Rank = a.Rank, Rank = a.Rank,
CreatedDate = a.CreatedDate, CreatedDate = a.CreatedDate,
@ -916,8 +916,8 @@ namespace Roadie.Api.Services
tsw.Stop(); tsw.Stop();
timings.Add("adapt", tsw.ElapsedMilliseconds); timings.Add("adapt", tsw.ElapsedMilliseconds);
tsw.Restart(); tsw.Restart();
result.Thumbnail = MakeArtistThumbnailImage(id); result.Thumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, id);
result.MediumThumbnail = MakeThumbnailImage(id, "artist", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height); result.MediumThumbnail = MakeThumbnailImage(Configuration, HttpContext, id, "artist", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
result.Genres = artist.Genres.Select(x => new DataToken result.Genres = artist.Genres.Select(x => new DataToken
{ {
Text = x.Genre.Name, Text = x.Genre.Name,
@ -940,7 +940,7 @@ namespace Roadie.Api.Services
.ToArray()) .ToArray())
{ {
var releaseList = release.Adapt<ReleaseList>(); var releaseList = release.Adapt<ReleaseList>();
releaseList.Thumbnail = MakeReleaseThumbnailImage(release.RoadieId); releaseList.Thumbnail = MakeReleaseThumbnailImage(Configuration, HttpContext, release.RoadieId);
var dtoReleaseMedia = new List<ReleaseMediaList>(); var dtoReleaseMedia = new List<ReleaseMediaList>();
if (includes.Contains("tracks")) if (includes.Contains("tracks"))
foreach (var releasemedia in release.Medias.OrderBy(x => x.MediaNumber).ToArray()) foreach (var releasemedia in release.Medias.OrderBy(x => x.MediaNumber).ToArray())
@ -959,7 +959,7 @@ namespace Roadie.Api.Services
var ta = DbContext.Artists.FirstOrDefault(x => x.Id == t.ArtistId.Value); var ta = DbContext.Artists.FirstOrDefault(x => x.Id == t.ArtistId.Value);
if (ta != null) if (ta != null)
trackArtist = ArtistList.FromDataArtist(ta, trackArtist = ArtistList.FromDataArtist(ta,
MakeArtistThumbnailImage(ta.RoadieId)); MakeArtistThumbnailImage(Configuration, HttpContext, ta.RoadieId));
} }
track.TrackArtist = trackArtist; track.TrackArtist = trackArtist;
@ -1023,14 +1023,14 @@ namespace Roadie.Api.Services
{ {
tsw.Restart(); tsw.Restart();
result.Images = DbContext.Images.Where(x => x.ArtistId == artist.Id) result.Images = DbContext.Images.Where(x => x.ArtistId == artist.Id)
.Select(x => MakeFullsizeImage(x.RoadieId, x.Caption)).ToArray(); .Select(x => MakeFullsizeImage(Configuration, HttpContext, x.RoadieId, x.Caption)).ToArray();
var artistFolder = artist.ArtistFileFolder(Configuration); var artistFolder = artist.ArtistFileFolder(Configuration);
var artistImagesInFolder = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(artistFolder), var artistImagesInFolder = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(artistFolder),
ImageType.ArtistSecondary, SearchOption.TopDirectoryOnly); ImageType.ArtistSecondary, SearchOption.TopDirectoryOnly);
if (artistImagesInFolder.Any()) if (artistImagesInFolder.Any())
result.Images = result.Images.Concat(artistImagesInFolder.Select((x, i) => result.Images = result.Images.Concat(artistImagesInFolder.Select((x, i) =>
MakeFullsizeSecondaryImage(id, ImageType.ArtistSecondary, i))); MakeFullsizeSecondaryImage(Configuration, HttpContext, id, ImageType.ArtistSecondary, i)));
tsw.Stop(); tsw.Stop();
timings.Add("images", tsw.ElapsedMilliseconds); timings.Add("images", tsw.ElapsedMilliseconds);
@ -1051,7 +1051,7 @@ namespace Roadie.Api.Services
Text = a.Name, Text = a.Name,
Value = a.RoadieId.ToString() Value = a.RoadieId.ToString()
}, },
Thumbnail = MakeArtistThumbnailImage(a.RoadieId), Thumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, a.RoadieId),
Rating = a.Rating, Rating = a.Rating,
Rank = a.Rank, Rank = a.Rank,
CreatedDate = a.CreatedDate, CreatedDate = a.CreatedDate,
@ -1075,7 +1075,7 @@ namespace Roadie.Api.Services
Text = a.Name, Text = a.Name,
Value = a.RoadieId.ToString() Value = a.RoadieId.ToString()
}, },
Thumbnail = MakeArtistThumbnailImage(a.RoadieId), Thumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, a.RoadieId),
Rating = a.Rating, Rating = a.Rating,
Rank = a.Rank, Rank = a.Rank,
CreatedDate = a.CreatedDate, CreatedDate = a.CreatedDate,
@ -1108,7 +1108,7 @@ namespace Roadie.Api.Services
Text = a.Name, Text = a.Name,
Value = a.RoadieId.ToString() Value = a.RoadieId.ToString()
}, },
Thumbnail = MakeArtistThumbnailImage(a.RoadieId), Thumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, a.RoadieId),
Rating = a.Rating, Rating = a.Rating,
Rank = a.Rank, Rank = a.Rank,
CreatedDate = a.CreatedDate, CreatedDate = a.CreatedDate,
@ -1132,7 +1132,7 @@ namespace Roadie.Api.Services
Text = a.Name, Text = a.Name,
Value = a.RoadieId.ToString() Value = a.RoadieId.ToString()
}, },
Thumbnail = MakeArtistThumbnailImage(a.RoadieId), Thumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, a.RoadieId),
Rating = a.Rating, Rating = a.Rating,
Rank = a.Rank, Rank = a.Rank,
CreatedDate = a.CreatedDate, CreatedDate = a.CreatedDate,
@ -1181,7 +1181,7 @@ namespace Roadie.Api.Services
var comment = artistComment.Adapt<Comment>(); var comment = artistComment.Adapt<Comment>();
comment.DatabaseId = artistComment.Id; comment.DatabaseId = artistComment.Id;
comment.User = UserList.FromDataUser(artistComment.User, comment.User = UserList.FromDataUser(artistComment.User,
MakeUserThumbnailImage(artistComment.User.RoadieId)); MakeUserThumbnailImage(Configuration, HttpContext, artistComment.User.RoadieId));
comment.DislikedCount = userCommentReactions.Count(x => comment.DislikedCount = userCommentReactions.Count(x =>
x.CommentId == artistComment.Id && x.ReactionValue == CommentReaction.Dislike); x.CommentId == artistComment.Id && x.ReactionValue == CommentReaction.Dislike);
comment.LikedCount = userCommentReactions.Count(x => comment.LikedCount = userCommentReactions.Count(x =>
@ -1230,7 +1230,7 @@ namespace Roadie.Api.Services
select r) select r)
.OrderBy(x => x.Title) .OrderBy(x => x.Title)
.ToArray() .ToArray()
.Select(r => ReleaseList.FromDataRelease(r, r.Artist, HttpContext.BaseUrl, MakeArtistThumbnailImage(r.Artist.RoadieId), MakeReleaseThumbnailImage(r.RoadieId))); .Select(r => ReleaseList.FromDataRelease(r, r.Artist, HttpContext.BaseUrl, MakeArtistThumbnailImage(Configuration, HttpContext, r.Artist.RoadieId), MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId)));
result.ArtistContributionReleases = result.ArtistContributionReleases.Any() result.ArtistContributionReleases = result.ArtistContributionReleases.Any()
? result.ArtistContributionReleases ? result.ArtistContributionReleases
@ -1248,7 +1248,7 @@ namespace Roadie.Api.Services
join r in DbContext.Releases on rl.ReleaseId equals r.Id join r in DbContext.Releases on rl.ReleaseId equals r.Id
where r.ArtistId == artist.Id where r.ArtistId == artist.Id
orderby l.SortName orderby l.SortName
select LabelList.FromDataLabel(l, MakeLabelThumbnailImage(l.RoadieId))) select LabelList.FromDataLabel(l, MakeLabelThumbnailImage(Configuration, HttpContext, l.RoadieId)))
.ToArray() .ToArray()
.GroupBy(x => x.Label.Value) .GroupBy(x => x.Label.Value)
.Select(x => x.First()) .Select(x => x.First())
@ -1510,8 +1510,7 @@ namespace Roadie.Api.Services
return new OperationResult<Image> return new OperationResult<Image>
{ {
IsSuccess = !errors.Any(), IsSuccess = !errors.Any(),
Data = MakeThumbnailImage(id, "artist", Configuration.MediumImageSize.Width, Data = MakeThumbnailImage(Configuration, HttpContext, id, "artist", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height, true),
Configuration.MediumImageSize.Height, true),
OperationTime = sw.ElapsedMilliseconds, OperationTime = sw.ElapsedMilliseconds,
Errors = errors Errors = errors
}; };

View file

@ -79,8 +79,8 @@ namespace Roadie.Api.Services
Value = artist.RoadieId.ToString() Value = artist.RoadieId.ToString()
}; };
row.Artist = row.Artist =
models.ArtistList.FromDataArtist(artist, MakeArtistThumbnailImage(artist.RoadieId)); models.ArtistList.FromDataArtist(artist, MakeArtistThumbnailImage(Configuration, HttpContext, artist.RoadieId));
row.Thumbnail = MakeArtistThumbnailImage(artist.RoadieId); row.Thumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, artist.RoadieId);
row.SortName = artist.SortName ?? artist.Name; row.SortName = artist.SortName ?? artist.Name;
break; break;
@ -94,9 +94,9 @@ namespace Roadie.Api.Services
Value = release.RoadieId.ToString() Value = release.RoadieId.ToString()
}; };
row.Release = ReleaseList.FromDataRelease(release, release.Artist, HttpContext.BaseUrl, row.Release = ReleaseList.FromDataRelease(release, release.Artist, HttpContext.BaseUrl,
MakeArtistThumbnailImage(release.Artist.RoadieId), MakeArtistThumbnailImage(Configuration, HttpContext, release.Artist.RoadieId),
MakeReleaseThumbnailImage(release.RoadieId)); MakeReleaseThumbnailImage(Configuration, HttpContext, release.RoadieId));
row.Thumbnail = MakeReleaseThumbnailImage(release.RoadieId); row.Thumbnail = MakeReleaseThumbnailImage(Configuration, HttpContext, release.RoadieId);
row.SortName = release.Title; row.SortName = release.Title;
break; break;
@ -120,14 +120,14 @@ namespace Roadie.Api.Services
track.ReleaseMedia.Release.Artist, track.ReleaseMedia.Release.Artist,
track.TrackArtist, track.TrackArtist,
HttpContext.BaseUrl, HttpContext.BaseUrl,
MakeTrackThumbnailImage(track.RoadieId), MakeTrackThumbnailImage(Configuration, HttpContext, track.RoadieId),
MakeReleaseThumbnailImage(track.ReleaseMedia.Release.RoadieId), MakeReleaseThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.RoadieId),
MakeArtistThumbnailImage(track.ReleaseMedia.Release.Artist.RoadieId), MakeArtistThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.Artist.RoadieId),
MakeArtistThumbnailImage(track.TrackArtist == null MakeArtistThumbnailImage(Configuration, HttpContext, track.TrackArtist == null
? null ? null
: (Guid?)track.TrackArtist.RoadieId)); : (Guid?)track.TrackArtist.RoadieId));
row.Track.TrackPlayUrl = MakeTrackPlayUrl(user, HttpContext.BaseUrl, track.Id, track.RoadieId); row.Track.TrackPlayUrl = MakeTrackPlayUrl(user, HttpContext.BaseUrl, track.Id, track.RoadieId);
row.Thumbnail = MakeTrackThumbnailImage(track.RoadieId); row.Thumbnail = MakeTrackThumbnailImage(Configuration, HttpContext, track.RoadieId);
row.SortName = track.Title; row.SortName = track.Title;
break; break;
@ -142,9 +142,9 @@ namespace Roadie.Api.Services
Value = playlist.RoadieId.ToString() Value = playlist.RoadieId.ToString()
}; };
row.Playlist = PlaylistList.FromDataPlaylist(playlist, playlist.User, row.Playlist = PlaylistList.FromDataPlaylist(playlist, playlist.User,
MakePlaylistThumbnailImage(playlist.RoadieId), MakePlaylistThumbnailImage(Configuration, HttpContext, playlist.RoadieId),
MakeUserThumbnailImage(playlist.User.RoadieId)); MakeUserThumbnailImage(Configuration, HttpContext, playlist.User.RoadieId));
row.Thumbnail = MakePlaylistThumbnailImage(playlist.RoadieId); row.Thumbnail = MakePlaylistThumbnailImage(Configuration, HttpContext, playlist.RoadieId);
row.SortName = playlist.Name; row.SortName = playlist.Name;
break; break;
@ -159,8 +159,8 @@ namespace Roadie.Api.Services
row.Collection = CollectionList.FromDataCollection(collection, row.Collection = CollectionList.FromDataCollection(collection,
(from crc in DbContext.CollectionReleases (from crc in DbContext.CollectionReleases
where crc.CollectionId == collection.Id where crc.CollectionId == collection.Id
select crc.Id).Count(), MakeCollectionThumbnailImage(collection.RoadieId)); select crc.Id).Count(), MakeCollectionThumbnailImage(Configuration, HttpContext, collection.RoadieId));
row.Thumbnail = MakeCollectionThumbnailImage(collection.RoadieId); row.Thumbnail = MakeCollectionThumbnailImage(Configuration, HttpContext, collection.RoadieId);
row.SortName = collection.SortName ?? collection.Name; row.SortName = collection.SortName ?? collection.Name;
break; break;
@ -172,8 +172,8 @@ namespace Roadie.Api.Services
Text = label.Name, Text = label.Name,
Value = label.RoadieId.ToString() Value = label.RoadieId.ToString()
}; };
row.Label = models.LabelList.FromDataLabel(label, MakeLabelThumbnailImage(label.RoadieId)); row.Label = models.LabelList.FromDataLabel(label, MakeLabelThumbnailImage(Configuration, HttpContext, label.RoadieId));
row.Thumbnail = MakeLabelThumbnailImage(label.RoadieId); row.Thumbnail = MakeLabelThumbnailImage(Configuration, HttpContext, label.RoadieId);
row.SortName = label.SortName ?? label.Name; row.SortName = label.SortName ?? label.Name;
break; break;
} }

View file

@ -214,7 +214,7 @@ namespace Roadie.Api.Services
CreatedDate = c.CreatedDate, CreatedDate = c.CreatedDate,
IsLocked = c.IsLocked, IsLocked = c.IsLocked,
LastUpdated = c.LastUpdated, LastUpdated = c.LastUpdated,
Thumbnail = MakeCollectionThumbnailImage(c.RoadieId) Thumbnail = MakeCollectionThumbnailImage(Configuration, HttpContext, c.RoadieId)
}; };
var sortBy = string.IsNullOrEmpty(request.Sort) var sortBy = string.IsNullOrEmpty(request.Sort)
@ -355,8 +355,8 @@ namespace Roadie.Api.Services
result.AlternateNames = collection.AlternateNames; result.AlternateNames = collection.AlternateNames;
result.Tags = collection.Tags; result.Tags = collection.Tags;
result.URLs = collection.URLs; result.URLs = collection.URLs;
result.Thumbnail = MakeCollectionThumbnailImage(collection.RoadieId); result.Thumbnail = MakeCollectionThumbnailImage(Configuration, HttpContext, collection.RoadieId);
result.MediumThumbnail = MakeThumbnailImage(id, "collection", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height); result.MediumThumbnail = MakeThumbnailImage(Configuration, HttpContext, id, "collection", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
result.CollectionFoundCount = (from crc in DbContext.CollectionReleases result.CollectionFoundCount = (from crc in DbContext.CollectionReleases
where crc.CollectionId == collection.Id where crc.CollectionId == collection.Id
select crc.Id).Count(); select crc.Id).Count();
@ -385,7 +385,7 @@ namespace Roadie.Api.Services
select new CollectionRelease select new CollectionRelease
{ {
ListNumber = crc.ListNumber, ListNumber = crc.ListNumber,
Release = ReleaseList.FromDataRelease(r, r.Artist, HttpContext.BaseUrl, MakeArtistThumbnailImage(r.Artist.RoadieId), MakeReleaseThumbnailImage(r.RoadieId)) Release = ReleaseList.FromDataRelease(r, r.Artist, HttpContext.BaseUrl, MakeArtistThumbnailImage(Configuration, HttpContext, r.Artist.RoadieId), MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId))
}).ToArray(); }).ToArray();
tsw.Stop(); tsw.Stop();
timings.Add("releases", tsw.ElapsedMilliseconds); timings.Add("releases", tsw.ElapsedMilliseconds);
@ -439,7 +439,7 @@ namespace Roadie.Api.Services
{ {
var comment = collectionComment.Adapt<Comment>(); var comment = collectionComment.Adapt<Comment>();
comment.DatabaseId = collectionComment.Id; comment.DatabaseId = collectionComment.Id;
comment.User = UserList.FromDataUser(collectionComment.User, MakeUserThumbnailImage(collectionComment.User.RoadieId)); comment.User = UserList.FromDataUser(collectionComment.User, MakeUserThumbnailImage(Configuration, HttpContext, collectionComment.User.RoadieId));
comment.DislikedCount = userCommentReactions.Count(x => x.CommentId == collectionComment.Id && x.ReactionValue == CommentReaction.Dislike); comment.DislikedCount = userCommentReactions.Count(x => x.CommentId == collectionComment.Id && x.ReactionValue == CommentReaction.Dislike);
comment.LikedCount = userCommentReactions.Count(x => x.CommentId == collectionComment.Id && x.ReactionValue == CommentReaction.Like); comment.LikedCount = userCommentReactions.Count(x => x.CommentId == collectionComment.Id && x.ReactionValue == CommentReaction.Like);
comments.Add(comment); comments.Add(comment);

View file

@ -104,7 +104,7 @@ namespace Roadie.Api.Services
FROM `genre` g FROM `genre` g
order BY RIGHT( HEX( (1<<24) * (1+RAND()) ), 6) order BY RIGHT( HEX( (1<<24) * (1+RAND()) ), 6)
LIMIT 0, {0}"; LIMIT 0, {0}";
randomGenreIds = (from l in DbContext.Genres.FromSql(sql, randomLimit) randomGenreIds = (from l in DbContext.Genres.FromSqlRaw(sql, randomLimit)
select l.Id).ToArray(); select l.Id).ToArray();
rowCount = DbContext.Genres.Count(); rowCount = DbContext.Genres.Count();
} }
@ -131,7 +131,7 @@ namespace Roadie.Api.Services
ArtistCount = artistCount, ArtistCount = artistCount,
CreatedDate = g.CreatedDate, CreatedDate = g.CreatedDate,
LastUpdated = g.LastUpdated, LastUpdated = g.LastUpdated,
Thumbnail = MakeGenreThumbnailImage(g.RoadieId) Thumbnail = MakeGenreThumbnailImage(Configuration, HttpContext, g.RoadieId)
}; };
GenreList[] rows; GenreList[] rows;
@ -196,8 +196,8 @@ namespace Roadie.Api.Services
var result = genre.Adapt<Genre>(); var result = genre.Adapt<Genre>();
result.AlternateNames = genre.AlternateNames; result.AlternateNames = genre.AlternateNames;
result.Tags = genre.Tags; result.Tags = genre.Tags;
result.Thumbnail = MakeLabelThumbnailImage(genre.RoadieId); result.Thumbnail = MakeLabelThumbnailImage(Configuration, HttpContext, genre.RoadieId);
result.MediumThumbnail = MakeThumbnailImage(id, "genre", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height); result.MediumThumbnail = MakeThumbnailImage(Configuration, HttpContext, id, "genre", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
tsw.Stop(); tsw.Stop();
timings.Add("adapt", tsw.ElapsedMilliseconds); timings.Add("adapt", tsw.ElapsedMilliseconds);
if (includes != null && includes.Any()) if (includes != null && includes.Any())
@ -264,7 +264,7 @@ namespace Roadie.Api.Services
return new OperationResult<Image> return new OperationResult<Image>
{ {
IsSuccess = !errors.Any(), IsSuccess = !errors.Any(),
Data = MakeThumbnailImage(id, "genre", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height, true), Data = MakeThumbnailImage(Configuration, HttpContext, id, "genre", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height, true),
OperationTime = sw.ElapsedMilliseconds, OperationTime = sw.ElapsedMilliseconds,
Errors = errors Errors = errors
}; };

View file

@ -367,8 +367,7 @@ namespace Roadie.Api.Services
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured)); return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
} }
private FileOperationResult<Image> GenerateFileOperationResult(Guid id, data.Image image, private FileOperationResult<Image> GenerateFileOperationResult(Guid id, data.Image image, EntityTagHeaderValue etag = null, string contentType = "image/jpeg")
EntityTagHeaderValue etag = null, string contentType = "image/jpeg")
{ {
var imageEtag = EtagHelper.GenerateETag(HttpEncoder, image.Bytes); var imageEtag = EtagHelper.GenerateETag(HttpEncoder, image.Bytes);
if (EtagHelper.CompareETag(HttpEncoder, etag, imageEtag)) if (EtagHelper.CompareETag(HttpEncoder, etag, imageEtag))

View file

@ -139,7 +139,7 @@ namespace Roadie.Api.Services
FROM `label` l FROM `label` l
order BY RIGHT( HEX( (1<<24) * (1+RAND()) ), 6) order BY RIGHT( HEX( (1<<24) * (1+RAND()) ), 6)
LIMIT 0, {0}"; LIMIT 0, {0}";
randomLabelIds = (from l in DbContext.Labels.FromSql(sql, randomLimit) randomLabelIds = (from l in DbContext.Labels.FromSqlRaw(sql, randomLimit)
select l.Id).ToArray(); select l.Id).ToArray();
rowCount = DbContext.Labels.Count(); rowCount = DbContext.Labels.Count();
} }
@ -167,7 +167,7 @@ namespace Roadie.Api.Services
ArtistCount = l.ArtistCount, ArtistCount = l.ArtistCount,
ReleaseCount = l.ReleaseCount, ReleaseCount = l.ReleaseCount,
TrackCount = l.TrackCount, TrackCount = l.TrackCount,
Thumbnail = MakeLabelThumbnailImage(l.RoadieId) Thumbnail = MakeLabelThumbnailImage(Configuration, HttpContext, l.RoadieId)
}; };
LabelList[] rows = null; LabelList[] rows = null;
rowCount = rowCount ?? result.Count(); rowCount = rowCount ?? result.Count();
@ -377,8 +377,8 @@ namespace Roadie.Api.Services
result.AlternateNames = label.AlternateNames; result.AlternateNames = label.AlternateNames;
result.Tags = label.Tags; result.Tags = label.Tags;
result.URLs = label.URLs; result.URLs = label.URLs;
result.Thumbnail = MakeLabelThumbnailImage(label.RoadieId); result.Thumbnail = MakeLabelThumbnailImage(Configuration, HttpContext, label.RoadieId);
result.MediumThumbnail = MakeThumbnailImage(id, "label", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height); result.MediumThumbnail = MakeThumbnailImage(Configuration, HttpContext, id, "label", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
tsw.Stop(); tsw.Stop();
timings.Add("adapt", tsw.ElapsedMilliseconds); timings.Add("adapt", tsw.ElapsedMilliseconds);
if (includes != null && includes.Any()) if (includes != null && includes.Any())
@ -430,7 +430,7 @@ namespace Roadie.Api.Services
{ {
var comment = labelComment.Adapt<Comment>(); var comment = labelComment.Adapt<Comment>();
comment.DatabaseId = labelComment.Id; comment.DatabaseId = labelComment.Id;
comment.User = UserList.FromDataUser(labelComment.User, MakeUserThumbnailImage(labelComment.User.RoadieId)); comment.User = UserList.FromDataUser(labelComment.User, MakeUserThumbnailImage(Configuration, HttpContext, labelComment.User.RoadieId));
comment.DislikedCount = userCommentReactions.Count(x => x.CommentId == labelComment.Id && x.ReactionValue == CommentReaction.Dislike); comment.DislikedCount = userCommentReactions.Count(x => x.CommentId == labelComment.Id && x.ReactionValue == CommentReaction.Dislike);
comment.LikedCount = userCommentReactions.Count(x => x.CommentId == labelComment.Id && x.ReactionValue == CommentReaction.Like); comment.LikedCount = userCommentReactions.Count(x => x.CommentId == labelComment.Id && x.ReactionValue == CommentReaction.Like);
comments.Add(comment); comments.Add(comment);
@ -486,8 +486,7 @@ namespace Roadie.Api.Services
return new OperationResult<Image> return new OperationResult<Image>
{ {
IsSuccess = !errors.Any(), IsSuccess = !errors.Any(),
Data = MakeThumbnailImage(id, "label", Configuration.MediumImageSize.Width, Data = MakeThumbnailImage(Configuration, HttpContext, id, "label", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height, true),
Configuration.MediumImageSize.Height, true),
OperationTime = sw.ElapsedMilliseconds, OperationTime = sw.ElapsedMilliseconds,
Errors = errors Errors = errors
}; };

View file

@ -80,10 +80,10 @@ namespace Roadie.Api.Services
releaseArtist, releaseArtist,
trackArtist, trackArtist,
HttpContext.BaseUrl, HttpContext.BaseUrl,
MakeTrackThumbnailImage(t.RoadieId), MakeTrackThumbnailImage(Configuration, HttpContext, t.RoadieId),
MakeReleaseThumbnailImage(r.RoadieId), MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId),
MakeArtistThumbnailImage(releaseArtist.RoadieId), MakeArtistThumbnailImage(Configuration, HttpContext, releaseArtist.RoadieId),
MakeArtistThumbnailImage(trackArtist == null ? null : (Guid?)trackArtist.RoadieId)), MakeArtistThumbnailImage(Configuration, HttpContext, trackArtist == null ? null : (Guid?)trackArtist.RoadieId)),
User = new DataToken User = new DataToken
{ {
Text = u.UserName, Text = u.UserName,
@ -107,10 +107,10 @@ namespace Roadie.Api.Services
UserRating = usertrack.Rating, UserRating = usertrack.Rating,
TrackPlayUrl = $"{HttpContext.BaseUrl}/play/track/{t.RoadieId}.mp3", TrackPlayUrl = $"{HttpContext.BaseUrl}/play/track/{t.RoadieId}.mp3",
ArtistThumbnail = ArtistThumbnail =
MakeArtistThumbnailImage( MakeArtistThumbnailImage(Configuration, HttpContext,
trackArtist != null ? trackArtist.RoadieId : releaseArtist.RoadieId), trackArtist != null ? trackArtist.RoadieId : releaseArtist.RoadieId),
ReleaseThumbnail = MakeReleaseThumbnailImage(r.RoadieId), ReleaseThumbnail = MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId),
UserThumbnail = MakeUserThumbnailImage(u.RoadieId) UserThumbnail = MakeUserThumbnailImage(Configuration, HttpContext, u.RoadieId)
}; };
var sortBy = string.IsNullOrEmpty(request.Sort) var sortBy = string.IsNullOrEmpty(request.Sort)
@ -197,10 +197,10 @@ namespace Roadie.Api.Services
track.ReleaseMedia.Release.Artist, track.ReleaseMedia.Release.Artist,
track.TrackArtist, track.TrackArtist,
HttpContext.BaseUrl, HttpContext.BaseUrl,
MakeTrackThumbnailImage(track.RoadieId), MakeTrackThumbnailImage(Configuration, HttpContext, track.RoadieId),
MakeReleaseThumbnailImage(track.ReleaseMedia.Release.RoadieId), MakeReleaseThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.RoadieId),
MakeArtistThumbnailImage(track.ReleaseMedia.Release.Artist.RoadieId), MakeArtistThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.Artist.RoadieId),
MakeArtistThumbnailImage(track.TrackArtist == null MakeArtistThumbnailImage(Configuration, HttpContext, track.TrackArtist == null
? null ? null
: (Guid?)track.TrackArtist.RoadieId)), : (Guid?)track.TrackArtist.RoadieId)),
User = new DataToken User = new DataToken
@ -208,17 +208,17 @@ namespace Roadie.Api.Services
Text = roadieUser.UserName, Text = roadieUser.UserName,
Value = roadieUser.UserId.ToString() Value = roadieUser.UserId.ToString()
}, },
ArtistThumbnail = MakeArtistThumbnailImage(track.TrackArtist != null ArtistThumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, track.TrackArtist != null
? track.TrackArtist.RoadieId ? track.TrackArtist.RoadieId
: track.ReleaseMedia.Release.Artist.RoadieId), : track.ReleaseMedia.Release.Artist.RoadieId),
PlayedDateDateTime = scrobble.TimePlayed, PlayedDateDateTime = scrobble.TimePlayed,
IsNowPlaying = isNowPlaying, IsNowPlaying = isNowPlaying,
Rating = track.Rating, Rating = track.Rating,
ReleasePlayUrl = $"{HttpContext.BaseUrl}/play/release/{track.ReleaseMedia.Release.RoadieId}", ReleasePlayUrl = $"{HttpContext.BaseUrl}/play/release/{track.ReleaseMedia.Release.RoadieId}",
ReleaseThumbnail = MakeReleaseThumbnailImage(track.ReleaseMedia.Release.RoadieId), ReleaseThumbnail = MakeReleaseThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.RoadieId),
TrackPlayUrl = $"{HttpContext.BaseUrl}/play/track/{track.RoadieId}.mp3", TrackPlayUrl = $"{HttpContext.BaseUrl}/play/track/{track.RoadieId}.mp3",
UserRating = userTrack?.Rating, UserRating = userTrack?.Rating,
UserThumbnail = MakeUserThumbnailImage(roadieUser.UserId) UserThumbnail = MakeUserThumbnailImage(Configuration, HttpContext, roadieUser.UserId)
}; };
try try
{ {

View file

@ -254,9 +254,9 @@ namespace Roadie.Api.Services
TrackCount = pl.TrackCount, TrackCount = pl.TrackCount,
CreatedDate = pl.CreatedDate, CreatedDate = pl.CreatedDate,
LastUpdated = pl.LastUpdated, LastUpdated = pl.LastUpdated,
UserThumbnail = MakeUserThumbnailImage(u.RoadieId), UserThumbnail = MakeUserThumbnailImage(Configuration, HttpContext, u.RoadieId),
Id = pl.RoadieId, Id = pl.RoadieId,
Thumbnail = MakePlaylistThumbnailImage(pl.RoadieId) Thumbnail = MakePlaylistThumbnailImage(Configuration, HttpContext, pl.RoadieId)
}; };
var sortBy = string.IsNullOrEmpty(request.Sort) var sortBy = string.IsNullOrEmpty(request.Sort)
? request.OrderValue(new Dictionary<string, string> { { "Playlist.Text", "ASC" } }) ? request.OrderValue(new Dictionary<string, string> { { "Playlist.Text", "ASC" } })
@ -465,9 +465,9 @@ namespace Roadie.Api.Services
result.Tags = playlist.Tags; result.Tags = playlist.Tags;
result.URLs = playlist.URLs; result.URLs = playlist.URLs;
var maintainer = DbContext.Users.Include(x => x.UserRoles).Include("UserRoles.Role").FirstOrDefault(x => x.Id == playlist.UserId); var maintainer = DbContext.Users.Include(x => x.UserRoles).Include("UserRoles.Role").FirstOrDefault(x => x.Id == playlist.UserId);
result.Maintainer = UserList.FromDataUser(maintainer, MakeUserThumbnailImage(maintainer.RoadieId)); result.Maintainer = UserList.FromDataUser(maintainer, MakeUserThumbnailImage(Configuration, HttpContext, maintainer.RoadieId));
result.Thumbnail = MakePlaylistThumbnailImage(playlist.RoadieId); result.Thumbnail = MakePlaylistThumbnailImage(Configuration, HttpContext, playlist.RoadieId);
result.MediumThumbnail = MakeThumbnailImage(id, "playlist", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height); result.MediumThumbnail = MakeThumbnailImage(Configuration, HttpContext, id, "playlist", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
tsw.Stop(); tsw.Stop();
timings.Add("adapt", tsw.ElapsedMilliseconds); timings.Add("adapt", tsw.ElapsedMilliseconds);
if (includes != null && includes.Any()) if (includes != null && includes.Any())
@ -510,10 +510,10 @@ namespace Roadie.Api.Services
releaseArtist, releaseArtist,
trackArtist, trackArtist,
HttpContext.BaseUrl, HttpContext.BaseUrl,
MakeTrackThumbnailImage(plt.t.RoadieId), MakeTrackThumbnailImage(Configuration, HttpContext, plt.t.RoadieId),
MakeReleaseThumbnailImage(r.RoadieId), MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId),
MakeArtistThumbnailImage(releaseArtist.RoadieId), MakeArtistThumbnailImage(Configuration, HttpContext, releaseArtist.RoadieId),
MakeArtistThumbnailImage(trackArtist == null ? null : (Guid?)trackArtist.RoadieId)) MakeArtistThumbnailImage(Configuration, HttpContext, trackArtist == null ? null : (Guid?)trackArtist.RoadieId))
}).ToArray(); }).ToArray();
tsw.Stop(); tsw.Stop();
timings.Add("tracks", tsw.ElapsedMilliseconds); timings.Add("tracks", tsw.ElapsedMilliseconds);
@ -536,7 +536,7 @@ namespace Roadie.Api.Services
{ {
var comment = playlistComment.Adapt<Comment>(); var comment = playlistComment.Adapt<Comment>();
comment.DatabaseId = playlistComment.Id; comment.DatabaseId = playlistComment.Id;
comment.User = UserList.FromDataUser(playlistComment.User, MakeUserThumbnailImage(playlistComment.User.RoadieId)); comment.User = UserList.FromDataUser(playlistComment.User, MakeUserThumbnailImage(Configuration, HttpContext, playlistComment.User.RoadieId));
comment.DislikedCount = userCommentReactions.Count(x => x.CommentId == playlistComment.Id && x.ReactionValue == CommentReaction.Dislike); comment.DislikedCount = userCommentReactions.Count(x => x.CommentId == playlistComment.Id && x.ReactionValue == CommentReaction.Dislike);
comment.LikedCount = userCommentReactions.Count(x => x.CommentId == playlistComment.Id && x.ReactionValue == CommentReaction.Like); comment.LikedCount = userCommentReactions.Count(x => x.CommentId == playlistComment.Id && x.ReactionValue == CommentReaction.Like);
comments.Add(comment); comments.Add(comment);

View file

@ -475,10 +475,10 @@ namespace Roadie.Api.Services
FROM `release` r FROM `release` r
WHERE (r.id NOT IN (select releaseId FROM `userrelease` where userId = {1} and isDisliked = 1)) 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) OR (r.id IN (select releaseId FROM `userrelease` where userId = {1} and isFavorite = 1)
AND {2} = 0) AND {2} = 1)
order BY RIGHT( HEX( (1<<24) * (1+RAND()) ), 6) order BY RIGHT( HEX( (1<<24) * (1+RAND()) ), 6)
LIMIT 0, {0}"; LIMIT 0, {0}";
randomReleaseIds = (from a in DbContext.Releases.FromSql(sql, randomLimit, userId, request.FilterFavoriteOnly ? "1" : "0") randomReleaseIds = (from a in DbContext.Releases.FromSqlRaw(sql, randomLimit, userId, request.FilterFavoriteOnly ? "1" : "0")
select a.Id).ToArray(); select a.Id).ToArray();
rowCount = DbContext.Releases.Count(); rowCount = DbContext.Releases.Count();
} }
@ -517,7 +517,7 @@ namespace Roadie.Api.Services
Text = r.Title, Text = r.Title,
Value = r.RoadieId.ToString() Value = r.RoadieId.ToString()
}, },
ArtistThumbnail = MakeArtistThumbnailImage(a.RoadieId), ArtistThumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, a.RoadieId),
CreatedDate = r.CreatedDate, CreatedDate = r.CreatedDate,
Duration = r.Duration, Duration = r.Duration,
LastPlayed = r.LastPlayed, LastPlayed = r.LastPlayed,
@ -529,7 +529,7 @@ namespace Roadie.Api.Services
ReleaseDateDateTime = r.ReleaseDate, ReleaseDateDateTime = r.ReleaseDate,
ReleasePlayUrl = $"{HttpContext.BaseUrl}/play/release/{r.RoadieId}", ReleasePlayUrl = $"{HttpContext.BaseUrl}/play/release/{r.RoadieId}",
Status = r.Status, Status = r.Status,
Thumbnail = MakeReleaseThumbnailImage(r.RoadieId), Thumbnail = MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId),
TrackCount = r.TrackCount, TrackCount = r.TrackCount,
TrackPlayedCount = r.PlayedCount TrackPlayedCount = r.PlayedCount
}); });
@ -551,7 +551,7 @@ namespace Roadie.Api.Services
} }
else if (request.FilterToArtistId.HasValue) else if (request.FilterToArtistId.HasValue)
{ {
sortBy = request.OrderValue(new Dictionary<string, string> { { "ReleaseDate", "ASC" }, { "Release.Text", "ASC" } }); sortBy = request.OrderValue(new Dictionary<string, string> { { "ReleaseDateDateTime", "ASC" }, { "Release.Text", "ASC" } });
} }
else else
{ {
@ -574,6 +574,8 @@ namespace Roadie.Api.Services
} }
else else
{ {
sortBy = sortBy.Replace("ReleaseDate ", "ReleaseDateDateTime ");
rows = result rows = result
.OrderBy(sortBy) .OrderBy(sortBy)
.Skip(request.SkipValue) .Skip(request.SkipValue)
@ -689,7 +691,18 @@ namespace Roadie.Api.Services
} }
if (includes != null && includes.Any()) if (includes != null && includes.Any())
{
if (includes.Contains("tracks")) if (includes.Contains("tracks"))
{
var rowIds = rows.Select(x => x.DatabaseId).ToArray();
var userRatingsForResult = (from ut in DbContext.UserTracks.Include(x => x.Track)
join t in DbContext.Tracks on ut.TrackId equals t.Id
join rm in DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id
where rowIds.Contains(rm.ReleaseId)
where ut.UserId == roadieUser.Id
select ut)
.ToArray() ?? new data.UserTrack[0];
foreach (var release in rows) foreach (var release in rows)
{ {
release.Media = DbContext.ReleaseMedias release.Media = DbContext.ReleaseMedias
@ -701,25 +714,30 @@ namespace Roadie.Api.Services
.OrderBy(x => x.MediaNumber) .OrderBy(x => x.MediaNumber)
.ToArray(); .ToArray();
var userRatingsForRelease = (from ut in DbContext.UserTracks Parallel.ForEach(release.Media, (media) =>
join t in DbContext.Tracks on ut.TrackId equals t.Id
join rm in DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id
where rm.ReleaseId == release.DatabaseId
where ut.UserId == roadieUser.Id
select new { trackId = t.RoadieId, ut }).ToArray();
foreach (var userRatingForRelease in userRatingsForRelease)
{ {
var mediaTrack = release.Media?.SelectMany(x => x.Tracks) media.Tracks = media.Tracks.OrderBy(x => x.TrackNumber);
.FirstOrDefault(x => x.Id == userRatingForRelease.trackId); var userTracksForMedia = userRatingsForResult.Where(x => x.Track.ReleaseMediaId == media.DatabaseId).ToArray();
if (mediaTrack != null) if (userTracksForMedia.Any())
mediaTrack.UserRating = new UserTrack {
Parallel.ForEach(userTracksForMedia, (userTrack) =>
{ {
Rating = userRatingForRelease.ut.Rating, var mediaTrack = media.Tracks.FirstOrDefault(x => x.DatabaseId == userTrack.TrackId);
IsFavorite = userRatingForRelease.ut.IsFavorite ?? false, if(mediaTrack != null)
IsDisliked = userRatingForRelease.ut.IsDisliked ?? false {
}; mediaTrack.UserRating = new UserTrack
} {
Rating = userTrack.Rating,
IsFavorite = userTrack.IsFavorite ?? false,
IsDisliked = userTrack.IsDisliked ?? false
};
}
});
}
});
} }
}
}
if (request.FilterFavoriteOnly) rows = rows.OrderBy(x => x.UserRating.Rating).ToArray(); if (request.FilterFavoriteOnly) rows = rows.OrderBy(x => x.UserRating.Rating).ToArray();
sw.Stop(); sw.Stop();
@ -1724,9 +1742,9 @@ namespace Roadie.Api.Services
} }
tsw.Restart(); tsw.Restart();
var result = release.Adapt<Release>(); var result = release.Adapt<Release>();
result.Artist = ArtistList.FromDataArtist(release.Artist, MakeArtistThumbnailImage(release.Artist.RoadieId)); result.Artist = ArtistList.FromDataArtist(release.Artist, MakeArtistThumbnailImage(Configuration, HttpContext, release.Artist.RoadieId));
result.Thumbnail = MakeReleaseThumbnailImage(release.RoadieId); result.Thumbnail = MakeReleaseThumbnailImage(Configuration, HttpContext, release.RoadieId);
result.MediumThumbnail = MakeThumbnailImage(id, "release", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height); result.MediumThumbnail = MakeThumbnailImage(Configuration, HttpContext, id, "release", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
result.ReleasePlayUrl = $"{HttpContext.BaseUrl}/play/release/{release.RoadieId}"; result.ReleasePlayUrl = $"{HttpContext.BaseUrl}/play/release/{release.RoadieId}";
result.Profile = release.Profile; result.Profile = release.Profile;
result.ReleaseDate = release.ReleaseDate.Value; result.ReleaseDate = release.ReleaseDate.Value;
@ -1757,7 +1775,7 @@ namespace Roadie.Api.Services
Text = submission.User.UserName, Text = submission.User.UserName,
Value = submission.User.RoadieId.ToString() Value = submission.User.RoadieId.ToString()
}, },
UserThumbnail = MakeUserThumbnailImage(submission.User.RoadieId), UserThumbnail = MakeUserThumbnailImage(Configuration, HttpContext, submission.User.RoadieId),
SubmittedDate = submission.CreatedDate SubmittedDate = submission.CreatedDate
}; };
} }
@ -1821,7 +1839,7 @@ namespace Roadie.Api.Services
if (includes.Contains("images")) if (includes.Contains("images"))
{ {
tsw.Restart(); tsw.Restart();
var releaseImages = DbContext.Images.Where(x => x.ReleaseId == release.Id).Select(x => MakeFullsizeImage(x.RoadieId, x.Caption)).ToArray(); var releaseImages = DbContext.Images.Where(x => x.ReleaseId == release.Id).Select(x => MakeFullsizeImage(Configuration, HttpContext, x.RoadieId, x.Caption)).ToArray();
if (releaseImages != null && releaseImages.Any()) if (releaseImages != null && releaseImages.Any())
{ {
result.Images = releaseImages; result.Images = releaseImages;
@ -1831,7 +1849,7 @@ namespace Roadie.Api.Services
var releaseImagesInFolder = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(releaseFolder), ImageType.ReleaseSecondary, SearchOption.TopDirectoryOnly); var releaseImagesInFolder = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(releaseFolder), ImageType.ReleaseSecondary, SearchOption.TopDirectoryOnly);
if (releaseImagesInFolder.Any()) if (releaseImagesInFolder.Any())
{ {
result.Images = result.Images.Concat(releaseImagesInFolder.Select((x, i) => MakeFullsizeSecondaryImage(id, ImageType.ReleaseSecondary, i))); result.Images = result.Images.Concat(releaseImagesInFolder.Select((x, i) => MakeFullsizeSecondaryImage(Configuration, HttpContext, id, ImageType.ReleaseSecondary, i)));
} }
tsw.Stop(); tsw.Stop();
timings.Add("images", tsw.ElapsedMilliseconds); timings.Add("images", tsw.ElapsedMilliseconds);
@ -1888,7 +1906,7 @@ namespace Roadie.Api.Services
ArtistCount = releaseLabel.l.ArtistCount, ArtistCount = releaseLabel.l.ArtistCount,
ReleaseCount = releaseLabel.l.ReleaseCount, ReleaseCount = releaseLabel.l.ReleaseCount,
TrackCount = releaseLabel.l.TrackCount, TrackCount = releaseLabel.l.TrackCount,
Thumbnail = MakeLabelThumbnailImage(releaseLabel.l.RoadieId) Thumbnail = MakeLabelThumbnailImage(Configuration, HttpContext, releaseLabel.l.RoadieId)
} }
}; };
labels.Add(rl); labels.Add(rl);
@ -1933,7 +1951,7 @@ namespace Roadie.Api.Services
CreatedDate = releaseCollection.Collection.CreatedDate, CreatedDate = releaseCollection.Collection.CreatedDate,
IsLocked = releaseCollection.Collection.IsLocked, IsLocked = releaseCollection.Collection.IsLocked,
LastUpdated = releaseCollection.Collection.LastUpdated, LastUpdated = releaseCollection.Collection.LastUpdated,
Thumbnail = MakeCollectionThumbnailImage(releaseCollection.Collection.RoadieId) Thumbnail = MakeCollectionThumbnailImage(Configuration, HttpContext, releaseCollection.Collection.RoadieId)
}, },
ListNumber = releaseCollection.ListNumber ListNumber = releaseCollection.ListNumber
}); });
@ -1962,7 +1980,7 @@ namespace Roadie.Api.Services
{ {
var comment = releaseComment.Adapt<Comment>(); var comment = releaseComment.Adapt<Comment>();
comment.DatabaseId = releaseComment.Id; comment.DatabaseId = releaseComment.Id;
comment.User = UserList.FromDataUser(releaseComment.User, MakeUserThumbnailImage(releaseComment.User.RoadieId)); comment.User = UserList.FromDataUser(releaseComment.User, MakeUserThumbnailImage(Configuration, HttpContext, releaseComment.User.RoadieId));
comment.DislikedCount = userCommentReactions.Count(x => x.CommentId == releaseComment.Id && x.ReactionValue == CommentReaction.Dislike); comment.DislikedCount = userCommentReactions.Count(x => x.CommentId == releaseComment.Id && x.ReactionValue == CommentReaction.Dislike);
comment.LikedCount = userCommentReactions.Count(x => x.CommentId == releaseComment.Id && x.ReactionValue == CommentReaction.Like); comment.LikedCount = userCommentReactions.Count(x => x.CommentId == releaseComment.Id && x.ReactionValue == CommentReaction.Like);
comments.Add(comment); comments.Add(comment);
@ -1993,7 +2011,7 @@ namespace Roadie.Api.Services
t.Status = track.Status; t.Status = track.Status;
t.TrackArtist = track.TrackArtist != null t.TrackArtist = track.TrackArtist != null
? ArtistList.FromDataArtist(track.TrackArtist, ? ArtistList.FromDataArtist(track.TrackArtist,
MakeArtistThumbnailImage(track.TrackArtist.RoadieId)) MakeArtistThumbnailImage(Configuration, HttpContext, track.TrackArtist.RoadieId))
: null; : null;
rmTracks.Add(t); rmTracks.Add(t);
} }
@ -2054,8 +2072,7 @@ namespace Roadie.Api.Services
return new OperationResult<Image> return new OperationResult<Image>
{ {
IsSuccess = !errors.Any(), IsSuccess = !errors.Any(),
Data = MakeThumbnailImage(id, "release", Configuration.MediumImageSize.Width, Data = MakeThumbnailImage(Configuration, HttpContext, id, "release", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height, true),
Configuration.MediumImageSize.Height, true),
OperationTime = sw.ElapsedMilliseconds, OperationTime = sw.ElapsedMilliseconds,
Errors = errors Errors = errors
}; };

View file

@ -1,16 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework> <TargetFramework>netcoreapp3.0</TargetFramework>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Hashids.net" Version="1.2.2" /> <PackageReference Include="Hashids.net" Version="1.2.2" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="2.2.5" /> <PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="3.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.5.0" /> <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.6.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.19" /> <PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.19" />
</ItemGroup> </ItemGroup>

View file

@ -87,9 +87,9 @@ namespace Roadie.Api.Services
return token; return token;
} }
public Image MakeThumbnailImage(Guid id, string type, int? width = null, int? height = null, bool includeCachebuster = false) public static Image MakeThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id, string type, int? width = null, int? height = null, bool includeCachebuster = false)
{ {
return MakeImage(id, type, width ?? Configuration.ThumbnailImageSize.Width, height ?? Configuration.ThumbnailImageSize.Height, null, includeCachebuster); return MakeImage(configuration, httpContext, id, type, width ?? configuration.ThumbnailImageSize.Width, height ?? configuration.ThumbnailImageSize.Height, null, includeCachebuster);
} }
protected IEnumerable<int> ArtistIdsForRelease(int releaseId) protected IEnumerable<int> ArtistIdsForRelease(int releaseId)
@ -227,56 +227,65 @@ namespace Roadie.Api.Services
}, ApplicationUser.CacheRegionUrn(id.Value)); }, ApplicationUser.CacheRegionUrn(id.Value));
} }
protected Image MakeArtistThumbnailImage(Guid? id) protected static Image MakeArtistThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid? id)
{ {
if (!id.HasValue) return null; if (!id.HasValue) return null;
return MakeThumbnailImage(id.Value, "artist"); return MakeThumbnailImage(configuration, httpContext, id.Value, "artist");
} }
protected Image MakeCollectionThumbnailImage(Guid id) protected static Image MakeCollectionThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
{ {
return MakeThumbnailImage(id, "collection"); return MakeThumbnailImage(configuration, httpContext, id, "collection");
} }
protected Image MakeFullsizeImage(Guid id, string caption = null) protected static Image MakeFullsizeImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id, string caption = null)
{ {
return new Image($"{HttpContext.ImageBaseUrl}/{id}", caption, return new Image($"{httpContext.ImageBaseUrl}/{id}", caption,
$"{HttpContext.ImageBaseUrl}/{id}/{Configuration.SmallImageSize.Width}/{Configuration.SmallImageSize.Height}"); $"{httpContext.ImageBaseUrl}/{id}/{configuration.SmallImageSize.Width}/{configuration.SmallImageSize.Height}");
} }
protected Image MakeFullsizeSecondaryImage(Guid id, ImageType type, int imageId, string caption = null) protected static Image MakeFullsizeSecondaryImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id, ImageType type, int imageId, string caption = null)
{ {
if (type == ImageType.ArtistSecondary) if (type == ImageType.ArtistSecondary)
{ {
return new Image($"{HttpContext.ImageBaseUrl}/artist-secondary/{id}/{imageId}", caption, return new Image($"{httpContext.ImageBaseUrl}/artist-secondary/{id}/{imageId}", caption,
$"{HttpContext.ImageBaseUrl}/artist-secondary/{id}/{imageId}/{Configuration.SmallImageSize.Width}/{Configuration.SmallImageSize.Height}"); $"{httpContext.ImageBaseUrl}/artist-secondary/{id}/{imageId}/{configuration.SmallImageSize.Width}/{configuration.SmallImageSize.Height}");
} }
return new Image($"{HttpContext.ImageBaseUrl}/release-secondary/{id}/{imageId}", caption, return new Image($"{httpContext.ImageBaseUrl}/release-secondary/{id}/{imageId}", caption,
$"{HttpContext.ImageBaseUrl}/release-secondary/{id}/{imageId}/{Configuration.SmallImageSize.Width}/{Configuration.SmallImageSize.Height}"); $"{httpContext.ImageBaseUrl}/release-secondary/{id}/{imageId}/{configuration.SmallImageSize.Width}/{configuration.SmallImageSize.Height}");
} }
protected Image MakeGenreThumbnailImage(Guid id) protected static Image MakeGenreThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
{ {
return MakeThumbnailImage(id, "genre"); return MakeThumbnailImage(configuration, httpContext, id, "genre");
} }
protected Image MakeImage(Guid id, int width = 200, int height = 200, string caption = null, protected static Image MakeImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id, int width = 200, int height = 200, string caption = null, bool includeCachebuster = false)
bool includeCachebuster = false)
{ {
return new Image( return new Image(
$"{HttpContext.ImageBaseUrl}/{id}/{width}/{height}/{(includeCachebuster ? DateTime.UtcNow.Ticks.ToString() : string.Empty)}", $"{httpContext.ImageBaseUrl}/{id}/{width}/{height}/{(includeCachebuster ? DateTime.UtcNow.Ticks.ToString() : string.Empty)}",
caption, caption,
$"{HttpContext.ImageBaseUrl}/{id}/{Configuration.SmallImageSize.Width}/{Configuration.SmallImageSize.Height}"); $"{httpContext.ImageBaseUrl}/{id}/{configuration.SmallImageSize.Width}/{configuration.SmallImageSize.Height}");
} }
protected Image MakeImage(Guid id, string type, IImageSize imageSize) protected static Image MakeImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id, string type, IImageSize imageSize)
{ {
return MakeImage(id, type, imageSize.Width, imageSize.Height); return MakeImage(configuration, httpContext, id, type, imageSize.Width, imageSize.Height);
}
private static Image MakeImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id, string type, int? width, int? height, string caption = null, bool includeCachebuster = false)
{
if (width.HasValue && height.HasValue && (width.Value != configuration.ThumbnailImageSize.Width ||
height.Value != configuration.ThumbnailImageSize.Height))
return new Image(
$"{httpContext.ImageBaseUrl}/{type}/{id}/{width}/{height}/{(includeCachebuster ? DateTime.UtcNow.Ticks.ToString() : string.Empty)}",
caption,
$"{httpContext.ImageBaseUrl}/{type}/{id}/{configuration.ThumbnailImageSize.Width}/{configuration.ThumbnailImageSize.Height}");
return new Image($"{httpContext.ImageBaseUrl}/{type}/{id}", caption, null);
} }
protected Image MakeLabelThumbnailImage(Guid id) protected static Image MakeLabelThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
{ {
return MakeThumbnailImage(id, "label"); return MakeThumbnailImage(configuration, httpContext, id, "label");
} }
protected string MakeLastFmUrl(string artistName, string releaseTitle) protected string MakeLastFmUrl(string artistName, string releaseTitle)
@ -289,24 +298,24 @@ namespace Roadie.Api.Services
return new Image($"{HttpContext.ImageBaseUrl}/{type}.jpg", null, null); return new Image($"{HttpContext.ImageBaseUrl}/{type}.jpg", null, null);
} }
protected Image MakePlaylistThumbnailImage(Guid id) protected static Image MakePlaylistThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
{ {
return MakeThumbnailImage(id, "playlist"); return MakeThumbnailImage(configuration, httpContext, id, "playlist");
} }
protected Image MakeReleaseThumbnailImage(Guid id) protected static Image MakeReleaseThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
{ {
return MakeThumbnailImage(id, "release"); return MakeThumbnailImage(configuration, httpContext, id, "release");
} }
protected Image MakeTrackThumbnailImage(Guid id) protected static Image MakeTrackThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
{ {
return MakeThumbnailImage(id, "track"); return MakeThumbnailImage(configuration, httpContext, id, "track");
} }
protected Image MakeUserThumbnailImage(Guid id) protected static Image MakeUserThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
{ {
return MakeThumbnailImage(id, "user"); return MakeThumbnailImage(configuration, httpContext, id, "user");
} }
protected async Task<OperationResult<short>> SetArtistRating(Guid artistId, ApplicationUser user, short rating) protected async Task<OperationResult<short>> SetArtistRating(Guid artistId, ApplicationUser user, short rating)
@ -932,16 +941,6 @@ namespace Roadie.Api.Services
} }
} }
private Image MakeImage(Guid id, string type, int? width, int? height, string caption = null,
bool includeCachebuster = false)
{
if (width.HasValue && height.HasValue && (width.Value != Configuration.ThumbnailImageSize.Width ||
height.Value != Configuration.ThumbnailImageSize.Height))
return new Image(
$"{HttpContext.ImageBaseUrl}/{type}/{id}/{width}/{height}/{(includeCachebuster ? DateTime.UtcNow.Ticks.ToString() : string.Empty)}",
caption,
$"{HttpContext.ImageBaseUrl}/{type}/{id}/{Configuration.ThumbnailImageSize.Width}/{Configuration.ThumbnailImageSize.Height}");
return new Image($"{HttpContext.ImageBaseUrl}/{type}/{id}", caption, null);
}
} }
} }

View file

@ -498,11 +498,11 @@ namespace Roadie.Api.Services
Item = new subsonic.AlbumInfo Item = new subsonic.AlbumInfo
{ {
largeImageUrl = largeImageUrl =
MakeImage(release.RoadieId, "release", Configuration.LargeImageSize).Url, MakeImage(Configuration, HttpContext, release.RoadieId, "release", Configuration.LargeImageSize).Url,
mediumImageUrl = MakeImage(release.RoadieId, "release", Configuration.MediumImageSize) mediumImageUrl = MakeImage(Configuration, HttpContext, release.RoadieId, "release", Configuration.MediumImageSize)
.Url, .Url,
smallImageUrl = smallImageUrl =
MakeImage(release.RoadieId, "release", Configuration.SmallImageSize).Url, MakeImage(Configuration, HttpContext, release.RoadieId, "release", Configuration.SmallImageSize).Url,
lastFmUrl = MakeLastFmUrl(release.Artist.Name, release.Title), lastFmUrl = MakeLastFmUrl(release.Artist.Name, release.Title),
musicBrainzId = release.MusicBrainzId, musicBrainzId = release.MusicBrainzId,
notes = release.Profile notes = release.Profile
@ -1940,7 +1940,7 @@ namespace Roadie.Api.Services
{ {
id = subsonic.Request.CollectionIdentifier + c.RoadieId, id = subsonic.Request.CollectionIdentifier + c.RoadieId,
name = c.Name, name = c.Name,
artistImageUrl = MakeCollectionThumbnailImage(c.RoadieId).Url, artistImageUrl = MakeCollectionThumbnailImage(Configuration, HttpContext, c.RoadieId).Url,
averageRating = 0, averageRating = 0,
userRating = 0 userRating = 0
}).ToArray() }).ToArray()
@ -2071,7 +2071,7 @@ namespace Roadie.Api.Services
{ {
id = subsonic.Request.ArtistIdIdentifier + artist.Artist.Value, id = subsonic.Request.ArtistIdIdentifier + artist.Artist.Value,
name = artist.Artist.Text, name = artist.Artist.Text,
artistImageUrl = MakeArtistThumbnailImage(artist.Id).Url, artistImageUrl = MakeArtistThumbnailImage(Configuration, HttpContext, artist.Id).Url,
averageRating = artist.Rating ?? 0, averageRating = artist.Rating ?? 0,
averageRatingSpecified = true, averageRatingSpecified = true,
starred = artist.UserRating?.RatedDate ?? DateTime.UtcNow, starred = artist.UserRating?.RatedDate ?? DateTime.UtcNow,
@ -2083,7 +2083,7 @@ namespace Roadie.Api.Services
private subsonic.ArtistID3 SubsonicArtistID3ForArtist(ArtistList artist) private subsonic.ArtistID3 SubsonicArtistID3ForArtist(ArtistList artist)
{ {
var artistImageUrl = MakeArtistThumbnailImage(artist.Id).Url; var artistImageUrl = MakeArtistThumbnailImage(Configuration, HttpContext, artist.Id).Url;
return new subsonic.ArtistID3 return new subsonic.ArtistID3
{ {
id = subsonic.Request.ArtistIdIdentifier + artist.Artist.Value, id = subsonic.Request.ArtistIdIdentifier + artist.Artist.Value,
@ -2107,11 +2107,11 @@ namespace Roadie.Api.Services
return new subsonic.ArtistInfo2 return new subsonic.ArtistInfo2
{ {
biography = artist.BioContext, biography = artist.BioContext,
largeImageUrl = MakeImage(artist.RoadieId, "artist", Configuration.LargeImageSize).Url, largeImageUrl = MakeImage(Configuration, HttpContext, artist.RoadieId, "artist", Configuration.LargeImageSize).Url,
mediumImageUrl = MakeImage(artist.RoadieId, "artist", Configuration.MediumImageSize).Url, mediumImageUrl = MakeImage(Configuration, HttpContext, artist.RoadieId, "artist", Configuration.MediumImageSize).Url,
musicBrainzId = artist.MusicBrainzId, musicBrainzId = artist.MusicBrainzId,
similarArtist = new subsonic.ArtistID3[0], similarArtist = new subsonic.ArtistID3[0],
smallImageUrl = MakeImage(artist.RoadieId, "artist", Configuration.SmallImageSize).Url smallImageUrl = MakeImage(Configuration, HttpContext, artist.RoadieId, "artist", Configuration.SmallImageSize).Url
}; };
} }
@ -2120,11 +2120,11 @@ namespace Roadie.Api.Services
return new subsonic.ArtistInfo return new subsonic.ArtistInfo
{ {
biography = artist.BioContext, biography = artist.BioContext,
largeImageUrl = MakeImage(artist.RoadieId, "artist", Configuration.LargeImageSize).Url, largeImageUrl = MakeImage(Configuration, HttpContext, artist.RoadieId, "artist", Configuration.LargeImageSize).Url,
mediumImageUrl = MakeImage(artist.RoadieId, "artist", Configuration.MediumImageSize).Url, mediumImageUrl = MakeImage(Configuration, HttpContext, artist.RoadieId, "artist", Configuration.MediumImageSize).Url,
musicBrainzId = artist.MusicBrainzId, musicBrainzId = artist.MusicBrainzId,
similarArtist = new subsonic.Artist[0], similarArtist = new subsonic.Artist[0],
smallImageUrl = MakeImage(artist.RoadieId, "artist", Configuration.SmallImageSize).Url smallImageUrl = MakeImage(Configuration, HttpContext, artist.RoadieId, "artist", Configuration.SmallImageSize).Url
}; };
} }
@ -2137,7 +2137,7 @@ namespace Roadie.Api.Services
private subsonic.ArtistWithAlbumsID3 SubsonicArtistWithAlbumsID3ForArtist(ArtistList artist, private subsonic.ArtistWithAlbumsID3 SubsonicArtistWithAlbumsID3ForArtist(ArtistList artist,
subsonic.AlbumID3[] releases) subsonic.AlbumID3[] releases)
{ {
var artistImageUrl = MakeArtistThumbnailImage(artist.Id).Url; var artistImageUrl = MakeArtistThumbnailImage(Configuration, HttpContext, artist.Id).Url;
return new subsonic.ArtistWithAlbumsID3 return new subsonic.ArtistWithAlbumsID3
{ {
id = subsonic.Request.ArtistIdIdentifier + artist.Artist.Value, id = subsonic.Request.ArtistIdIdentifier + artist.Artist.Value,
@ -2290,7 +2290,7 @@ namespace Roadie.Api.Services
{ {
return new subsonic.PlaylistWithSongs return new subsonic.PlaylistWithSongs
{ {
coverArt = MakePlaylistThumbnailImage(playlist.Id).Url, coverArt = MakePlaylistThumbnailImage(Configuration, HttpContext, playlist.Id).Url,
allowedUser = playlist.IsPublic ? AllowedUsers() : null, allowedUser = playlist.IsPublic ? AllowedUsers() : null,
changed = playlist.LastUpdated ?? playlist.CreatedDate ?? DateTime.UtcNow, changed = playlist.LastUpdated ?? playlist.CreatedDate ?? DateTime.UtcNow,
created = playlist.CreatedDate ?? DateTime.UtcNow, created = playlist.CreatedDate ?? DateTime.UtcNow,

View file

@ -290,58 +290,37 @@ namespace Roadie.Api.Services
var randomLimit = roadieUser?.RandomReleaseLimit ?? request.LimitValue; var randomLimit = roadieUser?.RandomReleaseLimit ?? request.LimitValue;
var userId = roadieUser?.Id ?? -1; var userId = roadieUser?.Id ?? -1;
// Select random tracks that are not disliked Artist, Release or Track by user. // This is MySQL specific but I can't figure out how else to get random without throwing EF local evaluate warnings.
var dislikedArtistIds = (from ua in DbContext.UserArtists var sql = @"SELECT t.id
where ua.UserId == userId FROM `track` t
where ua.IsDisliked == true # Artist is not disliked
select ua.ArtistId).ToArray(); WHERE ((t.id NOT IN (select tt.id
var dislikedReleaseIds = (from ur in DbContext.UserReleases FROM `track` tt
where ur.UserId == userId JOIN `releasemedia` rm on (tt.releaseMediaId = rm.id)
where ur.IsDisliked == true JOIN `userartist` ua on (rm.id = ua.artistId)
select ur.ReleaseId).ToArray(); WHERE ua.userId = {1} AND ua.isDisliked = 1))
var dislikedTrackIds = (from ut in DbContext.UserTracks # Release is not disliked
where ut.UserId == userId AND (t.id NOT IN (select tt.id
where ut.IsDisliked == true FROM `track` tt
select ut.TrackId).ToArray(); JOIN `releasemedia` rm on (tt.releaseMediaId = rm.id)
int[] favoritedTrackIds = null; JOIN `userrelease` ur on (rm.releaseId = ur.releaseId)
if (request.FilterFavoriteOnly) WHERE ur.userId = {1} AND ur.isDisliked = 1))
{ # Track is not disliked
favoritedTrackIds = (from ut in DbContext.UserTracks AND (t.id NOT IN (select tt.id
where ut.UserId == userId FROM `track` tt
where ut.IsFavorite == true JOIN `usertrack` ut on (tt.id = ut.trackId)
select ut.TrackId).ToArray(); WHERE ut.userId = {1} AND ut.isDisliked = 1)))
favoriteTrackIds = new int[0].AsQueryable(); # If toggled then only favorites
request.FilterFavoriteOnly = false; OR (t.id IN (select tt.id
} FROM `track` tt
randomTrackIds = (from t in DbContext.Tracks JOIN `usertrack` ut on (tt.id = ut.trackId)
join rm in DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id WHERE ut.userId = {1} AND ut.isFavorite = 1) AND {2} = 1)
join r in DbContext.Releases on rm.ReleaseId equals r.Id order BY RIGHT( HEX( (1<<24) * (1+RAND()) ), 6)
join a in DbContext.Artists on r.ArtistId equals a.Id LIMIT 0, {0};";
where !request.FilterRatedOnly || request.FilterRatedOnly && t.Rating > 0 randomTrackIds = (from a in DbContext.Releases.FromSqlRaw(sql, randomLimit, userId, request.FilterFavoriteOnly ? "1" : "0")
where !dislikedArtistIds.Contains(r.ArtistId) select a.Id).ToArray();
where !dislikedArtistIds.Contains(t.ArtistId ?? 0) rowCount = DbContext.Releases.Count();
where !dislikedReleaseIds.Contains(r.Id)
where !dislikedTrackIds.Contains(t.Id)
where favoritedTrackIds == null || favoritedTrackIds.Contains(t.Id)
where t.Hash != null
select new TrackList
{
DatabaseId = t.Id,
Artist = new ArtistList
{
Artist = new DataToken { Value = a.RoadieId.ToString(), Text = a.Name }
},
Release = new ReleaseList
{
Release = new DataToken { Value = r.RoadieId.ToString(), Text = r.Title }
}
})
.OrderBy(x => x.Artist.RandomSortId)
.ThenBy(x => x.RandomSortId)
.ThenBy(x => x.RandomSortId)
.Take(randomLimit)
.Select(x => x.DatabaseId)
.ToArray();
} }
Guid?[] filterToTrackIds = null; Guid?[] filterToTrackIds = null;
@ -438,7 +417,7 @@ namespace Roadie.Api.Services
Text = r.Title, Text = r.Title,
Value = r.RoadieId.ToString() Value = r.RoadieId.ToString()
}, },
ArtistThumbnail = MakeArtistThumbnailImage(releaseArtist.RoadieId), ArtistThumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, releaseArtist.RoadieId),
CreatedDate = r.CreatedDate, CreatedDate = r.CreatedDate,
Duration = r.Duration, Duration = r.Duration,
LastPlayed = r.LastPlayed, LastPlayed = r.LastPlayed,
@ -450,7 +429,7 @@ namespace Roadie.Api.Services
ReleaseDateDateTime = r.ReleaseDate, ReleaseDateDateTime = r.ReleaseDate,
ReleasePlayUrl = $"{HttpContext.BaseUrl}/play/release/{r.RoadieId}", ReleasePlayUrl = $"{HttpContext.BaseUrl}/play/release/{r.RoadieId}",
Status = r.Status, Status = r.Status,
Thumbnail = MakeReleaseThumbnailImage(r.RoadieId), Thumbnail = MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId),
TrackCount = r.TrackCount, TrackCount = r.TrackCount,
TrackPlayedCount = r.PlayedCount TrackPlayedCount = r.PlayedCount
}, },
@ -471,7 +450,7 @@ namespace Roadie.Api.Services
ReleaseCount = trackArtist.ReleaseCount, ReleaseCount = trackArtist.ReleaseCount,
TrackCount = trackArtist.TrackCount, TrackCount = trackArtist.TrackCount,
SortName = trackArtist.SortName, SortName = trackArtist.SortName,
Thumbnail = MakeArtistThumbnailImage(trackArtist.RoadieId) Thumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, trackArtist.RoadieId)
}, },
ra = new ArtistList ra = new ArtistList
{ {
@ -488,7 +467,7 @@ namespace Roadie.Api.Services
ReleaseCount = releaseArtist.ReleaseCount, ReleaseCount = releaseArtist.ReleaseCount,
TrackCount = releaseArtist.TrackCount, TrackCount = releaseArtist.TrackCount,
SortName = releaseArtist.SortName, SortName = releaseArtist.SortName,
Thumbnail = MakeArtistThumbnailImage(releaseArtist.RoadieId) Thumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, releaseArtist.RoadieId)
} }
}; };
@ -526,12 +505,10 @@ namespace Roadie.Api.Services
Rating = x.ti.Rating, Rating = x.ti.Rating,
Release = x.rl, Release = x.rl,
ReleaseDate = x.rl.ReleaseDateDateTime, ReleaseDate = x.rl.ReleaseDateDateTime,
Thumbnail = MakeTrackThumbnailImage(x.ti.RoadieId), Thumbnail = MakeTrackThumbnailImage(Configuration, HttpContext, x.ti.RoadieId),
Title = x.ti.Title, Title = x.ti.Title,
TrackArtist = x.ta, TrackArtist = x.ta,
TrackNumber = playListTrackPositions.ContainsKey(x.ti.Id) TrackNumber = x.ti.TrackNumber,
? playListTrackPositions[x.ti.Id]
: x.ti.TrackNumber,
TrackPlayUrl = MakeTrackPlayUrl(user, HttpContext.BaseUrl, x.ti.Id, x.ti.RoadieId) TrackPlayUrl = MakeTrackPlayUrl(user, HttpContext.BaseUrl, x.ti.Id, x.ti.RoadieId)
}); });
string sortBy = null; string sortBy = null;
@ -572,7 +549,6 @@ namespace Roadie.Api.Services
.Take(request.LimitValue) .Take(request.LimitValue)
.ToArray(); .ToArray();
} }
if (rows.Any() && roadieUser != null) if (rows.Any() && roadieUser != null)
{ {
var rowIds = rows.Select(x => x.DatabaseId).ToArray(); var rowIds = rows.Select(x => x.DatabaseId).ToArray();
@ -658,9 +634,15 @@ namespace Roadie.Api.Services
foreach (var row in rows) foreach (var row in rows)
{ {
row.FavoriteCount = favoriteUserTrackRatings.Where(x => x.TrackId == row.DatabaseId).Count(); row.FavoriteCount = favoriteUserTrackRatings.Where(x => x.TrackId == row.DatabaseId).Count();
row.TrackNumber = playListTrackPositions.ContainsKey(row.DatabaseId) ? playListTrackPositions[row.DatabaseId] : row.TrackNumber;
} }
} }
if(playListTrackPositions.Any())
{
rows = rows.OrderBy(x => x.TrackNumber).ToArray();
}
sw.Stop(); sw.Stop();
return Task.FromResult(new Library.Models.Pagination.PagedResult<TrackList> return Task.FromResult(new Library.Models.Pagination.PagedResult<TrackList>
{ {
@ -969,17 +951,16 @@ namespace Roadie.Api.Services
(track.ReleaseMedia.IsLocked ?? false) || (track.ReleaseMedia.IsLocked ?? false) ||
(track.ReleaseMedia.Release.IsLocked ?? false) || (track.ReleaseMedia.Release.IsLocked ?? false) ||
(track.ReleaseMedia.Release.Artist.IsLocked ?? false); (track.ReleaseMedia.Release.Artist.IsLocked ?? false);
result.Thumbnail = MakeTrackThumbnailImage(id); result.Thumbnail = MakeTrackThumbnailImage(Configuration, HttpContext, id);
result.MediumThumbnail = MakeThumbnailImage(id, "track", Configuration.MediumImageSize.Width, result.MediumThumbnail = MakeThumbnailImage(Configuration, HttpContext, id, "track", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
Configuration.MediumImageSize.Height);
result.ReleaseMediaId = track.ReleaseMedia.RoadieId.ToString(); result.ReleaseMediaId = track.ReleaseMedia.RoadieId.ToString();
result.Artist = ArtistList.FromDataArtist(track.ReleaseMedia.Release.Artist, result.Artist = ArtistList.FromDataArtist(track.ReleaseMedia.Release.Artist,
MakeArtistThumbnailImage(track.ReleaseMedia.Release.Artist.RoadieId)); MakeArtistThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.Artist.RoadieId));
result.ArtistThumbnail = MakeArtistThumbnailImage(track.ReleaseMedia.Release.Artist.RoadieId); result.ArtistThumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.Artist.RoadieId);
result.Release = ReleaseList.FromDataRelease(track.ReleaseMedia.Release, track.ReleaseMedia.Release.Artist, result.Release = ReleaseList.FromDataRelease(track.ReleaseMedia.Release, track.ReleaseMedia.Release.Artist,
HttpContext.BaseUrl, MakeArtistThumbnailImage(track.ReleaseMedia.Release.Artist.RoadieId), HttpContext.BaseUrl, MakeArtistThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.Artist.RoadieId),
MakeReleaseThumbnailImage(track.ReleaseMedia.Release.RoadieId)); MakeReleaseThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.RoadieId));
result.ReleaseThumbnail = MakeReleaseThumbnailImage(track.ReleaseMedia.Release.RoadieId); result.ReleaseThumbnail = MakeReleaseThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.RoadieId);
tsw.Stop(); tsw.Stop();
timings.Add("adapt", tsw.ElapsedMilliseconds); timings.Add("adapt", tsw.ElapsedMilliseconds);
if (track.ArtistId.HasValue) if (track.ArtistId.HasValue)
@ -993,9 +974,9 @@ namespace Roadie.Api.Services
else else
{ {
result.TrackArtist = result.TrackArtist =
ArtistList.FromDataArtist(trackArtist, MakeArtistThumbnailImage(trackArtist.RoadieId)); ArtistList.FromDataArtist(trackArtist, MakeArtistThumbnailImage(Configuration, HttpContext, trackArtist.RoadieId));
result.TrackArtistToken = result.TrackArtist.Artist; result.TrackArtistToken = result.TrackArtist.Artist;
result.TrackArtistThumbnail = MakeArtistThumbnailImage(trackArtist.RoadieId); result.TrackArtistThumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, trackArtist.RoadieId);
} }
tsw.Stop(); tsw.Stop();
timings.Add("trackArtist", tsw.ElapsedMilliseconds); timings.Add("trackArtist", tsw.ElapsedMilliseconds);
@ -1042,7 +1023,7 @@ namespace Roadie.Api.Services
var comment = trackComment.Adapt<Comment>(); var comment = trackComment.Adapt<Comment>();
comment.DatabaseId = trackComment.Id; comment.DatabaseId = trackComment.Id;
comment.User = UserList.FromDataUser(trackComment.User, comment.User = UserList.FromDataUser(trackComment.User,
MakeUserThumbnailImage(trackComment.User.RoadieId)); MakeUserThumbnailImage(Configuration, HttpContext, trackComment.User.RoadieId));
comment.DislikedCount = userCommentReactions.Count(x => comment.DislikedCount = userCommentReactions.Count(x =>
x.CommentId == trackComment.Id && x.ReactionValue == CommentReaction.Dislike); x.CommentId == trackComment.Id && x.ReactionValue == CommentReaction.Dislike);
comment.LikedCount = userCommentReactions.Count(x => comment.LikedCount = userCommentReactions.Count(x =>

View file

@ -73,7 +73,7 @@ namespace Roadie.Api.Services
sw.Stop(); sw.Stop();
if (result?.Data != null) if (result?.Data != null)
{ {
result.Data.Avatar = MakeUserThumbnailImage(id); result.Data.Avatar = MakeUserThumbnailImage(Configuration, HttpContext, id);
if (!isAccountSettingsEdit) if (!isAccountSettingsEdit)
{ {
result.Data.ApiToken = null; result.Data.ApiToken = null;
@ -113,7 +113,7 @@ namespace Roadie.Api.Services
IsEditor = u.UserRoles.Any(x => x.Role.Name == "Editor"), IsEditor = u.UserRoles.Any(x => x.Role.Name == "Editor"),
IsAdmin = u.UserRoles.Any(x => x.Role.Name == "Admin"), IsAdmin = u.UserRoles.Any(x => x.Role.Name == "Admin"),
IsPrivate = u.IsPrivate, IsPrivate = u.IsPrivate,
Thumbnail = MakeUserThumbnailImage(u.RoadieId), Thumbnail = MakeUserThumbnailImage(Configuration, HttpContext, u.RoadieId),
CreatedDate = u.CreatedDate, CreatedDate = u.CreatedDate,
LastUpdated = u.LastUpdated, LastUpdated = u.LastUpdated,
RegisteredDate = u.RegisteredOn, RegisteredDate = u.RegisteredOn,
@ -615,7 +615,7 @@ namespace Roadie.Api.Services
}; };
} }
private Task<OperationResult<User>> UserByIdAction(Guid id, IEnumerable<string> includes) private async Task<OperationResult<User>> UserByIdAction(Guid id, IEnumerable<string> includes)
{ {
var timings = new Dictionary<string, long>(); var timings = new Dictionary<string, long>();
var tsw = new Stopwatch(); var tsw = new Stopwatch();
@ -627,11 +627,11 @@ namespace Roadie.Api.Services
if (user == null) if (user == null)
{ {
return Task.FromResult(new OperationResult<User>(true, string.Format("User Not Found [{0}]", id))); return new OperationResult<User>(true, string.Format("User Not Found [{0}]", id));
} }
tsw.Restart(); tsw.Restart();
var model = user.Adapt<User>(); var model = user.Adapt<User>();
model.MediumThumbnail = MakeThumbnailImage(id, "user", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height); model.MediumThumbnail = MakeThumbnailImage(Configuration, HttpContext, id, "user", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
model.IsAdmin = user.UserRoles?.Any(x => x.Role?.NormalizedName == "ADMIN") ?? false; model.IsAdmin = user.UserRoles?.Any(x => x.Role?.NormalizedName == "ADMIN") ?? false;
model.IsEditor = model.IsAdmin ? true : user.UserRoles?.Any(x => x.Role?.NormalizedName == "EDITOR") ?? false; model.IsEditor = model.IsAdmin ? true : user.UserRoles?.Any(x => x.Role?.NormalizedName == "EDITOR") ?? false;
tsw.Stop(); tsw.Stop();
@ -645,37 +645,31 @@ namespace Roadie.Api.Services
var userArtists = DbContext.UserArtists.Include(x => x.Artist).Where(x => x.UserId == user.Id).ToArray() ?? new data.UserArtist[0]; var userArtists = DbContext.UserArtists.Include(x => x.Artist).Where(x => x.UserId == user.Id).ToArray() ?? new data.UserArtist[0];
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];
var mostPlayedArtist = (from a in DbContext.Artists
join r in DbContext.Releases on a.Id equals r.ArtistId // This is MySQL specific
join rm in DbContext.ReleaseMedias on r.Id equals rm.ReleaseId var sql = @"select a.*
join t in DbContext.Tracks on rm.Id equals t.ReleaseMediaId FROM `usertrack` ut
join ut in DbContext.UserTracks on t.Id equals ut.TrackId join `track` t on (ut.trackId = t.id)
where ut.UserId == user.Id join `releasemedia` rm on (t.releaseMediaId = rm.id)
select new { a, ut.PlayedCount }) join `release` r on (rm.releaseId = r.id)
.GroupBy(a => a.a) join `artist` a on (r.artistId = a.id)
.Select(x => new where ut.userId = {0}
{ group by r.id
Artist = x.Key, order by SUM(ut.playedCount) desc
Played = x.Sum(t => t.PlayedCount) LIMIT 1";
}) var mostPlayedArtist = await DbContext.Artists.FromSqlRaw(sql, user.Id).FirstOrDefaultAsync();
.OrderByDescending(x => x.Played)
.FirstOrDefault(); // This is MySQL specific
var mostPlayedReleaseId = (from r in DbContext.Releases sql = @"SELECT r.*
join rm in DbContext.ReleaseMedias on r.Id equals rm.ReleaseId FROM `usertrack` ut
join t in DbContext.Tracks on rm.Id equals t.ReleaseMediaId join `track` t on (ut.trackId = t.id)
join ut in DbContext.UserTracks on t.Id equals ut.TrackId join `releasemedia` rm on (t.releaseMediaId = rm.id)
where ut.UserId == user.Id join `release` r on (rm.releaseId = r.id)
select new { r, ut.PlayedCount }) WHERE ut.userId = {0}
.GroupBy(r => r.r) GROUP by r.id
.Select(x => new ORDER by SUM(ut.playedCount) desc
{ LIMIT 1";
Release = x.Key, var mostPlayedRelease = await DbContext.Releases.FromSqlRaw(sql, user.Id).FirstOrDefaultAsync();
Played = x.Sum(t => t.PlayedCount)
})
.OrderByDescending(x => x.Played)
.Select(x => x.Release.RoadieId)
.FirstOrDefault();
var mostPlayedRelease = GetRelease(mostPlayedReleaseId);
var mostPlayedTrackUserTrack = userTracks.OrderByDescending(x => x.PlayedCount) var mostPlayedTrackUserTrack = userTracks.OrderByDescending(x => x.PlayedCount)
.FirstOrDefault(); .FirstOrDefault();
var lastPlayedTrackUserTrack = userTracks.OrderByDescending(x => x.LastPlayed) var lastPlayedTrackUserTrack = userTracks.OrderByDescending(x => x.LastPlayed)
@ -710,23 +704,23 @@ namespace Roadie.Api.Services
lastPlayedTrack.ReleaseMedia.Release.Artist, lastPlayedTrack.ReleaseMedia.Release.Artist,
lastPlayedTrack.TrackArtist, lastPlayedTrack.TrackArtist,
HttpContext.BaseUrl, HttpContext.BaseUrl,
MakeTrackThumbnailImage(lastPlayedTrack.RoadieId), MakeTrackThumbnailImage(Configuration, HttpContext, lastPlayedTrack.RoadieId),
MakeReleaseThumbnailImage(lastPlayedTrack.ReleaseMedia.Release.RoadieId), MakeReleaseThumbnailImage(Configuration, HttpContext, lastPlayedTrack.ReleaseMedia.Release.RoadieId),
MakeArtistThumbnailImage(lastPlayedTrack.ReleaseMedia.Release.Artist.RoadieId), MakeArtistThumbnailImage(Configuration, HttpContext, lastPlayedTrack.ReleaseMedia.Release.Artist.RoadieId),
MakeArtistThumbnailImage(lastPlayedTrack.TrackArtist == null MakeArtistThumbnailImage(Configuration, HttpContext, lastPlayedTrack.TrackArtist == null
? null ? null
: (Guid?)lastPlayedTrack.TrackArtist.RoadieId)), : (Guid?)lastPlayedTrack.TrackArtist.RoadieId)),
MostPlayedArtist = mostPlayedArtist == null MostPlayedArtist = mostPlayedArtist == null
? null ? null
: models.ArtistList.FromDataArtist(mostPlayedArtist.Artist, : models.ArtistList.FromDataArtist(mostPlayedArtist,
MakeArtistThumbnailImage(mostPlayedArtist.Artist.RoadieId)), MakeArtistThumbnailImage(Configuration, HttpContext, mostPlayedArtist.RoadieId)),
MostPlayedRelease = mostPlayedRelease == null MostPlayedRelease = mostPlayedRelease == null
? null ? null
: ReleaseList.FromDataRelease(mostPlayedRelease, : ReleaseList.FromDataRelease(mostPlayedRelease,
mostPlayedRelease.Artist, mostPlayedRelease.Artist,
HttpContext.BaseUrl, HttpContext.BaseUrl,
MakeArtistThumbnailImage(mostPlayedRelease.Artist.RoadieId), MakeArtistThumbnailImage(Configuration, HttpContext, mostPlayedRelease.Artist.RoadieId),
MakeReleaseThumbnailImage(mostPlayedRelease.RoadieId)), MakeReleaseThumbnailImage(Configuration, HttpContext, mostPlayedRelease.RoadieId)),
MostPlayedTrack = mostPlayedTrack == null MostPlayedTrack = mostPlayedTrack == null
? null ? null
: models.TrackList.FromDataTrack( : models.TrackList.FromDataTrack(
@ -737,10 +731,10 @@ namespace Roadie.Api.Services
mostPlayedTrack.ReleaseMedia.Release.Artist, mostPlayedTrack.ReleaseMedia.Release.Artist,
mostPlayedTrack.TrackArtist, mostPlayedTrack.TrackArtist,
HttpContext.BaseUrl, HttpContext.BaseUrl,
MakeTrackThumbnailImage(mostPlayedTrack.RoadieId), MakeTrackThumbnailImage(Configuration, HttpContext, mostPlayedTrack.RoadieId),
MakeReleaseThumbnailImage(mostPlayedTrack.ReleaseMedia.Release.RoadieId), MakeReleaseThumbnailImage(Configuration, HttpContext, mostPlayedTrack.ReleaseMedia.Release.RoadieId),
MakeArtistThumbnailImage(mostPlayedTrack.ReleaseMedia.Release.Artist.RoadieId), MakeArtistThumbnailImage(Configuration, HttpContext, mostPlayedTrack.ReleaseMedia.Release.Artist.RoadieId),
MakeArtistThumbnailImage(mostPlayedTrack.TrackArtist == null MakeArtistThumbnailImage(Configuration, HttpContext, mostPlayedTrack.TrackArtist == null
? null ? null
: (Guid?)mostPlayedTrack.TrackArtist.RoadieId)), : (Guid?)mostPlayedTrack.TrackArtist.RoadieId)),
RatedArtists = userArtists.Where(x => x.Rating > 0).Count(), RatedArtists = userArtists.Where(x => x.Rating > 0).Count(),
@ -759,11 +753,11 @@ namespace Roadie.Api.Services
} }
} }
Logger.LogInformation($"ByIdAction: User `{ user }`: includes [{includes.ToCSV()}], timings: [{ timings.ToTimings() }]"); Logger.LogInformation($"ByIdAction: User `{ user }`: includes [{includes.ToCSV()}], timings: [{ timings.ToTimings() }]");
return Task.FromResult(new OperationResult<User> return new OperationResult<User>
{ {
IsSuccess = true, IsSuccess = true,
Data = model Data = model
}); };
} }
} }
} }

View file

@ -21,11 +21,11 @@ namespace Roadie.Api.Controllers
{ {
private IAdminService AdminService { get; } private IAdminService AdminService { get; }
public AdminController(IAdminService adminService, ILoggerFactory logger, ICacheManager cacheManager, public AdminController(IAdminService adminService, ILogger<AdminController> logger, ICacheManager cacheManager,
UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings) UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings)
: base(cacheManager, roadieSettings, userManager) : base(cacheManager, roadieSettings, userManager)
{ {
Logger = logger.CreateLogger("RoadieApi.Controllers.AdminController"); Logger = logger;
AdminService = adminService; AdminService = adminService;
} }

View file

@ -25,11 +25,11 @@ namespace Roadie.Api.Controllers
{ {
private IArtistService ArtistService { get; } private IArtistService ArtistService { get; }
public ArtistController(IArtistService artistService, ILoggerFactory logger, ICacheManager cacheManager, public ArtistController(IArtistService artistService, ILogger<ArtistController> logger, ICacheManager cacheManager,
UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings) UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings)
: base(cacheManager, roadieSettings, userManager) : base(cacheManager, roadieSettings, userManager)
{ {
Logger = logger.CreateLogger("RoadieApi.Controllers.ArtistController"); Logger = logger;
ArtistService = artistService; ArtistService = artistService;
} }

View file

@ -21,11 +21,11 @@ namespace Roadie.Api.Controllers
{ {
private IBookmarkService BookmarkService { get; } private IBookmarkService BookmarkService { get; }
public BookmarkController(IBookmarkService bookmarkService, ILoggerFactory logger, ICacheManager cacheManager, public BookmarkController(IBookmarkService bookmarkService, ILogger<BookmarkController> logger, ICacheManager cacheManager,
UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings) UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings)
: base(cacheManager, roadieSettings, userManager) : base(cacheManager, roadieSettings, userManager)
{ {
Logger = logger.CreateLogger("RoadieApi.Controllers.BookmarkController"); Logger = logger;
BookmarkService = bookmarkService; BookmarkService = bookmarkService;
} }

View file

@ -23,12 +23,12 @@ namespace Roadie.Api.Controllers
{ {
private ICollectionService CollectionService { get; } private ICollectionService CollectionService { get; }
public CollectionController(ICollectionService collectionService, ILoggerFactory logger, public CollectionController(ICollectionService collectionService, ILogger<CollectionController> logger,
ICacheManager cacheManager, ICacheManager cacheManager,
UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings) UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings)
: base(cacheManager, roadieSettings, userManager) : base(cacheManager, roadieSettings, userManager)
{ {
Logger = logger.CreateLogger("RoadieApi.Controllers.CollectionController"); Logger = logger;
CollectionService = collectionService; CollectionService = collectionService;
} }

View file

@ -23,12 +23,12 @@ namespace Roadie.Api.Controllers
{ {
private ICommentService CommentService { get; } private ICommentService CommentService { get; }
public CommentController(ILoggerFactory logger, ICacheManager cacheManager, public CommentController(ILogger<CommentController> logger, ICacheManager cacheManager,
UserManager<ApplicationUser> userManager, UserManager<ApplicationUser> userManager,
IRoadieSettings roadieSettings, ICommentService commentService) IRoadieSettings roadieSettings, ICommentService commentService)
: base(cacheManager, roadieSettings, userManager) : base(cacheManager, roadieSettings, userManager)
{ {
Logger = logger.CreateLogger("RoadieApi.Controllers.CommentController"); Logger = logger;
CommentService = commentService; CommentService = commentService;
} }

View file

@ -14,7 +14,6 @@ using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web.Http;
using models = Roadie.Library.Models.Users; using models = Roadie.Library.Models.Users;
namespace Roadie.Api.Controllers namespace Roadie.Api.Controllers

View file

@ -25,11 +25,11 @@ namespace Roadie.Api.Controllers
{ {
private IGenreService GenreService { get; } private IGenreService GenreService { get; }
public GenreController(IGenreService genreService, ILoggerFactory logger, ICacheManager cacheManager, public GenreController(IGenreService genreService, ILogger<GenreController> logger, ICacheManager cacheManager,
UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings) UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings)
: base(cacheManager, roadieSettings, userManager) : base(cacheManager, roadieSettings, userManager)
{ {
Logger = logger.CreateLogger("RoadieApi.Controllers.GenreController"); Logger = logger;
GenreService = genreService; GenreService = genreService;
} }

View file

@ -20,11 +20,11 @@ namespace Roadie.Api.Controllers
{ {
private IImageService ImageService { get; } private IImageService ImageService { get; }
public ImageController(IImageService imageService, ILoggerFactory logger, ICacheManager cacheManager, public ImageController(IImageService imageService, ILogger<ImageController> logger, ICacheManager cacheManager,
UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings) UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings)
: base(cacheManager, roadieSettings, userManager) : base(cacheManager, roadieSettings, userManager)
{ {
Logger = logger.CreateLogger("RoadieApi.Controllers.ImageController"); Logger = logger;
ImageService = imageService; ImageService = imageService;
} }

View file

@ -25,11 +25,11 @@ namespace Roadie.Api.Controllers
{ {
private ILabelService LabelService { get; } private ILabelService LabelService { get; }
public LabelController(ILabelService labelService, ILoggerFactory logger, ICacheManager cacheManager, public LabelController(ILabelService labelService, ILogger<LabelController> logger, ICacheManager cacheManager,
UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings) UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings)
: base(cacheManager, roadieSettings, userManager) : base(cacheManager, roadieSettings, userManager)
{ {
Logger = logger.CreateLogger("RoadieApi.Controllers.LabelController"); Logger = logger;
LabelService = labelService; LabelService = labelService;
} }

View file

@ -20,11 +20,11 @@ namespace Roadie.Api.Controllers
{ {
private ILookupService LookupService { get; } private ILookupService LookupService { get; }
public LookupController(ILabelService labelService, ILoggerFactory logger, ICacheManager cacheManager, public LookupController(ILabelService labelService, ILogger<LookupController> logger, ICacheManager cacheManager,
UserManager<ApplicationUser> userManager, ILookupService lookupService, IRoadieSettings roadieSettings) UserManager<ApplicationUser> userManager, ILookupService lookupService, IRoadieSettings roadieSettings)
: base(cacheManager, roadieSettings, userManager) : base(cacheManager, roadieSettings, userManager)
{ {
Logger = logger.CreateLogger("RoadieApi.Controllers.LookupController"); Logger = logger;
LookupService = lookupService; LookupService = lookupService;
} }

View file

@ -22,12 +22,12 @@ namespace Roadie.Api.Controllers
{ {
private IPlayActivityService PlayActivityService { get; } private IPlayActivityService PlayActivityService { get; }
public PlayActivityController(IPlayActivityService playActivityService, ILoggerFactory logger, public PlayActivityController(IPlayActivityService playActivityService, ILogger<PlayActivityController> logger,
ICacheManager cacheManager, ICacheManager cacheManager,
UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings) UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings)
: base(cacheManager, roadieSettings, userManager) : base(cacheManager, roadieSettings, userManager)
{ {
Logger = logger.CreateLogger("RoadieApi.Controllers.PlayActivityController"); Logger = logger;
PlayActivityService = playActivityService; PlayActivityService = playActivityService;
} }

View file

@ -28,13 +28,12 @@ namespace Roadie.Api.Controllers
private ITrackService TrackService { get; } private ITrackService TrackService { get; }
public PlayController(ITrackService trackService, IReleaseService releaseService, public PlayController(ITrackService trackService, IReleaseService releaseService, IPlayActivityService playActivityService,
IPlayActivityService playActivityService, ILogger<PlayController> logger, ICacheManager cacheManager, UserManager<ApplicationUser> userManager,
ILoggerFactory logger, ICacheManager cacheManager, UserManager<ApplicationUser> userManager,
IRoadieSettings roadieSettings) IRoadieSettings roadieSettings)
: base(cacheManager, roadieSettings, userManager) : base(cacheManager, roadieSettings, userManager)
{ {
Logger = logger.CreateLogger("RoadieApi.Controllers.PlayController"); Logger = logger;
TrackService = trackService; TrackService = trackService;
PlayActivityService = playActivityService; PlayActivityService = playActivityService;
ReleaseService = releaseService; ReleaseService = releaseService;

View file

@ -23,11 +23,11 @@ namespace Roadie.Api.Controllers
{ {
private IPlaylistService PlaylistService { get; } private IPlaylistService PlaylistService { get; }
public PlaylistController(IPlaylistService playlistService, ILoggerFactory logger, ICacheManager cacheManager, public PlaylistController(IPlaylistService playlistService, ILogger<PlaylistController> logger, ICacheManager cacheManager,
UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings) UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings)
: base(cacheManager, roadieSettings, userManager) : base(cacheManager, roadieSettings, userManager)
{ {
Logger = logger.CreateLogger("RoadieApi.Controllers.PlaylistController"); Logger = logger;
PlaylistService = playlistService; PlaylistService = playlistService;
} }

View file

@ -25,11 +25,11 @@ namespace Roadie.Api.Controllers
{ {
private IReleaseService ReleaseService { get; } private IReleaseService ReleaseService { get; }
public ReleaseController(IReleaseService releaseService, ILoggerFactory logger, ICacheManager cacheManager, public ReleaseController(IReleaseService releaseService, ILogger<ReleaseController> logger, ICacheManager cacheManager,
UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings) UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings)
: base(cacheManager, roadieSettings, userManager) : base(cacheManager, roadieSettings, userManager)
{ {
Logger = logger.CreateLogger("RoadieApi.Controllers.ReleaseController"); Logger = logger;
; ;
ReleaseService = releaseService; ReleaseService = releaseService;
} }

View file

@ -20,11 +20,11 @@ namespace Roadie.Api.Controllers
{ {
private IStatisticsService StatisticsService { get; } private IStatisticsService StatisticsService { get; }
public StatsController(IStatisticsService statisticsService, ILoggerFactory logger, ICacheManager cacheManager, public StatsController(IStatisticsService statisticsService, ILogger<StatsController> logger, ICacheManager cacheManager,
UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings) UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings)
: base(cacheManager, roadieSettings, userManager) : base(cacheManager, roadieSettings, userManager)
{ {
Logger = logger.CreateLogger("RoadieApi.Controllers.StatsController"); Logger = logger;
StatisticsService = statisticsService; StatisticsService = statisticsService;
} }

View file

@ -40,11 +40,11 @@ namespace Roadie.Api.Controllers
public SubsonicController(ISubsonicService subsonicService, ITrackService trackService, public SubsonicController(ISubsonicService subsonicService, ITrackService trackService,
IReleaseService releaseService, IReleaseService releaseService,
IPlayActivityService playActivityService, ILoggerFactory logger, ICacheManager cacheManager, IPlayActivityService playActivityService, ILogger<SubsonicController> logger, ICacheManager cacheManager,
UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings) UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings)
: base(cacheManager, roadieSettings, userManager) : base(cacheManager, roadieSettings, userManager)
{ {
Logger = logger.CreateLogger("RoadieApi.Controllers.SubsonicController"); Logger = logger;
SubsonicService = subsonicService; SubsonicService = subsonicService;
TrackService = trackService; TrackService = trackService;
ReleaseService = releaseService; ReleaseService = releaseService;
@ -686,8 +686,6 @@ namespace Roadie.Api.Controllers
postBody = JsonConvert.SerializeObject(formDictionary); postBody = JsonConvert.SerializeObject(formDictionary);
} }
Logger.LogTrace(
$"Subsonic Request: Method [{method}], Accept Header [{acceptHeader}], Path [{queryPath}], Query String [{queryString}], Posted Body [{postBody}], Response Error Code [{response?.ErrorCode}], Request [{JsonConvert.SerializeObject(request, Newtonsoft.Json.Formatting.Indented)}] ResponseType [{responseType}]");
if (response?.ErrorCode.HasValue ?? false) return SendError(request, response); if (response?.ErrorCode.HasValue ?? false) return SendError(request, response);
if (request.IsJSONRequest) if (request.IsJSONRequest)
{ {

View file

@ -23,11 +23,11 @@ namespace Roadie.Api.Controllers
{ {
private ITrackService TrackService { get; } private ITrackService TrackService { get; }
public TrackController(ITrackService trackService, ILoggerFactory logger, ICacheManager cacheManager, public TrackController(ITrackService trackService, ILogger<TrackController> logger, ICacheManager cacheManager,
UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings) UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings)
: base(cacheManager, roadieSettings, userManager) : base(cacheManager, roadieSettings, userManager)
{ {
Logger = logger.CreateLogger("RoadieApi.Controllers.TrackController"); Logger = logger;
TrackService = trackService; TrackService = trackService;
} }

View file

@ -30,12 +30,12 @@ namespace Roadie.Api.Controllers
private IUserService UserService { get; } private IUserService UserService { get; }
public UserController(IUserService userService, ILoggerFactory logger, ICacheManager cacheManager, public UserController(IUserService userService, ILogger<UserController> logger, ICacheManager cacheManager,
IConfiguration configuration, ITokenService tokenService, UserManager<ApplicationUser> userManager, IConfiguration configuration, ITokenService tokenService, UserManager<ApplicationUser> userManager,
IHttpContext httpContext, IRoadieSettings roadieSettings) IHttpContext httpContext, IRoadieSettings roadieSettings)
: base(cacheManager, roadieSettings, userManager) : base(cacheManager, roadieSettings, userManager)
{ {
Logger = logger.CreateLogger("RoadieApi.Controllers.UserController"); Logger = logger;
UserService = userService; UserService = userService;
TokenService = tokenService; TokenService = tokenService;
RoadieHttpContext = httpContext; RoadieHttpContext = httpContext;

View file

@ -1,9 +1,8 @@
using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Serilog; using Serilog;
using Serilog.Events; using Serilog.Extensions.Logging;
using Serilog.Sinks.RollingFileAlternate;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
@ -12,6 +11,7 @@ namespace Roadie.Api
{ {
public class Program public class Program
{ {
public static IConfiguration Configuration { get; } = new ConfigurationBuilder() public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory()) .SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", false, true) .AddJsonFile("appsettings.json", false, true)
@ -48,7 +48,7 @@ namespace Roadie.Api
Console.WriteLine(@"(__\_) \__/ \_/\_/(____/(__)(____) \_/\_/(__) (__) "); Console.WriteLine(@"(__\_) \__/ \_/\_/(____/(__)(____) \_/\_/(__) (__) ");
Console.WriteLine(""); Console.WriteLine("");
CreateWebHostBuilder(args).Build().Run(); CreateHostBuilder(args).Build().Run();
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -60,12 +60,13 @@ namespace Roadie.Api
} }
} }
public static IWebHostBuilder CreateWebHostBuilder(string[] args) public static IHostBuilder CreateHostBuilder(string[] args) =>
{ Host.CreateDefaultBuilder(args)
return WebHost.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder =>
.UseStartup<Startup>() {
.UseSerilog(); webBuilder.UseStartup<Startup>();
} })
.UseSerilog();
} }
public class LoggingTraceListener : TraceListener public class LoggingTraceListener : TraceListener

View file

@ -13,9 +13,9 @@ by editing this MSBuild file. In order to learn more about this please visit htt
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish> <LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
<ExcludeApp_Data>False</ExcludeApp_Data> <ExcludeApp_Data>False</ExcludeApp_Data>
<ProjectGuid>68c80416-0d72-409d-b727-3fea7ab7fd2c</ProjectGuid> <ProjectGuid>68c80416-0d72-409d-b727-3fea7ab7fd2c</ProjectGuid>
<publishUrl>bin\x64\Debug\netcoreapp2.2\publish\</publishUrl> <publishUrl>C:\publish</publishUrl>
<DeleteExistingFiles>True</DeleteExistingFiles> <DeleteExistingFiles>True</DeleteExistingFiles>
<TargetFramework>netcoreapp2.2</TargetFramework> <TargetFramework>netcoreapp3.0</TargetFramework>
<SelfContained>false</SelfContained> <SelfContained>false</SelfContained>
<_IsPortable>true</_IsPortable> <_IsPortable>true</_IsPortable>
<RuntimeIdentifier>linux-x64</RuntimeIdentifier> <RuntimeIdentifier>linux-x64</RuntimeIdentifier>

View file

@ -3,7 +3,7 @@
"Roadie.Api": { "Roadie.Api": {
"commandName": "Project", "commandName": "Project",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Production"
}, },
"applicationUrl": "http://localhost:5123/" "applicationUrl": "http://localhost:5123/"
} }

View file

@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework> <TargetFramework>netcoreapp3.0</TargetFramework>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<UserSecretsId>3f484b72-52aa-42ae-938d-4635f9511319</UserSecretsId> <UserSecretsId>3f484b72-52aa-42ae-938d-4635f9511319</UserSecretsId>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>TRACE;DEBUG;NETCOREAPP2_0</DefineConstants> <DefineConstants>TRACE;DEBUG</DefineConstants>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -23,17 +23,17 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="BCrypt-Core" Version="2.0.0" /> <PackageReference Include="BCrypt-Core" Version="2.0.0" />
<PackageReference Include="Mapster" Version="4.1.0" /> <PackageReference Include="Mapster" Version="4.1.1" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.10.0" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.11.2" />
<PackageReference Include="Microsoft.AspNet.SignalR" Version="2.4.1" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.0.0" />
<PackageReference Include="Microsoft.AspNetCore.All" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.0.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.2.1" /> <PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.3.1" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.2.1" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.3.1" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.2.1" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.3.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.3" /> <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="Serilog.AspNetCore" Version="3.0.0" /> <PackageReference Include="Serilog.AspNetCore" Version="3.1.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" />
@ -41,7 +41,7 @@
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" /> <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
<PackageReference Include="Serilog.Sinks.LiteDB.NetStandard" Version="1.0.14" /> <PackageReference Include="Serilog.Sinks.LiteDB.NetStandard" Version="1.0.14" />
<PackageReference Include="Serilog.Sinks.RollingFileAlternate" Version="2.0.9" /> <PackageReference Include="Serilog.Sinks.RollingFileAlternate" Version="2.0.9" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.5.0" /> <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.6.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.19" /> <PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.19" />
</ItemGroup> </ItemGroup>

View file

@ -1,4 +1,5 @@
#region Usings #region Usings
using Mapster; using Mapster;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
@ -11,7 +12,7 @@ using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json; using Newtonsoft.Json;
using Pomelo.EntityFrameworkCore.MySql.Infrastructure; using Pomelo.EntityFrameworkCore.MySql.Infrastructure;
@ -41,24 +42,21 @@ using Roadie.Library.Utility;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
#endregion using Serilog;
using Microsoft.Extensions.Logging;
using System.Diagnostics;
#endregion Usings
namespace Roadie.Api namespace Roadie.Api
{ {
public class Startup public class Startup
{ {
private readonly IConfiguration _configuration; private readonly IConfiguration _configuration;
private readonly ILoggerFactory _loggerFactory;
private ILogger Logger { get; } public Startup(IConfiguration configuration)
public Startup(IConfiguration configuration, ILoggerFactory loggerFactory)
{ {
_configuration = configuration; _configuration = configuration;
_loggerFactory = loggerFactory;
Logger = _loggerFactory.CreateLogger<Startup>();
TypeAdapterConfig<Library.Data.Image, Library.Models.Image> TypeAdapterConfig<Library.Data.Image, Library.Models.Image>
.NewConfig() .NewConfig()
.Map(i => i.ArtistId, .Map(i => i.ArtistId,
@ -71,13 +69,18 @@ namespace Roadie.Api
} }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IHostingEnvironment env) public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{ {
if (env.IsDevelopment()) app.UseDeveloperExceptionPage(); if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors("CORSPolicy"); app.UseCors("CORSPolicy");
app.UseAuthorization();
app.UseAuthentication(); app.UseAuthentication();
//app.UseSwagger(); //app.UseSwagger();
//app.UseSwaggerUI(c => //app.UseSwaggerUI(c =>
//{ //{
@ -85,14 +88,18 @@ namespace Roadie.Api
// c.RoutePrefix = string.Empty; // c.RoutePrefix = string.Empty;
//}); //});
app.UseSerilogRequestLogging();
app.UseStaticFiles(); app.UseStaticFiles();
app.UseSignalR(routes => app.UseRouting();
app.UseEndpoints(endpoints =>
{ {
routes.MapHub<PlayActivityHub>("/playActivityHub"); endpoints.MapHub<PlayActivityHub>("/playActivityHub");
routes.MapHub<ScanActivityHub>("/scanActivityHub"); endpoints.MapHub<ScanActivityHub>("/scanActivityHub");
endpoints.MapControllers();
}); });
app.UseMvc();
} }
// This method gets called by the runtime. Use this method to add services to the container. // This method gets called by the runtime. Use this method to add services to the container.
@ -102,8 +109,11 @@ namespace Roadie.Api
services.AddSingleton<IHttpEncoder, HttpEncoder>(); services.AddSingleton<IHttpEncoder, HttpEncoder>();
services.AddSingleton<IEmailSender, EmailSenderService>(); services.AddSingleton<IEmailSender, EmailSenderService>();
var cacheManager = new MemoryCacheManager(_loggerFactory.CreateLogger<DictionaryCacheManager>(), new CachePolicy(TimeSpan.FromHours(4))); services.AddSingleton<ICacheManager>(options =>
services.AddSingleton<ICacheManager>(cacheManager); {
var logger = options.GetService<ILogger<MemoryCacheManager>>();
return new MemoryCacheManager(logger, new CachePolicy(TimeSpan.FromHours(4)));
});
services.AddDbContextPool<ApplicationUserDbContext>( services.AddDbContextPool<ApplicationUserDbContext>(
options => options.UseMySql(_configuration.GetConnectionString("RoadieDatabaseConnection"), options => options.UseMySql(_configuration.GetConnectionString("RoadieDatabaseConnection"),
@ -142,7 +152,7 @@ namespace Roadie.Api
services.Configure<IConfiguration>(_configuration); services.Configure<IConfiguration>(_configuration);
var corsOrigins = (_configuration["CORSOrigins"] ?? "http://localhost:8080").Split('|'); var corsOrigins = (_configuration["CORSOrigins"] ?? "http://localhost:8080").Split('|');
Logger.LogDebug("Setting Up CORS Policy [{0}]", string.Join(", ", corsOrigins)); Trace.WriteLine($"Setting Up CORS Policy [{string.Join(", ", corsOrigins)}]");
services.AddCors(options => options.AddPolicy("CORSPolicy", builder => services.AddCors(options => options.AddPolicy("CORSPolicy", builder =>
{ {
@ -158,7 +168,7 @@ namespace Roadie.Api
var settings = new RoadieSettings(); var settings = new RoadieSettings();
var configuration = ctx.GetService<IConfiguration>(); var configuration = ctx.GetService<IConfiguration>();
configuration.GetSection("RoadieSettings").Bind(settings); configuration.GetSection("RoadieSettings").Bind(settings);
var hostingEnvironment = ctx.GetService<IHostingEnvironment>(); var hostingEnvironment = ctx.GetService<IWebHostEnvironment>();
settings.ContentPath = hostingEnvironment.WebRootPath; settings.ContentPath = hostingEnvironment.WebRootPath;
settings.ConnectionString = _configuration.GetConnectionString("RoadieDatabaseConnection"); settings.ConnectionString = _configuration.GetConnectionString("RoadieDatabaseConnection");
@ -231,7 +241,7 @@ namespace Roadie.Api
services.AddSingleton<Microsoft.Extensions.Hosting.IHostedService, DlnaHostService>(); services.AddSingleton<Microsoft.Extensions.Hosting.IHostedService, DlnaHostService>();
var securityKey = new SymmetricSecurityKey(Encoding.Default.GetBytes(_configuration["Tokens:PrivateKey"])); var securityKey = new SymmetricSecurityKey(Encoding.Default.GetBytes(_configuration["Tokens:PrivateKey"]));
services.AddAuthentication(options => services.AddAuthentication(options =>
{ {
@ -270,13 +280,12 @@ namespace Roadie.Api
options.RespectBrowserAcceptHeader = true; // false by default options.RespectBrowserAcceptHeader = true; // false by default
options.ModelBinderProviders.Insert(0, new SubsonicRequestBinderProvider()); options.ModelBinderProviders.Insert(0, new SubsonicRequestBinderProvider());
}) })
.AddJsonOptions(options => .AddNewtonsoftJson(options =>
{ {
options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
}) })
.AddXmlSerializerFormatters() .AddXmlSerializerFormatters();
.SetCompatibilityVersion(CompatibilityVersion.Latest);
services.Configure<IdentityOptions>(options => services.Configure<IdentityOptions>(options =>
{ {
@ -292,7 +301,7 @@ namespace Roadie.Api
services.AddScoped<IHttpContext>(factory => services.AddScoped<IHttpContext>(factory =>
{ {
var actionContext = factory.GetService<IActionContextAccessor>().ActionContext; var actionContext = factory.GetService<IActionContextAccessor>().ActionContext;
if(actionContext == null) if (actionContext == null)
{ {
return null; return null;
} }

View file

@ -53,7 +53,8 @@
"CORSOrigins": "http://localhost:4200|http://localhost:8080|https://localhost:8080|http://localhost:80|https://localhost:80", "CORSOrigins": "http://localhost:4200|http://localhost:8080|https://localhost:8080|http://localhost:80|https://localhost:80",
"RoadieSettings": { "RoadieSettings": {
"Dlna": { "Dlna": {
"Port": 61903 "Port": 61903,
"IsEnabled": false
}, },
"Converting": { "Converting": {
"ConvertingEnabled": true, "ConvertingEnabled": true,

View file

@ -122,41 +122,31 @@ namespace Roadie.Dlna.Services
throw new NotImplementedException(); throw new NotImplementedException();
} }
private byte[] ArtistArt(Guid artistId) private IEnumerable<string> ArtistGroupKeys()
{
var imageResult = AsyncHelper.RunSync(() => ImageService.ArtistImage(artistId, 320, 320));
return imageResult.Data?.Bytes;
}
private Dictionary<string, data.Artist[]> ArtistGroups()
{ {
lock (lockObject) lock (lockObject)
{ {
return CacheManager.Get("urn:DlnaService:Artists", () => return CacheManager.Get("urn:DlnaService:Artists", () =>
{ {
IEnumerable<string> result = new string[0];
try try
{ {
var sw = Stopwatch.StartNew(); var sw = Stopwatch.StartNew();
var result = (from a in DbContext.Artists result = (from a in DbContext.Artists
join r in DbContext.Releases on a.Id equals r.ArtistId where a.ReleaseCount > 0
let sn = (a.SortName ?? a.Name ?? "?").ToUpper() select a)
orderby sn .ToArray()
group a by sn[0] into ag .Select(x => x.GroupBy)
select new .Distinct();
{
FirstLetter = ag.Key.ToString(),
Artists = ag.ToArray()
})
.ToDictionary(x => x.FirstLetter, x => x.Artists);
sw.Stop(); sw.Stop();
Logger.LogDebug($"DLNA ArtistGroups fetch Elapsed Time [{ sw.Elapsed }]"); Logger.LogDebug($"DLNA ArtistGroupKeys fetch Elapsed Time [{ sw.Elapsed }]");
return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.LogError(ex); Logger.LogError(ex);
} }
return null; return result;
}, "urn:DlnaServiceRegion"); }, "urn:DlnaServiceRegion");
} }
} }
@ -174,10 +164,10 @@ namespace Roadie.Dlna.Services
Name = "Artists", Name = "Artists",
Id = "vf:artists" Id = "vf:artists"
}; };
foreach (var ag in ArtistGroups()) foreach (var groupKey in ArtistGroupKeys())
{ {
var f = new VirtualFolder(result, ag.Key, $"vf:artistsforfolder:{ ag.Key }"); var f = new VirtualFolder(result, groupKey, $"vf:artistsforfolder:{ groupKey }");
foreach (var artistForGroup in ArtistsForGroup(ag.Key)) foreach (var artistForGroup in ArtistsForGroup(groupKey))
{ {
var af = new VirtualFolder(f, artistForGroup.RoadieId.ToString(), $"vf:artist:{ artistForGroup.Id }"); var af = new VirtualFolder(f, artistForGroup.RoadieId.ToString(), $"vf:artist:{ artistForGroup.Id }");
f.AddFolder(af); f.AddFolder(af);
@ -224,11 +214,7 @@ namespace Roadie.Dlna.Services
{ {
return CacheManager.Get($"urn:DlnaService:ArtistsForGroup:{ groupKey }", () => return CacheManager.Get($"urn:DlnaService:ArtistsForGroup:{ groupKey }", () =>
{ {
return (from a in DbContext.Artists return DbContext.Artists.AsEnumerable().Where(x => x.GroupBy == groupKey).Distinct().ToArray();
join r in DbContext.Releases on a.Id equals r.ArtistId
let sn = (a.SortName ?? a.Name).ToUpper()
where sn[0].ToString().ToUpper() == groupKey
select a).Distinct().ToArray();
}, "urn:DlnaServiceRegion"); }, "urn:DlnaServiceRegion");
} }
} }
@ -267,22 +253,23 @@ namespace Roadie.Dlna.Services
return result; return result;
} }
private IEnumerable<data.Collection> CollectionsForGroup(string groupKey) //private IEnumerable<data.Collection> CollectionsForGroup(string groupKey)
{ //{
lock (lockObject) // lock (lockObject)
{ // {
return CacheManager.Get($"urn:DlnaService:CollectionsForGroup:{ groupKey }", () => // return CacheManager.Get($"urn:DlnaService:CollectionsForGroup:{ groupKey }", () =>
{ // {
return (from c in DbContext.Collections // return (from c in DbContext.Collections
let sn = (c.SortName ?? c.Name).ToUpper() // let sn = (c.SortName ?? c.Name).ToUpper()
where sn == groupKey // where sn == groupKey
select c).Distinct().ToArray(); // select c).Distinct().ToArray();
}, "urn:DlnaServiceRegion"); // }, "urn:DlnaServiceRegion");
} // }
} //}
private IEnumerable<data.Playlist> PlaylistGroups() private IEnumerable<data.Playlist> PlaylistGroups()
{ lock (lockObject) {
lock (lockObject)
{ {
return CacheManager.Get("urn:DlnaService:Playlists", () => return CacheManager.Get("urn:DlnaService:Playlists", () =>
{ {
@ -406,17 +393,18 @@ namespace Roadie.Dlna.Services
return imageResult.Data?.Bytes; return imageResult.Data?.Bytes;
} }
private Dictionary<string, data.Release[]> ReleaseGroups() private IEnumerable<string> ReleaseGroupKeys()
{ {
lock (lockObject) lock (lockObject)
{ {
return CacheManager.Get("urn:DlnaService:Releases", () => return CacheManager.Get("urn:DlnaService:Releases", () =>
{ {
return (from r in DbContext.Releases return (from r in DbContext.Releases
orderby r.Title select r)
group r by r.Title[0] into rg .ToArray()
select new { FirstLetter = rg.Key.ToString(), Releases = rg.ToArray() }) .Select(x => x.GroupBy)
.ToDictionary(x => x.FirstLetter, x => x.Releases); .Distinct();
}, "urn:DlnaServiceRegion"); }, "urn:DlnaServiceRegion");
} }
} }
@ -428,10 +416,10 @@ namespace Roadie.Dlna.Services
Name = "Releases", Name = "Releases",
Id = "vf:releases" Id = "vf:releases"
}; };
foreach (var ag in ReleaseGroups()) foreach (var groupKey in ReleaseGroupKeys())
{ {
var f = new VirtualFolder(result, ag.Key, $"vf:releasesforfolder:{ ag.Key }"); var f = new VirtualFolder(result, groupKey, $"vf:releasesforfolder:{ groupKey}");
foreach (var releaseForGroup in ReleasesForGroup(ag.Key)) foreach (var releaseForGroup in ReleasesForGroup(groupKey))
{ {
var af = new VirtualFolder(f, releaseForGroup.RoadieId.ToString(), $"vf:release:{ releaseForGroup.Id }"); var af = new VirtualFolder(f, releaseForGroup.RoadieId.ToString(), $"vf:release:{ releaseForGroup.Id }");
f.AddFolder(af); f.AddFolder(af);
@ -555,11 +543,9 @@ namespace Roadie.Dlna.Services
return CacheManager.Get($"urn:DlnaService:ReleasesForGroup:{ groupKey }", () => return CacheManager.Get($"urn:DlnaService:ReleasesForGroup:{ groupKey }", () =>
{ {
var sw = Stopwatch.StartNew(); var sw = Stopwatch.StartNew();
var result = (from r in DbContext.Releases var result = DbContext.Releases.AsEnumerable().Where(x => x.GroupBy == groupKey).Distinct().ToArray();
where r.Title[0].ToString() == groupKey
select r).Distinct().ToArray();
sw.Stop(); sw.Stop();
Logger.LogDebug($"DLNA ReleasesForGroup Elapsed Time [{ sw.Elapsed }]"); Logger.LogDebug($"DLNA ReleasesForGroup [{ groupKey }] Elapsed Time [{ sw.Elapsed }]");
return result; return result;
}, "urn:DlnaServiceRegion"); }, "urn:DlnaServiceRegion");
} }

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework> <TargetFramework>netcoreapp3.0</TargetFramework>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
</PropertyGroup> </PropertyGroup>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework> <TargetFramework>netcoreapp3.0</TargetFramework>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
</PropertyGroup> </PropertyGroup>