resolves #24, also most Info log writes are now Trace.

This commit is contained in:
Steven Hildreth 2019-08-03 17:59:20 -05:00
parent 872350763a
commit 891f57d89a
43 changed files with 776 additions and 291 deletions

3
.gitignore vendored
View file

@ -258,4 +258,5 @@ paket-files/
# Python Tools for Visual Studio (PTVS) # Python Tools for Visual Studio (PTVS)
__pycache__/ __pycache__/
*.pyc *.pyc
/Roadie.Api/logs/logs.db

View file

@ -97,11 +97,11 @@ namespace Roadie.Library.Caching
{ {
r = await getItem(); r = await getItem();
Add(key, r, region); Add(key, r, region);
Logger.LogInformation($"-+> Cache Miss for Key [{key}], Region [{region}]"); Logger.LogTrace($"-+> Cache Miss for Key [{key}], Region [{region}]");
} }
else else
{ {
Logger.LogInformation($"-!> Cache Hit for Key [{key}], Region [{region}]"); Logger.LogTrace($"-!> Cache Hit for Key [{key}], Region [{region}]");
} }
return r; return r;

View file

@ -48,8 +48,7 @@ namespace Roadie.Library.Data
public override string ToString() public override string ToString()
{ {
return string.Format("Id [{0}], Name [{1}], SortName [{2}], RoadieId [{3}]", Id, Name, SortNameValue, return $"Id [{ Id }], Status [{ Status }], Name [{ Name }], SortName [{ SortNameValue}], RoadieId [{ RoadieId}]";
RoadieId);
} }
} }
} }

View file

@ -25,5 +25,10 @@ namespace Roadie.Library.Data
if (Bytes == null || !Bytes.Any()) return null; if (Bytes == null || !Bytes.Any()) return null;
return ImageHasher.AverageHash(Bytes).ToString(); return ImageHasher.AverageHash(Bytes).ToString();
} }
public override string ToString()
{
return $"Id [{Id}], RoadieId [{RoadieId}]";
}
} }
} }

View file

@ -107,7 +107,7 @@ namespace Roadie.Library.Data
public override string ToString() public override string ToString()
{ {
return $"Id [{Id}], Title [{Title}], Release Date [{ReleaseYear}]"; return $"Id [{Id}], Status [{ Status }], LibraryStatus [{ LibraryStatus }], Title [{Title}], Release Date [{ReleaseYear}]";
} }
} }
} }

View file

@ -69,7 +69,7 @@ namespace Roadie.Library.Data
public override string ToString() public override string ToString()
{ {
return string.Format("Id [{0}], TrackNumber [{1}], Title [{2}]", Id, TrackNumber, Title); return $"Id [{ Id }], Status [{ Status }], TrackNumber [{ TrackNumber }], Title [{ Title}]";
} }
/// <summary> /// <summary>

View file

@ -152,7 +152,7 @@ namespace Roadie.Library.Engines
inserted = await DbContext.SaveChangesAsync(); inserted = await DbContext.SaveChangesAsync();
} }
sw.Stop(); sw.Stop();
Logger.LogInformation($"Added New Artist: Elapsed Time [{ sw.ElapsedMilliseconds }], Artist `{ artist }`"); Logger.LogTrace($"Added New Artist: Elapsed Time [{ sw.ElapsedMilliseconds }], Artist `{ artist }`");
} }
} }
catch (Exception ex) catch (Exception ex)
@ -232,7 +232,7 @@ namespace Roadie.Library.Engines
sw.Stop(); sw.Stop();
if (artist == null || !artist.IsValid) if (artist == null || !artist.IsValid)
{ {
Logger.LogInformation("ArtistLookupEngine: Artist Not Found By Name [{0}]", artistName); Logger.LogTrace("ArtistLookupEngine: Artist Not Found By Name [{0}]", artistName);
if (doFindIfNotInDatabase) if (doFindIfNotInDatabase)
{ {
OperationResult<Artist> artistSearch = null; OperationResult<Artist> artistSearch = null;

View file

@ -101,7 +101,7 @@ namespace Roadie.Library.Engines
sw.Stop(); sw.Stop();
if (label == null || !label.IsValid) if (label == null || !label.IsValid)
{ {
Logger.LogInformation("LabelFactory: Label Not Found By Name [{0}]", labelName); Logger.LogTrace("LabelFactory: Label Not Found By Name [{0}]", labelName);
if (doFindIfNotInDatabase) if (doFindIfNotInDatabase)
{ {
OperationResult<Label> LabelSearch = null; OperationResult<Label> LabelSearch = null;

View file

@ -274,7 +274,7 @@ namespace Roadie.Library.Engines
} }
} }
sw.Stop(); sw.Stop();
Logger.LogInformation($"Added New Release: Elapsed Time [{ sw.ElapsedMilliseconds }], Release `{ release }`"); Logger.LogTrace($"Added New Release: Elapsed Time [{ sw.ElapsedMilliseconds }], Release `{ release }`");
} }
} }
catch (Exception ex) catch (Exception ex)
@ -342,7 +342,7 @@ namespace Roadie.Library.Engines
sw.Stop(); sw.Stop();
if (release == null || !release.IsValid) if (release == null || !release.IsValid)
{ {
Logger.LogInformation("ReleaseFactory: Release Not Found For Artist `{0}` MetaData [{1}]", Logger.LogTrace("ReleaseFactory: Release Not Found For Artist `{0}` MetaData [{1}]",
artist.ToString(), metaData.ToString()); artist.ToString(), metaData.ToString());
if (doFindIfNotInDatabase) if (doFindIfNotInDatabase)
{ {

View file

@ -25,8 +25,7 @@ namespace Roadie.Library.Models.Collections
public DataToken Release { get; set; } public DataToken Release { get; set; }
public Image Thumbnail { get; set; } public Image Thumbnail { get; set; }
public static CollectionList FromDataCollection(Data.Collection collection, int foundCount, public static CollectionList FromDataCollection(Data.Collection collection, int foundCount, Image collectionThumbnail)
Image collectionThumbnail)
{ {
return new CollectionList return new CollectionList
{ {

View file

@ -28,18 +28,10 @@ namespace Roadie.Library.Models
public DateTime? LastUpdated { get; set; } public DateTime? LastUpdated { get; set; }
/// <summary>
/// Random int to sort when Random Request
/// </summary>
[AdaptIgnore]
[JsonIgnore]
public int RandomSortId { get; set; }
[MaxLength(250)] public string SortName { get; set; } [MaxLength(250)] public string SortName { get; set; }
public EntityInfoModelBase() public EntityInfoModelBase()
{ {
RandomSortId = StaticRandom.Instance.Next();
} }
} }
} }

View file

@ -41,7 +41,11 @@ namespace Roadie.Library.Models
public DateTime? EndDate { get; set; } public DateTime? EndDate { get; set; }
[AdaptMember("RoadieId")] public virtual Guid? Id { get; set; } /// <summary>
/// This is the exposed Id for API consumers, not the Database Id.
/// </summary>
[AdaptMember("RoadieId")]
public virtual Guid? Id { get; set; }
public bool? IsLocked { get; set; } public bool? IsLocked { get; set; }

View file

@ -1,4 +1,5 @@
using System; using Newtonsoft.Json;
using System;
namespace Roadie.Library.Models namespace Roadie.Library.Models
{ {

View file

@ -26,8 +26,7 @@ namespace Roadie.Library.Models.Playlists
public DataToken User { get; set; } public DataToken User { get; set; }
public Image UserThumbnail { get; set; } public Image UserThumbnail { get; set; }
public static PlaylistList FromDataPlaylist(Data.Playlist playlist, ApplicationUser user, public static PlaylistList FromDataPlaylist(Data.Playlist playlist, ApplicationUser user, Image playlistThumbnail, Image userThumbnail)
Image playlistThumbnail, Image userThumbnail)
{ {
return new PlaylistList return new PlaylistList
{ {

View file

@ -35,7 +35,7 @@ namespace Roadie.Library.Models.Users
[MaxLength(250)] public string FtpUrl { get; set; } [MaxLength(250)] public string FtpUrl { get; set; }
[MaxLength(50)] public string FtpUsername { get; set; } [MaxLength(50)] public string FtpUsername { get; set; }
public int? Id { get; set; } public new int? Id { get; set; }
public bool IsAdmin { get; set; } public bool IsAdmin { get; set; }
public bool IsEditor { get; set; } public bool IsEditor { get; set; }
public bool IsPrivate { get; set; } public bool IsPrivate { get; set; }
@ -73,9 +73,6 @@ namespace Roadie.Library.Models.Users
public DateTime LastApiAccess { get; set; } public DateTime LastApiAccess { get; set; }
public short? DefaultRowsPerPage { get; set; } public short? DefaultRowsPerPage { get; set; }
public override string ToString() public override string ToString() => $"Id [{Id}], RoadieId [{UserId}], UserName [{UserName}]";
{
return $"Id [{Id}], RoadieId [{UserId}], UserName [{UserName}]";
}
} }
} }

View file

@ -11,7 +11,7 @@
<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.5.2" /> <PackageReference Include="EFCore.BulkExtensions" Version="2.5.2" />
<PackageReference Include="FluentFTP" Version="27.0.0" /> <PackageReference Include="FluentFTP" Version="27.0.1" />
<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.12" />
<PackageReference Include="IdSharp.Common" Version="1.0.1" /> <PackageReference Include="IdSharp.Common" Version="1.0.1" />

View file

@ -65,8 +65,7 @@ namespace Roadie.Library.Scrobble
try try
{ {
var user = DbContext.Users.FirstOrDefault(x => x.RoadieId == roadieUser.UserId); var user = DbContext.Users.FirstOrDefault(x => x.RoadieId == roadieUser.UserId);
userTrack = DbContext.UserTracks.FirstOrDefault(x => userTrack = DbContext.UserTracks.FirstOrDefault(x => x.UserId == user.Id && x.TrackId == track.Id);
x.UserId == roadieUser.Id && x.TrackId == track.Id);
if (userTrack == null) if (userTrack == null)
{ {
userTrack = new data.UserTrack(now) userTrack = new data.UserTrack(now)

View file

@ -141,7 +141,7 @@ namespace Roadie.Library.MetaData.Audio
result.SetArtistName(artistNameReplaceKp.Key); result.SetArtistName(artistNameReplaceKp.Key);
} }
Logger.LogInformation("File [{0}], TagSources [{1}] MetaData [{2}]", fileInfo.Name, Logger.LogTrace("File [{0}], TagSources [{1}] MetaData [{2}]", fileInfo.Name,
string.Join(",", tagSources), result.ToString()); string.Join(",", tagSources), result.ToString());
return result; return result;
} }

View file

@ -136,7 +136,7 @@ namespace Roadie.Library.MetaData.LastFm
dataStream.Close(); dataStream.Close();
} }
var xp = GetResponseAsXml(request); var xp = GetResponseAsXml(request);
Logger.LogInformation($"LastFmHelper: RoadieUser `{roadieUser}` NowPlaying `{scrobble}` LastFmResult [{xp.InnerXml}]"); Logger.LogTrace($"LastFmHelper: RoadieUser `{roadieUser}` NowPlaying `{scrobble}` LastFmResult [{xp.InnerXml}]");
result = true; result = true;
}); });
} }
@ -303,8 +303,7 @@ namespace Roadie.Library.MetaData.LastFm
} }
var xp = GetResponseAsXml(request); var xp = GetResponseAsXml(request);
Logger.LogInformation( Logger.LogTrace($"LastFmHelper: RoadieUser `{roadieUser}` Scrobble `{scrobble}` LastFmResult [{xp.InnerXml}]");
$"LastFmHelper: RoadieUser `{roadieUser}` Scrobble `{scrobble}` LastFmResult [{xp.InnerXml}]");
result = true; result = true;
} }
catch (Exception ex) catch (Exception ex)

View file

@ -0,0 +1,332 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Roadie.Library.SearchEngines.MetaData.LastFm
{
// NOTE: Generated code may require at least .NET Framework 4.5 or .NET Core/Standard 2.0.
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class scrobbles
{
private scrobblesScrobble scrobbleField;
private byte ignoredField;
private byte acceptedField;
/// <remarks/>
public scrobblesScrobble scrobble
{
get
{
return this.scrobbleField;
}
set
{
this.scrobbleField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public byte ignored
{
get
{
return this.ignoredField;
}
set
{
this.ignoredField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public byte accepted
{
get
{
return this.acceptedField;
}
set
{
this.acceptedField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class scrobblesScrobble
{
private scrobblesScrobbleTrack trackField;
private scrobblesScrobbleArtist artistField;
private scrobblesScrobbleAlbum albumField;
private scrobblesScrobbleAlbumArtist albumArtistField;
private uint timestampField;
private scrobblesScrobbleIgnoredMessage ignoredMessageField;
/// <remarks/>
public scrobblesScrobbleTrack track
{
get
{
return this.trackField;
}
set
{
this.trackField = value;
}
}
/// <remarks/>
public scrobblesScrobbleArtist artist
{
get
{
return this.artistField;
}
set
{
this.artistField = value;
}
}
/// <remarks/>
public scrobblesScrobbleAlbum album
{
get
{
return this.albumField;
}
set
{
this.albumField = value;
}
}
/// <remarks/>
public scrobblesScrobbleAlbumArtist albumArtist
{
get
{
return this.albumArtistField;
}
set
{
this.albumArtistField = value;
}
}
/// <remarks/>
public uint timestamp
{
get
{
return this.timestampField;
}
set
{
this.timestampField = value;
}
}
/// <remarks/>
public scrobblesScrobbleIgnoredMessage ignoredMessage
{
get
{
return this.ignoredMessageField;
}
set
{
this.ignoredMessageField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class scrobblesScrobbleTrack
{
private byte correctedField;
private string valueField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public byte corrected
{
get
{
return this.correctedField;
}
set
{
this.correctedField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string Value
{
get
{
return this.valueField;
}
set
{
this.valueField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class scrobblesScrobbleArtist
{
private byte correctedField;
private string valueField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public byte corrected
{
get
{
return this.correctedField;
}
set
{
this.correctedField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string Value
{
get
{
return this.valueField;
}
set
{
this.valueField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class scrobblesScrobbleAlbum
{
private byte correctedField;
private string valueField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public byte corrected
{
get
{
return this.correctedField;
}
set
{
this.correctedField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string Value
{
get
{
return this.valueField;
}
set
{
this.valueField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class scrobblesScrobbleAlbumArtist
{
private byte correctedField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public byte corrected
{
get
{
return this.correctedField;
}
set
{
this.correctedField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class scrobblesScrobbleIgnoredMessage
{
private byte codeField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public byte code
{
get
{
return this.codeField;
}
set
{
this.codeField = value;
}
}
}
}

View file

@ -160,7 +160,7 @@ namespace Roadie.Library.MetaData.MusicBrainz
} }
else else
{ {
Logger.LogWarning("MusicBrainzArtist: ArtistName [{0}], No MusicBrainz Artist Found", query); Logger.LogTrace("MusicBrainzArtist: ArtistName [{0}], No MusicBrainz Artist Found", query);
} }
return new OperationResult<IEnumerable<ArtistSearchResult>> return new OperationResult<IEnumerable<ArtistSearchResult>>
{ {
@ -283,7 +283,7 @@ namespace Roadie.Library.MetaData.MusicBrainz
if (result == null) if (result == null)
{ {
Logger.LogWarning("MusicBrainzArtist: ArtistName [{0}], ReleaseTitle [{0}], No MusicBrainz Release Found", artistName, query); Logger.LogTrace("MusicBrainzArtist: ArtistName [{0}], ReleaseTitle [{0}], No MusicBrainz Release Found", artistName, query);
} }
else else
{ {

View file

@ -35,8 +35,6 @@ namespace Roadie.Api.Services
private IFileDirectoryProcessorService FileDirectoryProcessorService { get; } private IFileDirectoryProcessorService FileDirectoryProcessorService { get; }
private ILogger MessageLogger => EventMessageLogger as ILogger;
private IReleaseLookupEngine ReleaseLookupEngine { get; } private IReleaseLookupEngine ReleaseLookupEngine { get; }
private IReleaseService ReleaseService { get; } private IReleaseService ReleaseService { get; }
@ -501,7 +499,7 @@ namespace Roadie.Api.Services
} }
sw.Stop(); sw.Stop();
await LogAndPublish($"DeleteTracks `{track}`, By User `{user}`", LogLevel.Information); await LogAndPublish($"DeleteTracks `{track}`, By User `{user}`", LogLevel.Warning);
} }
CacheManager.Clear(); CacheManager.Clear();
return new OperationResult<bool> return new OperationResult<bool>
@ -553,7 +551,7 @@ namespace Roadie.Api.Services
} }
sw.Stop(); sw.Stop();
await LogAndPublish($"DeleteUser `{user}`, By User `{user}`", LogLevel.Information); await LogAndPublish($"DeleteUser `{user}`, By User `{user}`", LogLevel.Warning);
CacheManager.Clear(); CacheManager.Clear();
return new OperationResult<bool> return new OperationResult<bool>
{ {
@ -565,11 +563,9 @@ namespace Roadie.Api.Services
} }
/// <summary> /// <summary>
/// This is a very simple way to seed the database or setup configuration when the first (who becomes "Admin") user /// This is a very simple way to seed the database or setup configuration when the first (who becomes "Admin") user registers
/// registers
/// </summary> /// </summary>
public async Task<OperationResult<bool>> DoInitialSetup(ApplicationUser user, public async Task<OperationResult<bool>> DoInitialSetup(ApplicationUser user, UserManager<ApplicationUser> userManager)
UserManager<ApplicationUser> userManager)
{ {
var sw = new Stopwatch(); var sw = new Stopwatch();
sw.Start(); sw.Start();
@ -700,7 +696,7 @@ namespace Roadie.Api.Services
sw.Stop(); sw.Stop();
await LogAndPublish( await LogAndPublish(
$"ScanAllCollections, By User `{user}`, Updated Release Count [{updatedReleaseIds.Distinct().Count()}], ElapsedTime [{sw.ElapsedMilliseconds}]", $"ScanAllCollections, By User `{user}`, Updated Release Count [{updatedReleaseIds.Distinct().Count()}], ElapsedTime [{sw.ElapsedMilliseconds}]",
LogLevel.Information); LogLevel.Warning);
return new OperationResult<bool> return new OperationResult<bool>
{ {
IsSuccess = !errors.Any(), IsSuccess = !errors.Any(),
@ -769,7 +765,6 @@ namespace Roadie.Api.Services
}); });
await DbContext.SaveChangesAsync(); await DbContext.SaveChangesAsync();
await UpdateArtistRank(artist.Id, true); await UpdateArtistRank(artist.Id, true);
await LogAndPublish($"ScanArtist `{artist}`, By User `{user}`", LogLevel.Information);
return new OperationResult<bool> return new OperationResult<bool>
{ {
IsSuccess = !errors.Any(), IsSuccess = !errors.Any(),
@ -950,7 +945,7 @@ namespace Roadie.Api.Services
} }
sw.Stop(); sw.Stop();
Logger.LogInformation(string.Format("RescanCollection `{0}`, By User `{1}`, ElapsedTime [{2}]", collection, Logger.LogWarning(string.Format("RescanCollection `{0}`, By User `{1}`, ElapsedTime [{2}]", collection,
user, sw.ElapsedMilliseconds)); user, sw.ElapsedMilliseconds));
return new OperationResult<bool> return new OperationResult<bool>
@ -966,15 +961,13 @@ namespace Roadie.Api.Services
public async Task<OperationResult<bool>> ScanInboundFolder(ApplicationUser user, bool isReadOnly = false) public async Task<OperationResult<bool>> ScanInboundFolder(ApplicationUser user, bool isReadOnly = false)
{ {
var d = new DirectoryInfo(Configuration.InboundFolder); var d = new DirectoryInfo(Configuration.InboundFolder);
var dest = new DirectoryInfo(Configuration.LibraryFolder); return await ScanFolder(user, d, isReadOnly);
return await ScanFolder(user, d, dest, isReadOnly);
} }
public async Task<OperationResult<bool>> ScanLibraryFolder(ApplicationUser user, bool isReadOnly = false) public async Task<OperationResult<bool>> ScanLibraryFolder(ApplicationUser user, bool isReadOnly = false)
{ {
var d = new DirectoryInfo(Configuration.LibraryFolder); var d = new DirectoryInfo(Configuration.LibraryFolder);
var dest = new DirectoryInfo(Configuration.LibraryFolder); return await ScanFolder(user, d, isReadOnly);
return await ScanFolder(user, d, dest, isReadOnly);
} }
public async Task<OperationResult<bool>> ScanRelease(ApplicationUser user, Guid releaseId, bool isReadOnly = false, bool wasDoneForInvalidTrackPlay = false) public async Task<OperationResult<bool>> ScanRelease(ApplicationUser user, Guid releaseId, bool isReadOnly = false, bool wasDoneForInvalidTrackPlay = false)
@ -1013,9 +1006,6 @@ namespace Roadie.Api.Services
TimeSpanInSeconds = (int)sw.Elapsed.TotalSeconds TimeSpanInSeconds = (int)sw.Elapsed.TotalSeconds
}); });
await DbContext.SaveChangesAsync(); await DbContext.SaveChangesAsync();
await LogAndPublish(
$"ScanRelease `{release}`, By User `{user}`, WasDoneForInvalidTrackPlay [{wasDoneForInvalidTrackPlay}]",
LogLevel.Information);
return new OperationResult<bool> return new OperationResult<bool>
{ {
IsSuccess = !errors.Any(), IsSuccess = !errors.Any(),
@ -1025,10 +1015,7 @@ namespace Roadie.Api.Services
}; };
} }
private void EventMessageLogger_Messages(object sender, EventMessage e) private void EventMessageLogger_Messages(object sender, EventMessage e) => Task.WaitAll(LogAndPublish(e.Message, e.Level));
{
Task.WaitAll(LogAndPublish(e.Message, e.Level));
}
private async Task LogAndPublish(string message, LogLevel level = LogLevel.Trace) private async Task LogAndPublish(string message, LogLevel level = LogLevel.Trace)
{ {
@ -1058,7 +1045,7 @@ namespace Roadie.Api.Services
await ScanActivityHub.Clients.All.SendAsync("SendSystemActivity", message); await ScanActivityHub.Clients.All.SendAsync("SendSystemActivity", message);
} }
private async Task<OperationResult<bool>> ScanFolder(ApplicationUser user, DirectoryInfo d, DirectoryInfo dest, bool isReadOnly) private async Task<OperationResult<bool>> ScanFolder(ApplicationUser user, DirectoryInfo d, bool isReadOnly)
{ {
var sw = new Stopwatch(); var sw = new Stopwatch();
sw.Start(); sw.Start();

View file

@ -192,7 +192,7 @@ namespace Roadie.Api.Services
await DbContext.SaveChangesAsync(); await DbContext.SaveChangesAsync();
// TODO delete artist folder if empty? // TODO delete artist folder if empty?
CacheManager.ClearRegion(artist.CacheRegion); CacheManager.ClearRegion(artist.CacheRegion);
Logger.LogInformation(string.Format("x DeleteArtist [{0}]", artist.Id)); Logger.LogWarning("User `{0}` deleted Artist `{1}]`", user, artist);
isSuccess = true; isSuccess = true;
} }
} }
@ -217,6 +217,8 @@ namespace Roadie.Api.Services
var sw = new Stopwatch(); var sw = new Stopwatch();
sw.Start(); sw.Start();
int? rowCount = null;
IQueryable<int> favoriteArtistIds = null; IQueryable<int> favoriteArtistIds = null;
if (request.FilterFavoriteOnly) if (request.FilterFavoriteOnly)
{ {
@ -273,8 +275,29 @@ namespace Roadie.Api.Services
var normalizedFilterValue = !string.IsNullOrEmpty(request.FilterValue) var normalizedFilterValue = !string.IsNullOrEmpty(request.FilterValue)
? request.FilterValue.ToAlphanumericName() ? request.FilterValue.ToAlphanumericName()
: null; : null;
int[] randomArtistIds = null;
if (doRandomize ??false)
{
var randomLimit = request.Limit ?? roadieUser?.RandomReleaseLimit ?? request.LimitValue;
var userId = roadieUser?.Id ?? -1;
//// This is MySQL specific but I can't figure out how else to get random without throwing EF local evaluate warnings.
var sql = @"select a.id
FROM `artist` a
WHERE(a.id NOT IN(select artistId FROM `userartist` where userId = {1} and isDisliked = 1))
OR(a.id IN(select artistId FROM `userartist` where userId = {1} and isFavorite = 1)
AND {2} = 0)
order BY RIGHT(HEX((1 << 24) * (1 + RAND())), 6)
LIMIT 0, {0}";
randomArtistIds = (from a in DbContext.Artists.FromSql(sql, randomLimit, userId, request.FilterFavoriteOnly ? "1" : "0")
select a.Id).ToArray();
rowCount = DbContext.Artists.Count();
}
var result = (from a in DbContext.Artists var result = (from a in DbContext.Artists
where !onlyWithReleases || a.ReleaseCount > 0 where !onlyWithReleases || a.ReleaseCount > 0
where randomArtistIds == null || randomArtistIds.Contains(a.Id)
where request.FilterToArtistId == null || a.RoadieId == request.FilterToArtistId where request.FilterToArtistId == null || a.RoadieId == request.FilterToArtistId
where request.FilterMinimumRating == null || a.Rating >= request.FilterMinimumRating.Value where request.FilterMinimumRating == null || a.Rating >= request.FilterMinimumRating.Value
where request.FilterValue == "" || where request.FilterValue == "" ||
@ -311,17 +334,14 @@ namespace Roadie.Api.Services
ReleaseCount = a.ReleaseCount, ReleaseCount = a.ReleaseCount,
TrackCount = a.TrackCount, TrackCount = a.TrackCount,
SortName = a.SortName SortName = a.SortName
}).Distinct(); });
ArtistList[] rows; ArtistList[] rows;
var rowCount = result.Count(); rowCount = rowCount ?? result.Count();
if (doRandomize ?? false) if (doRandomize ?? false)
{ {
var randomLimit = roadieUser?.RandomReleaseLimit ?? request.Limit; rows = result.ToArray();
request.Limit = request.LimitValue > randomLimit ? randomLimit : request.LimitValue;
rows = result.OrderBy(x => x.RandomSortId)
.Take(request.LimitValue)
.ToArray();
} }
else else
{ {
@ -379,7 +399,7 @@ namespace Roadie.Api.Services
sw.Stop(); sw.Stop();
return new Library.Models.Pagination.PagedResult<ArtistList> return new Library.Models.Pagination.PagedResult<ArtistList>
{ {
TotalCount = rowCount, TotalCount = rowCount.Value,
CurrentPage = request.PageValue, CurrentPage = request.PageValue,
TotalPages = (int)Math.Ceiling((double)rowCount / request.LimitValue), TotalPages = (int)Math.Ceiling((double)rowCount / request.LimitValue),
OperationTime = sw.ElapsedMilliseconds, OperationTime = sw.ElapsedMilliseconds,
@ -426,7 +446,7 @@ namespace Roadie.Api.Services
{ {
CacheManager.ClearRegion(artistToMerge.CacheRegion); CacheManager.ClearRegion(artistToMerge.CacheRegion);
CacheManager.ClearRegion(mergeIntoArtist.CacheRegion); CacheManager.ClearRegion(mergeIntoArtist.CacheRegion);
Logger.LogInformation("MergeArtists `{0}` => `{1}`, By User `{2}`", artistToMerge, mergeIntoArtist, Logger.LogWarning("MergeArtists `{0}` => `{1}`, By User `{2}`", artistToMerge, mergeIntoArtist,
user); user);
} }
} }
@ -487,7 +507,7 @@ namespace Roadie.Api.Services
await DbContext.SaveChangesAsync(); await DbContext.SaveChangesAsync();
sw.Stop(); sw.Stop();
CacheManager.ClearRegion(artist.CacheRegion); CacheManager.ClearRegion(artist.CacheRegion);
Logger.LogInformation("Scanned RefreshArtistMetadata [{0}], OperationTime [{1}]", Logger.LogTrace("Scanned RefreshArtistMetadata [{0}], OperationTime [{1}]",
artist.ToString(), sw.ElapsedMilliseconds); artist.ToString(), sw.ElapsedMilliseconds);
} }
else else
@ -579,7 +599,7 @@ namespace Roadie.Api.Services
artist.LastUpdated = DateTime.UtcNow; artist.LastUpdated = DateTime.UtcNow;
await DbContext.SaveChangesAsync(); await DbContext.SaveChangesAsync();
CacheManager.ClearRegion(artist.CacheRegion); CacheManager.ClearRegion(artist.CacheRegion);
Logger.LogInformation("Update Thumbnail using Artist File [{0}]", iName); Logger.LogTrace("Update Thumbnail using Artist File [{0}]", iName);
} }
} }
@ -675,7 +695,7 @@ namespace Roadie.Api.Services
didRenameArtist = true; didRenameArtist = true;
if (Directory.Exists(originalArtistFolder)) if (Directory.Exists(originalArtistFolder))
{ {
Logger.LogInformation("Moving Artist From Folder [{0}] -> [{1}]", originalArtistFolder, newArtistFolder); Logger.LogTrace("Moving Artist From Folder [{0}] -> [{1}]", originalArtistFolder, newArtistFolder);
Directory.Move(originalArtistFolder, newArtistFolder); Directory.Move(originalArtistFolder, newArtistFolder);
} }
} }
@ -1460,7 +1480,7 @@ namespace Roadie.Api.Services
if (!Directory.Exists(artistFolder)) if (!Directory.Exists(artistFolder))
{ {
Directory.CreateDirectory(artistFolder); Directory.CreateDirectory(artistFolder);
Logger.LogInformation("Created Artist Folder [0] for `artist`", artistFolder, artist); Logger.LogTrace("Created Artist Folder [0] for `artist`", artistFolder, artist);
} }
// Save unaltered image to artist file // Save unaltered image to artist file

View file

@ -154,7 +154,7 @@ namespace Roadie.Api.Services
} }
sw.Stop(); sw.Stop();
Logger.LogInformation($"DeleteCollection `{collection}`, By User `{user}`"); Logger.LogWarning($"DeleteCollection `{collection}`, By User `{user}`");
return new OperationResult<bool> return new OperationResult<bool>
{ {
IsSuccess = !errors.Any(), IsSuccess = !errors.Any(),
@ -194,19 +194,43 @@ namespace Roadie.Api.Services
} }
var result = from c in collections var result = from c in collections
let collectionCount = (from crc in DbContext.CollectionReleases
where crc.CollectionId == c.Id
select crc.Id).Count()
where request.FilterValue.Length == 0 || where request.FilterValue.Length == 0 ||
request.FilterValue.Length > 0 && c.Name.Contains(request.Filter) request.FilterValue.Length > 0 && c.Name.Contains(request.Filter)
where request.FilterToStatusValue == Statuses.Ok || c.Status == request.FilterToStatusValue where request.FilterToStatusValue == Statuses.Ok || c.Status == request.FilterToStatusValue
select CollectionList.FromDataCollection(c, (from crc in DbContext.CollectionReleases select new CollectionList
where crc.CollectionId == c.Id {
select crc.Id).Count(), MakeCollectionThumbnailImage(c.RoadieId)); DatabaseId = c.Id,
Collection = new DataToken
{
Text = c.Name,
Value = c.RoadieId.ToString()
},
Id = c.RoadieId,
CollectionCount = c.CollectionCount,
CollectionType = (c.CollectionType ?? CollectionType.Unknown).ToString(),
CollectionFoundCount = collectionCount,
CreatedDate = c.CreatedDate,
IsLocked = c.IsLocked,
LastUpdated = c.LastUpdated,
Thumbnail = MakeCollectionThumbnailImage(c.RoadieId)
};
var sortBy = string.IsNullOrEmpty(request.Sort) var sortBy = string.IsNullOrEmpty(request.Sort)
? request.OrderValue(new Dictionary<string, string> { { "Collection.Text", "ASC" } }) ? request.OrderValue(new Dictionary<string, string> { { "Collection.Text", "ASC" } })
: request.OrderValue(); : request.OrderValue();
var rowCount = result.Count(); var rowCount = result.Count();
var rows = result.OrderBy(sortBy).Skip(request.SkipValue).Take(request.LimitValue).ToArray(); var rows = result
.OrderBy(sortBy)
.Skip(request.SkipValue)
.Take(request.LimitValue)
.ToArray();
if (request.FilterToStatusValue == Statuses.Incomplete) if (request.FilterToStatusValue == Statuses.Incomplete)
{
rows = rows.OrderByDescending(x => x.PercentComplete).ThenBy(x => x.SortName).ToArray(); rows = rows.OrderByDescending(x => x.PercentComplete).ThenBy(x => x.SortName).ToArray();
}
sw.Stop(); sw.Stop();
return Task.FromResult(new Library.Models.Pagination.PagedResult<CollectionList> return Task.FromResult(new Library.Models.Pagination.PagedResult<CollectionList>
{ {

View file

@ -109,7 +109,7 @@ namespace Roadie.Api.Services
_addedArtistIds.AddRange(ArtistLookupEngine.AddedArtistIds); _addedArtistIds.AddRange(ArtistLookupEngine.AddedArtistIds);
_addedReleaseIds.AddRange(ReleaseLookupEngine.AddedReleaseIds); _addedReleaseIds.AddRange(ReleaseLookupEngine.AddedReleaseIds);
_addedTrackIds.AddRange(ReleaseLookupEngine.AddedTrackIds); _addedTrackIds.AddRange(ReleaseLookupEngine.AddedTrackIds);
Logger.LogInformation("** Completed! Processed Folder [{0}]: Processed Files [{1}] : Elapsed Time [{2}]", folder.FullName, processedFiles, sw.Elapsed); Logger.LogInformation("Completed! Processed Folder [{0}]: Processed Files [{1}] : Elapsed Time [{2}]", folder.FullName, processedFiles, sw.Elapsed);
return new OperationResult<bool> return new OperationResult<bool>
{ {
IsSuccess = !errors.Any(), IsSuccess = !errors.Any(),
@ -143,7 +143,7 @@ namespace Roadie.Api.Services
if (!doJustInfo) if (!doJustInfo)
{ {
fileInFolder.Delete(); fileInFolder.Delete();
Logger.LogInformation("x Deleted File [{0}], Was found in in FileExtensionsToDelete", Logger.LogTrace("Deleted File [{0}], Was found in in FileExtensionsToDelete",
fileInFolder.Name); fileInFolder.Name);
} }
} }

View file

@ -1,5 +1,6 @@
using Mapster; using Mapster;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Roadie.Library; using Roadie.Library;
using Roadie.Library.Caching; using Roadie.Library.Caching;
@ -69,7 +70,7 @@ namespace Roadie.Api.Services
File.Delete(genreImageFilename); File.Delete(genreImageFilename);
} }
Logger.LogInformation("User `{0}` deleted Genre `{1}]`", user, genre); Logger.LogWarning("User `{0}` deleted Genre `{1}]`", user, genre);
CacheManager.ClearRegion(genre.CacheRegion); CacheManager.ClearRegion(genre.CacheRegion);
sw.Stop(); sw.Stop();
return new OperationResult<bool> return new OperationResult<bool>
@ -187,13 +188,31 @@ namespace Roadie.Api.Services
var sw = new Stopwatch(); var sw = new Stopwatch();
sw.Start(); sw.Start();
int? rowCount = null;
if (!string.IsNullOrEmpty(request.Sort)) if (!string.IsNullOrEmpty(request.Sort))
{ {
request.Sort = request.Sort.Replace("createdDate", "createdDateTime"); request.Sort = request.Sort.Replace("createdDate", "createdDateTime");
request.Sort = request.Sort.Replace("lastUpdated", "lastUpdatedDateTime"); request.Sort = request.Sort.Replace("lastUpdated", "lastUpdatedDateTime");
} }
int[] randomGenreIds = null;
if (doRandomize ?? false)
{
var randomLimit = request.Limit ?? roadieUser?.RandomReleaseLimit ?? request.LimitValue;
// This is MySQL specific but I can't figure out how else to get random without throwing EF local evaluate warnings.
var sql = @"select g.id
FROM `genre` g
order BY RIGHT( HEX( (1<<24) * (1+RAND()) ), 6)
LIMIT 0, {0}";
randomGenreIds = (from l in DbContext.Genres.FromSql(sql, randomLimit)
select l.Id).ToArray();
rowCount = DbContext.Genres.Count();
}
var result = from g in DbContext.Genres var result = from g in DbContext.Genres
where randomGenreIds == null || randomGenreIds.Contains(g.Id)
let releaseCount = (from rg in DbContext.ReleaseGenres let releaseCount = (from rg in DbContext.ReleaseGenres
where rg.GenreId == g.Id where rg.GenreId == g.Id
select rg.Id).Count() select rg.Id).Count()
@ -218,12 +237,10 @@ namespace Roadie.Api.Services
}; };
GenreList[] rows; GenreList[] rows;
var rowCount = result.Count(); rowCount = rowCount ?? result.Count();
if (doRandomize ?? false) if (doRandomize ?? false)
{ {
var randomLimit = roadieUser?.RandomReleaseLimit ?? 100; rows = result.ToArray();
request.Limit = request.LimitValue > randomLimit ? randomLimit : request.LimitValue;
rows = result.OrderBy(x => x.RandomSortId).Skip(request.SkipValue).Take(request.LimitValue).ToArray();
} }
else else
{ {
@ -236,7 +253,7 @@ namespace Roadie.Api.Services
sw.Stop(); sw.Stop();
return Task.FromResult(new Library.Models.Pagination.PagedResult<GenreList> return Task.FromResult(new Library.Models.Pagination.PagedResult<GenreList>
{ {
TotalCount = rowCount, TotalCount = rowCount.Value,
CurrentPage = request.PageValue, CurrentPage = request.PageValue,
TotalPages = (int)Math.Ceiling((double)rowCount / request.LimitValue), TotalPages = (int)Math.Ceiling((double)rowCount / request.LimitValue),
OperationTime = sw.ElapsedMilliseconds, OperationTime = sw.ElapsedMilliseconds,

View file

@ -106,7 +106,7 @@ namespace Roadie.Api.Services
if (image.ArtistId.HasValue) CacheManager.ClearRegion(data.Artist.CacheRegionUrn(image.Artist.RoadieId)); if (image.ArtistId.HasValue) CacheManager.ClearRegion(data.Artist.CacheRegionUrn(image.Artist.RoadieId));
if (image.ReleaseId.HasValue) CacheManager.ClearRegion(data.Release.CacheRegionUrn(image.Release.RoadieId)); if (image.ReleaseId.HasValue) CacheManager.ClearRegion(data.Release.CacheRegionUrn(image.Release.RoadieId));
CacheManager.ClearRegion(data.Image.CacheRegionUrn(id)); CacheManager.ClearRegion(data.Image.CacheRegionUrn(id));
Logger.LogInformation($"Deleted Image [{id}], By User [{user}]"); Logger.LogWarning("User `{0}` deleted Image `{1}]`", user, image);
sw.Stop(); sw.Stop();
return new OperationResult<bool> return new OperationResult<bool>
{ {
@ -241,7 +241,7 @@ namespace Roadie.Api.Services
artistFolder = artist.ArtistFileFolder(Configuration); artistFolder = artist.ArtistFileFolder(Configuration);
if (!Directory.Exists(artistFolder)) if (!Directory.Exists(artistFolder))
{ {
Logger.LogWarning($"Artist Folder [{artistFolder}], Not Found For Artist `{artist}`"); Logger.LogTrace($"Artist Folder [{artistFolder}], Not Found For Artist `{artist}`");
} }
else else
{ {
@ -294,7 +294,7 @@ namespace Roadie.Api.Services
artistFolder = artist.ArtistFileFolder(Configuration); artistFolder = artist.ArtistFileFolder(Configuration);
if (!Directory.Exists(artistFolder)) if (!Directory.Exists(artistFolder))
{ {
Logger.LogWarning($"Artist Folder [{artistFolder}], Not Found For Artist `{artist}`"); Logger.LogTrace($"Artist Folder [{artistFolder}], Not Found For Artist `{artist}`");
} }
else else
{ {
@ -593,7 +593,7 @@ namespace Roadie.Api.Services
artistFolder = release.Artist.ArtistFileFolder(Configuration); artistFolder = release.Artist.ArtistFileFolder(Configuration);
if (!Directory.Exists(artistFolder)) if (!Directory.Exists(artistFolder))
{ {
Logger.LogWarning($"Artist Folder [{artistFolder}], Not Found For Artist `{release.Artist}`"); Logger.LogTrace($"Artist Folder [{artistFolder}], Not Found For Artist `{release.Artist}`");
} }
else else
{ {
@ -656,7 +656,7 @@ namespace Roadie.Api.Services
artistFolder = release.Artist.ArtistFileFolder(Configuration); artistFolder = release.Artist.ArtistFileFolder(Configuration);
if (!Directory.Exists(artistFolder)) if (!Directory.Exists(artistFolder))
{ {
Logger.LogWarning($"Artist Folder [{artistFolder}], Not Found For Artist `{release.Artist}`"); Logger.LogTrace($"Artist Folder [{artistFolder}], Not Found For Artist `{release.Artist}`");
} }
else else
{ {

View file

@ -59,7 +59,7 @@ namespace Roadie.Api.Services
File.Delete(labelImageFilename); File.Delete(labelImageFilename);
} }
Logger.LogInformation("User `{0}` deleted Label `{1}]`", user, label); Logger.LogWarning("User `{0}` deleted Label `{1}]`", user, label);
CacheManager.ClearRegion(label.CacheRegion); CacheManager.ClearRegion(label.CacheRegion);
sw.Stop(); sw.Stop();
return new OperationResult<bool> return new OperationResult<bool>
@ -120,6 +120,8 @@ namespace Roadie.Api.Services
var sw = new Stopwatch(); var sw = new Stopwatch();
sw.Start(); sw.Start();
int? rowCount = null;
if (!string.IsNullOrEmpty(request.Sort)) if (!string.IsNullOrEmpty(request.Sort))
{ {
request.Sort = request.Sort.Replace("createdDate", "createdDateTime"); request.Sort = request.Sort.Replace("createdDate", "createdDateTime");
@ -129,7 +131,24 @@ namespace Roadie.Api.Services
var normalizedFilterValue = !string.IsNullOrEmpty(request.FilterValue) var normalizedFilterValue = !string.IsNullOrEmpty(request.FilterValue)
? request.FilterValue.ToAlphanumericName() ? request.FilterValue.ToAlphanumericName()
: null; : null;
int[] randomLabelIds = null;
if (doRandomize ?? false)
{
var randomLimit = request.Limit ?? roadieUser?.RandomReleaseLimit ?? request.LimitValue;
// This is MySQL specific but I can't figure out how else to get random without throwing EF local evaluate warnings.
var sql = @"select l.id
FROM `label` l
order BY RIGHT( HEX( (1<<24) * (1+RAND()) ), 6)
LIMIT 0, {0}";
randomLabelIds = (from l in DbContext.Labels.FromSql(sql, randomLimit)
select l.Id).ToArray();
rowCount = DbContext.Labels.Count();
}
var result = from l in DbContext.Labels var result = from l in DbContext.Labels
where randomLabelIds == null || randomLabelIds.Contains(l.Id)
where request.FilterValue == "" || ( where request.FilterValue == "" || (
l.Name.Contains(request.FilterValue) || l.Name.Contains(request.FilterValue) ||
l.SortName.Contains(request.FilterValue) || l.SortName.Contains(request.FilterValue) ||
@ -154,27 +173,27 @@ namespace Roadie.Api.Services
Thumbnail = MakeLabelThumbnailImage(l.RoadieId) Thumbnail = MakeLabelThumbnailImage(l.RoadieId)
}; };
LabelList[] rows = null; LabelList[] rows = null;
var rowCount = result.Count(); rowCount = rowCount ?? result.Count();
if (doRandomize ?? false) if (doRandomize ?? false)
{ {
var randomLimit = roadieUser?.RandomReleaseLimit ?? request.Limit; rows = result.ToArray();
request.Limit = request.LimitValue > randomLimit ? randomLimit : request.LimitValue;
rows = result.OrderBy(x => x.RandomSortId)
.Take(request.LimitValue)
.ToArray();
} }
else else
{ {
var sortBy = string.IsNullOrEmpty(request.Sort) var sortBy = string.IsNullOrEmpty(request.Sort)
? request.OrderValue(new Dictionary<string, string> { { "SortName", "ASC" }, { "Label.Text", "ASC" } }) ? request.OrderValue(new Dictionary<string, string> { { "SortName", "ASC" }, { "Label.Text", "ASC" } })
: request.OrderValue(); : request.OrderValue();
rows = result.OrderBy(sortBy).Skip(request.SkipValue).Take(request.LimitValue).ToArray(); rows = result
.OrderBy(sortBy)
.Skip(request.SkipValue)
.Take(request.LimitValue)
.ToArray();
} }
sw.Stop(); sw.Stop();
return Task.FromResult(new Library.Models.Pagination.PagedResult<LabelList> return Task.FromResult(new Library.Models.Pagination.PagedResult<LabelList>
{ {
TotalCount = rowCount, TotalCount = rowCount.Value,
CurrentPage = request.PageValue, CurrentPage = request.PageValue,
TotalPages = (int)Math.Ceiling((double)rowCount / request.LimitValue), TotalPages = (int)Math.Ceiling((double)rowCount / request.LimitValue),
OperationTime = sw.ElapsedMilliseconds, OperationTime = sw.ElapsedMilliseconds,

View file

@ -188,7 +188,7 @@ namespace Roadie.Api.Services
File.Delete(playlistImageFilename); File.Delete(playlistImageFilename);
} }
Logger.LogInformation("User `{0}` deleted Playlist `{1}]`", user, playlist); Logger.LogWarning("User `{0}` deleted Playlist `{1}]`", user, playlist);
CacheManager.ClearRegion(playlist.CacheRegion); CacheManager.ClearRegion(playlist.CacheRegion);
sw.Stop(); sw.Stop();
return new OperationResult<bool> return new OperationResult<bool>
@ -199,14 +199,14 @@ namespace Roadie.Api.Services
}; };
} }
public Task<Library.Models.Pagination.PagedResult<PlaylistList>> List(PagedRequest request, public Task<Library.Models.Pagination.PagedResult<PlaylistList>> List(PagedRequest request, User roadieUser = null)
User roadieUser = null)
{ {
var sw = new Stopwatch(); var sw = new Stopwatch();
sw.Start(); sw.Start();
var playlistWithArtistTrackIds = new int[0]; var playlistWithArtistTrackIds = new int[0];
if (request.FilterToArtistId.HasValue) if (request.FilterToArtistId.HasValue)
{
playlistWithArtistTrackIds = (from pl in DbContext.Playlists playlistWithArtistTrackIds = (from pl in DbContext.Playlists
join pltr in DbContext.PlaylistTracks on pl.Id equals pltr.PlayListId join pltr in DbContext.PlaylistTracks on pl.Id equals pltr.PlayListId
join t in DbContext.Tracks on pltr.TrackId equals t.Id join t in DbContext.Tracks on pltr.TrackId equals t.Id
@ -215,9 +215,11 @@ namespace Roadie.Api.Services
join a in DbContext.Artists on r.ArtistId equals a.Id join a in DbContext.Artists on r.ArtistId equals a.Id
where a.RoadieId == request.FilterToArtistId where a.RoadieId == request.FilterToArtistId
select pl.Id select pl.Id
).ToArray(); ).ToArray();
}
var playlistReleaseTrackIds = new int[0]; var playlistReleaseTrackIds = new int[0];
if (request.FilterToReleaseId.HasValue) if (request.FilterToReleaseId.HasValue)
{
playlistReleaseTrackIds = (from pl in DbContext.Playlists playlistReleaseTrackIds = (from pl in DbContext.Playlists
join pltr in DbContext.PlaylistTracks on pl.Id equals pltr.PlayListId join pltr in DbContext.PlaylistTracks on pl.Id equals pltr.PlayListId
join t in DbContext.Tracks on pltr.TrackId equals t.Id join t in DbContext.Tracks on pltr.TrackId equals t.Id
@ -225,24 +227,46 @@ namespace Roadie.Api.Services
join r in DbContext.Releases on rm.ReleaseId equals r.Id join r in DbContext.Releases on rm.ReleaseId equals r.Id
where r.RoadieId == request.FilterToReleaseId where r.RoadieId == request.FilterToReleaseId
select pl.Id select pl.Id
).ToArray(); ).ToArray();
}
var result = from pl in DbContext.Playlists var result = from pl in DbContext.Playlists
join u in DbContext.Users on pl.UserId equals u.Id join u in DbContext.Users on pl.UserId equals u.Id
where request.FilterToPlaylistId == null || pl.RoadieId == request.FilterToPlaylistId where request.FilterToPlaylistId == null || pl.RoadieId == request.FilterToPlaylistId
where request.FilterToArtistId == null || playlistWithArtistTrackIds.Contains(pl.Id) where request.FilterToArtistId == null || playlistWithArtistTrackIds.Contains(pl.Id)
where request.FilterToReleaseId == null || playlistReleaseTrackIds.Contains(pl.Id) where request.FilterToReleaseId == null || playlistReleaseTrackIds.Contains(pl.Id)
where roadieUser == null && pl.IsPublic || roadieUser != null && u.RoadieId == roadieUser.UserId || where roadieUser == null && pl.IsPublic || roadieUser != null && u.RoadieId == roadieUser.UserId || pl.IsPublic
pl.IsPublic where request.FilterValue.Length == 0 || request.FilterValue.Length > 0 && pl.Name != null && pl.Name.Contains(request.FilterValue)
where request.FilterValue.Length == 0 || request.FilterValue.Length > 0 && pl.Name != null && select new PlaylistList
pl.Name.Contains(request.FilterValue) {
select PlaylistList.FromDataPlaylist(pl, u, MakePlaylistThumbnailImage(pl.RoadieId), Playlist = new DataToken
MakeUserThumbnailImage(u.RoadieId)); {
Text = pl.Name,
Value = pl.RoadieId.ToString()
},
User = new DataToken
{
Text = u.UserName,
Value = u.RoadieId.ToString()
},
PlaylistCount = pl.TrackCount,
IsPublic = pl.IsPublic,
Duration = pl.Duration,
TrackCount = pl.TrackCount,
CreatedDate = pl.CreatedDate,
LastUpdated = pl.LastUpdated,
UserThumbnail = MakeUserThumbnailImage(u.RoadieId),
Id = pl.RoadieId,
Thumbnail = MakePlaylistThumbnailImage(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" } })
: request.OrderValue(); : request.OrderValue();
var rowCount = result.Count(); var rowCount = result.Count();
var rows = result.OrderBy(sortBy).Skip(request.SkipValue).Take(request.LimitValue).ToArray(); var rows = result
.OrderBy(sortBy)
.Skip(request.SkipValue)
.Take(request.LimitValue)
.ToArray();
sw.Stop(); sw.Stop();
return Task.FromResult(new Library.Models.Pagination.PagedResult<PlaylistList> return Task.FromResult(new Library.Models.Pagination.PagedResult<PlaylistList>
{ {

View file

@ -104,26 +104,26 @@ namespace Roadie.Api.Services
{ {
var sw = Stopwatch.StartNew(); var sw = Stopwatch.StartNew();
sw.Start(); sw.Start();
var cacheKey = string.Format("urn:release_by_id_operation:{0}:{1}", id, var cacheKey = string.Format("urn:release_by_id_operation:{0}:{1}", id, includes == null ? "0" : string.Join("|", includes));
includes == null ? "0" : string.Join("|", includes)); var result = await CacheManager.GetAsync(cacheKey,async () => { return await ReleaseByIdAction(id, includes); }, data.Artist.CacheRegionUrn(id));
var result = await CacheManager.GetAsync(cacheKey,
async () => { return await ReleaseByIdAction(id, includes); }, data.Artist.CacheRegionUrn(id));
if (result?.Data != null && roadieUser != null) if (result?.Data != null && roadieUser != null)
{ {
var release = GetRelease(id); var release = GetRelease(id);
var userBookmarkResult = var userBookmarkResult = await BookmarkService.List(roadieUser, new PagedRequest(), false, BookmarkType.Release);
await BookmarkService.List(roadieUser, new PagedRequest(), false, BookmarkType.Release);
if (userBookmarkResult.IsSuccess) if (userBookmarkResult.IsSuccess)
result.Data.UserBookmarked = {
userBookmarkResult?.Rows?.FirstOrDefault(x => result.Data.UserBookmarked = userBookmarkResult?.Rows?.FirstOrDefault(x => x.Bookmark.Value == release.RoadieId.ToString()) != null;
x.Bookmark.Value == release.RoadieId.ToString()) != null; }
if (result.Data.Medias != null) if (result.Data.Medias != null)
{ {
var user = GetUser(roadieUser.UserId); var user = GetUser(roadieUser.UserId);
foreach (var media in result.Data.Medias) foreach (var media in result.Data.Medias)
{
foreach (var track in media.Tracks) foreach (var track in media.Tracks)
{
track.TrackPlayUrl = MakeTrackPlayUrl(user, track.DatabaseId, track.Id); track.TrackPlayUrl = MakeTrackPlayUrl(user, track.DatabaseId, track.Id);
}
}
var releaseTrackIds = result.Data.Medias.SelectMany(x => x.Tracks).Select(x => x.Id); var releaseTrackIds = result.Data.Medias.SelectMany(x => x.Tracks).Select(x => x.Id);
var releaseUserTracks = (from ut in DbContext.UserTracks var releaseUserTracks = (from ut in DbContext.UserTracks
join t in DbContext.Tracks on ut.TrackId equals t.Id join t in DbContext.Tracks on ut.TrackId equals t.Id
@ -135,7 +135,9 @@ namespace Roadie.Api.Services
ut ut
}).ToArray(); }).ToArray();
if (releaseUserTracks != null && releaseUserTracks.Any()) if (releaseUserTracks != null && releaseUserTracks.Any())
{
foreach (var releaseUserTrack in releaseUserTracks) foreach (var releaseUserTrack in releaseUserTracks)
{
foreach (var media in result.Data.Medias) foreach (var media in result.Data.Medias)
{ {
var releaseTrack = media.Tracks.FirstOrDefault(x => x.Id == releaseUserTrack.t.RoadieId); var releaseTrack = media.Tracks.FirstOrDefault(x => x.Id == releaseUserTrack.t.RoadieId);
@ -149,17 +151,20 @@ namespace Roadie.Api.Services
PlayedCount = releaseUserTrack.ut.PlayedCount PlayedCount = releaseUserTrack.ut.PlayedCount
}; };
} }
}
}
} }
var userRelease = var userRelease = DbContext.UserReleases.FirstOrDefault(x => x.ReleaseId == release.Id && x.UserId == roadieUser.Id);
DbContext.UserReleases.FirstOrDefault(x => x.ReleaseId == release.Id && x.UserId == roadieUser.Id);
if (userRelease != null) if (userRelease != null)
{
result.Data.UserRating = new UserRelease result.Data.UserRating = new UserRelease
{ {
IsDisliked = userRelease.IsDisliked ?? false, IsDisliked = userRelease.IsDisliked ?? false,
IsFavorite = userRelease.IsFavorite ?? false, IsFavorite = userRelease.IsFavorite ?? false,
Rating = userRelease.Rating Rating = userRelease.Rating
}; };
}
if (result.Data.Comments.Any()) if (result.Data.Comments.Any())
{ {
var commentIds = result.Data.Comments.Select(x => x.DatabaseId).ToArray(); var commentIds = result.Data.Comments.Select(x => x.DatabaseId).ToArray();
@ -169,8 +174,7 @@ namespace Roadie.Api.Services
select cr).ToArray(); select cr).ToArray();
foreach (var comment in result.Data.Comments) foreach (var comment in result.Data.Comments)
{ {
var userCommentReaction = var userCommentReaction = userCommentReactions.FirstOrDefault(x => x.CommentId == comment.DatabaseId);
userCommentReactions.FirstOrDefault(x => x.CommentId == comment.DatabaseId);
comment.IsDisliked = userCommentReaction?.ReactionValue == CommentReaction.Dislike; comment.IsDisliked = userCommentReaction?.ReactionValue == CommentReaction.Dislike;
comment.IsLiked = userCommentReaction?.ReactionValue == CommentReaction.Like; comment.IsLiked = userCommentReaction?.ReactionValue == CommentReaction.Like;
} }
@ -193,22 +197,27 @@ namespace Roadie.Api.Services
{ {
var sw = new Stopwatch(); var sw = new Stopwatch();
sw.Start(); sw.Start();
int? rowCount = null;
IQueryable<int> collectionReleaseIds = null; IQueryable<int> collectionReleaseIds = null;
if (request.FilterToCollectionId.HasValue) if (request.FilterToCollectionId.HasValue)
{
collectionReleaseIds = from cr in DbContext.CollectionReleases collectionReleaseIds = from cr in DbContext.CollectionReleases
join c in DbContext.Collections on cr.CollectionId equals c.Id join c in DbContext.Collections on cr.CollectionId equals c.Id
join r in DbContext.Releases on cr.ReleaseId equals r.Id join r in DbContext.Releases on cr.ReleaseId equals r.Id
where c.RoadieId == request.FilterToCollectionId.Value where c.RoadieId == request.FilterToCollectionId.Value
orderby cr.ListNumber orderby cr.ListNumber
select r.Id; select r.Id;
}
IQueryable<int> favoriteReleaseIds = null; IQueryable<int> favoriteReleaseIds = null;
if (request.FilterFavoriteOnly) if (request.FilterFavoriteOnly)
{
favoriteReleaseIds = from a in DbContext.Releases favoriteReleaseIds = from a in DbContext.Releases
join ur in DbContext.UserReleases on a.Id equals ur.ReleaseId join ur in DbContext.UserReleases on a.Id equals ur.ReleaseId
where ur.IsFavorite ?? false where ur.IsFavorite ?? false
where roadieUser == null || ur.UserId == roadieUser.Id where roadieUser == null || ur.UserId == roadieUser.Id
select a.Id; select a.Id;
}
IQueryable<int> genreReleaseIds = null; IQueryable<int> genreReleaseIds = null;
var isFilteredToGenre = false; var isFilteredToGenre = false;
if(request.FilterToGenreId.HasValue) if(request.FilterToGenreId.HasValue)
@ -269,22 +278,48 @@ namespace Roadie.Api.Services
var normalizedFilterValue = !string.IsNullOrEmpty(request.FilterValue) var normalizedFilterValue = !string.IsNullOrEmpty(request.FilterValue)
? request.FilterValue.ToAlphanumericName() ? request.FilterValue.ToAlphanumericName()
: null; : null;
int[] randomReleaseIds = null;
if (doRandomize ?? false)
{
var randomLimit = request.Limit ?? roadieUser?.RandomReleaseLimit ?? request.LimitValue;
var userId = roadieUser?.Id ?? -1;
// This is MySQL specific but I can't figure out how else to get random without throwing EF local evaluate warnings.
var sql = @"select r.id
FROM `release` r
WHERE (r.id NOT IN (select releaseId FROM `userrelease` where userId = {1} and isDisliked = 1))
OR (r.id IN (select releaseId FROM `userrelease` where userId = {1} and isFavorite = 1)
AND {2} = 0)
order BY RIGHT( HEX( (1<<24) * (1+RAND()) ), 6)
LIMIT 0, {0}";
randomReleaseIds = (from a in DbContext.Releases.FromSql(sql, randomLimit, userId, request.FilterFavoriteOnly ? "1" : "0")
select a.Id).ToArray();
rowCount = DbContext.Releases.Count();
}
var result = (from r in DbContext.Releases var result = (from r in DbContext.Releases
join a in DbContext.Artists on r.ArtistId equals a.Id join a in DbContext.Artists on r.ArtistId equals a.Id
where randomReleaseIds == null || randomReleaseIds.Contains(r.Id)
where request.FilterMinimumRating == null || r.Rating >= request.FilterMinimumRating.Value where request.FilterMinimumRating == null || r.Rating >= request.FilterMinimumRating.Value
where request.FilterToArtistId == null || r.Artist.RoadieId == request.FilterToArtistId where request.FilterToArtistId == null || r.Artist.RoadieId == request.FilterToArtistId
where request.FilterToCollectionId == null || collectionReleaseIds.Contains(r.Id) where request.FilterToCollectionId == null || collectionReleaseIds.Contains(r.Id)
where !request.FilterFavoriteOnly || favoriteReleaseIds.Contains(r.Id) where !request.FilterFavoriteOnly || favoriteReleaseIds.Contains(r.Id)
where !isFilteredToGenre || genreReleaseIds.Contains(r.Id) where !isFilteredToGenre || genreReleaseIds.Contains(r.Id)
where request.FilterFromYear == null || where request.FilterFromYear == null ||
r.ReleaseDate != null && r.ReleaseDate.Value.Year <= request.FilterFromYear r.ReleaseDate != null && r.ReleaseDate.Value.Year <= request.FilterFromYear
where request.FilterToYear == null || where request.FilterToYear == null ||
r.ReleaseDate != null && r.ReleaseDate.Value.Year >= request.FilterToYear r.ReleaseDate != null && r.ReleaseDate.Value.Year >= request.FilterToYear
where request.FilterValue == "" || r.Title.Contains(request.FilterValue) || where request.FilterValue == "" ||
r.Title.Contains(request.FilterValue) ||
r.AlternateNames.Contains(request.FilterValue) || r.AlternateNames.Contains(request.FilterValue) ||
r.AlternateNames.Contains(normalizedFilterValue) r.AlternateNames.Contains(normalizedFilterValue)
where !isEqualFilter || r.Title.Equals(request.FilterValue) || where !isEqualFilter ||
r.AlternateNames.Equals(request.FilterValue) || r.AlternateNames.Equals(normalizedFilterValue) r.Title.Equals(request.FilterValue) ||
r.AlternateNames.Equals(request.FilterValue) ||
r.AlternateNames.Equals(normalizedFilterValue)
select new ReleaseList select new ReleaseList
{ {
DatabaseId = r.Id, DatabaseId = r.Id,
@ -315,37 +350,53 @@ namespace Roadie.Api.Services
TrackCount = r.TrackCount, TrackCount = r.TrackCount,
TrackPlayedCount = r.PlayedCount TrackPlayedCount = r.PlayedCount
} }
).Distinct(); );
ReleaseList[] rows = null; ReleaseList[] rows = null;
var rowCount = result.Count(); rowCount = rowCount ?? result.Count();
if (doRandomize ?? false) if (doRandomize ?? false)
{ {
var randomLimit = roadieUser?.RandomReleaseLimit ?? request.Limit; rows = result.ToArray();
request.Limit = request.LimitValue > randomLimit ? randomLimit : request.LimitValue;
rows = result.OrderBy(x => x.RandomSortId)
.Take(request.LimitValue)
.ToArray();
} }
else else
{ {
string sortBy = null; string sortBy = null;
if (request.ActionValue == User.ActionKeyUserRated) if (request.ActionValue == User.ActionKeyUserRated)
{
sortBy = request.OrderValue(new Dictionary<string, string> { { "Rating", "DESC" } }); sortBy = request.OrderValue(new Dictionary<string, string> { { "Rating", "DESC" } });
}
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> { { "ReleaseDate", "ASC" }, { "Release.Text", "ASC" } });
}
else else
{
sortBy = request.OrderValue(new Dictionary<string, string> { { "Release.Text", "ASC" } }); sortBy = request.OrderValue(new Dictionary<string, string> { { "Release.Text", "ASC" } });
if (request.FilterRatedOnly) result = result.Where(x => x.Rating.HasValue); }
if (request.FilterRatedOnly)
{
result = result.Where(x => x.Rating.HasValue);
}
if (request.FilterMinimumRating.HasValue) if (request.FilterMinimumRating.HasValue)
result = result.Where(x => {
x.Rating.HasValue && x.Rating.Value >= request.FilterMinimumRating.Value); result = result.Where(x => x.Rating.HasValue && x.Rating.Value >= request.FilterMinimumRating.Value);
}
if (request.FilterToCollectionId.HasValue) if (request.FilterToCollectionId.HasValue)
{
rows = result.ToArray(); rows = result.ToArray();
}
else else
rows = result.OrderBy(sortBy).Skip(request.SkipValue).Take(request.LimitValue).ToArray(); {
rows = result
.OrderBy(sortBy)
.Skip(request.SkipValue)
.Take(request.LimitValue)
.ToArray();
}
} }
if (rows.Any()) if (rows.Any())
@ -415,9 +466,14 @@ namespace Roadie.Api.Services
// Resort the list for the collection by listNumber // Resort the list for the collection by listNumber
if (request.FilterToStatusValue != Statuses.Ok) if (request.FilterToStatusValue != Statuses.Ok)
{
newRows = newRows.Where(x => x.Status == request.FilterToStatusValue).ToList(); newRows = newRows.Where(x => x.Status == request.FilterToStatusValue).ToList();
rows = newRows.OrderBy(x => x.ListNumber).Skip(request.SkipValue).Take(request.LimitValue) }
.ToArray(); rows = newRows
.OrderBy(x => x.ListNumber)
.Skip(request.SkipValue)
.Take(request.LimitValue)
.ToArray();
rowCount = collection.CollectionCount; rowCount = collection.CollectionCount;
} }
@ -487,7 +543,7 @@ namespace Roadie.Api.Services
sw.Stop(); sw.Stop();
return Task.FromResult(new Library.Models.Pagination.PagedResult<ReleaseList> return Task.FromResult(new Library.Models.Pagination.PagedResult<ReleaseList>
{ {
TotalCount = rowCount, TotalCount = rowCount.Value,
CurrentPage = request.PageValue, CurrentPage = request.PageValue,
TotalPages = (int)Math.Ceiling((double)rowCount / request.LimitValue), TotalPages = (int)Math.Ceiling((double)rowCount / request.LimitValue),
OperationTime = sw.ElapsedMilliseconds, OperationTime = sw.ElapsedMilliseconds,
@ -829,7 +885,7 @@ namespace Roadie.Api.Services
if (File.Exists(trackPath)) if (File.Exists(trackPath))
{ {
File.Delete(trackPath); File.Delete(trackPath);
Logger.LogWarning("x For Release [{0}], Deleted File [{1}]", release.Id, trackPath); Logger.LogWarning("For Release [{0}], Deleted File [{1}]", release.Id, trackPath);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -872,6 +928,7 @@ namespace Roadie.Api.Services
foreach (var releaseLabelId in releaseLabelIds) foreach (var releaseLabelId in releaseLabelIds)
await UpdateLabelCounts(releaseLabelId, now); await UpdateLabelCounts(releaseLabelId, now);
sw.Stop(); sw.Stop();
Logger.LogWarning("User `{0}` deleted Release `{1}]`", user, release);
return new OperationResult<bool> return new OperationResult<bool>
{ {
Data = result, Data = result,
@ -964,7 +1021,7 @@ namespace Roadie.Api.Services
} }
zipFileName = $"{release.Artist.Name}_{release.Title}.zip".ToFileNameFriendly(); zipFileName = $"{release.Artist.Name}_{release.Title}.zip".ToFileNameFriendly();
Logger.LogInformation( Logger.LogTrace(
$"User `{roadieUser}` downloaded Release `{release}` ZipFileName [{zipFileName}], Zip Size [{zipBytes?.Length}]"); $"User `{roadieUser}` downloaded Release `{release}` ZipFileName [{zipFileName}], Zip Size [{zipBytes?.Length}]");
} }
catch (Exception ex) catch (Exception ex)
@ -1611,13 +1668,13 @@ namespace Roadie.Api.Services
var release = GetRelease(id); var release = GetRelease(id);
if (release == null) if (release == null)
{
return new OperationResult<Release>(true, string.Format("Release Not Found [{0}]", id)); return new OperationResult<Release>(true, string.Format("Release Not Found [{0}]", id));
}
var result = release.Adapt<Release>(); var result = release.Adapt<Release>();
result.Artist = result.Artist = ArtistList.FromDataArtist(release.Artist, MakeArtistThumbnailImage(release.Artist.RoadieId));
ArtistList.FromDataArtist(release.Artist, MakeArtistThumbnailImage(release.Artist.RoadieId));
result.Thumbnail = MakeReleaseThumbnailImage(release.RoadieId); result.Thumbnail = MakeReleaseThumbnailImage(release.RoadieId);
result.MediumThumbnail = MakeThumbnailImage(id, "release", Configuration.MediumImageSize.Width, result.MediumThumbnail = MakeThumbnailImage(id, "release", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
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;
@ -1633,10 +1690,11 @@ namespace Roadie.Api.Services
: null; : null;
if (release.SubmissionId.HasValue) if (release.SubmissionId.HasValue)
{ {
var submission = DbContext.Submissions.Include(x => x.User) var submission = DbContext.Submissions.Include(x => x.User).FirstOrDefault(x => x.Id == release.SubmissionId);
.FirstOrDefault(x => x.Id == release.SubmissionId);
if (submission != null) if (submission != null)
{
if (!submission.User.IsPrivate ?? false) if (!submission.User.IsPrivate ?? false)
{
result.Submission = new ReleaseSubmission result.Submission = new ReleaseSubmission
{ {
User = new DataToken User = new DataToken
@ -1647,16 +1705,20 @@ namespace Roadie.Api.Services
UserThumbnail = MakeUserThumbnailImage(submission.User.RoadieId), UserThumbnail = MakeUserThumbnailImage(submission.User.RoadieId),
SubmittedDate = submission.CreatedDate SubmittedDate = submission.CreatedDate
}; };
}
}
} }
if (includes != null && includes.Any()) if (includes != null && includes.Any())
{ {
if (includes.Contains("genres")) if (includes.Contains("genres"))
{
result.Genres = release.Genres.Select(x => new DataToken result.Genres = release.Genres.Select(x => new DataToken
{ {
Text = x.Genre.Name, Text = x.Genre.Name,
Value = x.Genre.RoadieId.ToString() Value = x.Genre.RoadieId.ToString()
}); });
}
if (includes.Contains("stats")) if (includes.Contains("stats"))
{ {
var releaseTracks = from r in DbContext.Releases var releaseTracks = from r in DbContext.Releases
@ -1695,16 +1757,18 @@ namespace Roadie.Api.Services
if (includes.Contains("images")) if (includes.Contains("images"))
{ {
var releaseImages = DbContext.Images.Where(x => x.ReleaseId == release.Id) var releaseImages = DbContext.Images.Where(x => x.ReleaseId == release.Id).Select(x => MakeFullsizeImage(x.RoadieId, x.Caption)).ToArray();
.Select(x => MakeFullsizeImage(x.RoadieId, x.Caption)).ToArray(); if (releaseImages != null && releaseImages.Any())
if (releaseImages != null && releaseImages.Any()) result.Images = releaseImages; {
result.Images = releaseImages;
}
var artistFolder = release.Artist.ArtistFileFolder(Configuration); var artistFolder = release.Artist.ArtistFileFolder(Configuration);
var releaseFolder = release.ReleaseFileFolder(artistFolder); var releaseFolder = release.ReleaseFileFolder(artistFolder);
var releaseImagesInFolder = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(releaseFolder), var releaseImagesInFolder = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(releaseFolder), ImageType.ReleaseSecondary, SearchOption.TopDirectoryOnly);
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(id, ImageType.ReleaseSecondary, i)));
}
} }
if (includes.Contains("playlists")) if (includes.Contains("playlists"))
@ -1767,11 +1831,14 @@ namespace Roadie.Api.Services
if (includes.Contains("collections")) if (includes.Contains("collections"))
{ {
var releaseCollections = DbContext.CollectionReleases.Include(x => x.Collection) var releaseCollections = DbContext.CollectionReleases.Include(x => x.Collection)
.Where(x => x.ReleaseId == release.Id).OrderBy(x => x.ListNumber).ToArray(); .Where(x => x.ReleaseId == release.Id)
.OrderBy(x => x.ListNumber)
.ToArray();
if (releaseCollections != null) if (releaseCollections != null)
{ {
var collections = new List<ReleaseInCollection>(); var collections = new List<ReleaseInCollection>();
foreach (var releaseCollection in releaseCollections) foreach (var releaseCollection in releaseCollections)
{
collections.Add(new ReleaseInCollection collections.Add(new ReleaseInCollection
{ {
Collection = new CollectionList Collection = new CollectionList
@ -1797,14 +1864,17 @@ namespace Roadie.Api.Services
}, },
ListNumber = releaseCollection.ListNumber ListNumber = releaseCollection.ListNumber
}); });
}
result.Collections = collections; result.Collections = collections;
} }
} }
if (includes.Contains("comments")) if (includes.Contains("comments"))
{ {
var releaseComments = DbContext.Comments.Include(x => x.User).Where(x => x.ReleaseId == release.Id) var releaseComments = DbContext.Comments.Include(x => x.User)
.OrderByDescending(x => x.CreatedDate).ToArray(); .Where(x => x.ReleaseId == release.Id)
.OrderByDescending(x => x.CreatedDate)
.ToArray();
if (releaseComments.Any()) if (releaseComments.Any())
{ {
var comments = new List<Comment>(); var comments = new List<Comment>();
@ -1816,15 +1886,11 @@ 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, comment.User = UserList.FromDataUser(releaseComment.User, MakeUserThumbnailImage(releaseComment.User.RoadieId));
MakeUserThumbnailImage(releaseComment.User.RoadieId)); comment.DislikedCount = userCommentReactions.Count(x => x.CommentId == releaseComment.Id && x.ReactionValue == CommentReaction.Dislike);
comment.DislikedCount = userCommentReactions.Count(x => comment.LikedCount = userCommentReactions.Count(x => x.CommentId == releaseComment.Id && x.ReactionValue == CommentReaction.Like);
x.CommentId == releaseComment.Id && x.ReactionValue == CommentReaction.Dislike);
comment.LikedCount = userCommentReactions.Count(x =>
x.CommentId == releaseComment.Id && x.ReactionValue == CommentReaction.Like);
comments.Add(comment); comments.Add(comment);
} }
result.Comments = comments; result.Comments = comments;
} }
} }

View file

@ -763,7 +763,7 @@ namespace Roadie.Api.Services
await DbContext.SaveChangesAsync(); await DbContext.SaveChangesAsync();
CacheManager.ClearRegion(artist.CacheRegion); CacheManager.ClearRegion(artist.CacheRegion);
Logger.LogInformation("UpdatedArtistRank For Artist `{0}`", artist); Logger.LogTrace("UpdatedArtistRank For Artist `{0}`", artist);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -899,7 +899,7 @@ namespace Roadie.Api.Services
await DbContext.SaveChangesAsync(); await DbContext.SaveChangesAsync();
CacheManager.ClearRegion(release.CacheRegion); CacheManager.ClearRegion(release.CacheRegion);
Logger.LogInformation("UpdateReleaseRank For Release `{0}`", release); Logger.LogTrace("UpdateReleaseRank For Release `{0}`", release);
if (updateArtistRank) await UpdateArtistsRankForRelease(release); if (updateArtistRank) await UpdateArtistsRankForRelease(release);
} }
} }

View file

@ -73,11 +73,13 @@ namespace Roadie.Api.Services
var result = new List<DateAndCount>(); var result = new List<DateAndCount>();
var dateInfos = (from r in DbContext.Releases var dateInfos = (from r in DbContext.Releases
orderby r.CreatedDate orderby r.CreatedDate
group r by r.CreatedDate.ToString("yyyy-MM-dd") into g select r.CreatedDate)
select new .ToArray()
.GroupBy(x => x.ToString("yyyy-MM-dd"))
.Select(x => new
{ {
date = g.Key, date = x.Key,
count = g.Count() count = x.Count()
}); });
foreach (var dateInfo in dateInfos) foreach (var dateInfo in dateInfos)
{ {

View file

@ -126,7 +126,7 @@ namespace Roadie.Api.Services
.FirstOrDefault(x => x.UserName == request.u); .FirstOrDefault(x => x.UserName == request.u);
if (user == null) if (user == null)
{ {
Logger.LogInformation($"Unknown User [{request.u}]"); Logger.LogTrace($"Unknown User [{request.u}]");
return new subsonic.SubsonicOperationResult<subsonic.SubsonicAuthenticateResponse>( return new subsonic.SubsonicOperationResult<subsonic.SubsonicAuthenticateResponse>(
subsonic.ErrorCodes.WrongUsernameOrPassword, "Unknown Username"); subsonic.ErrorCodes.WrongUsernameOrPassword, "Unknown Username");
} }
@ -163,12 +163,12 @@ namespace Roadie.Api.Services
if (user == null) if (user == null)
{ {
Logger.LogInformation($"Invalid Credentials given for User [{request.u}]"); Logger.LogTrace($"Invalid Credentials given for User [{request.u}]");
return new subsonic.SubsonicOperationResult<subsonic.SubsonicAuthenticateResponse>( return new subsonic.SubsonicOperationResult<subsonic.SubsonicAuthenticateResponse>(
subsonic.ErrorCodes.WrongUsernameOrPassword, "Unknown Username"); subsonic.ErrorCodes.WrongUsernameOrPassword, "Unknown Username");
} }
Logger.LogInformation( Logger.LogTrace(
$"Subsonic: Successfully Authenticated User [{user}] via Application [{request.c}], Application Version [{request.v}]"); $"Subsonic: Successfully Authenticated User [{user}] via Application [{request.c}], Application Version [{request.v}]");
return new subsonic.SubsonicOperationResult<subsonic.SubsonicAuthenticateResponse> return new subsonic.SubsonicOperationResult<subsonic.SubsonicAuthenticateResponse>
{ {
@ -230,7 +230,7 @@ namespace Roadie.Api.Services
var user = GetUser(roadieUser.UserId); var user = GetUser(roadieUser.UserId);
CacheManager.ClearRegion(user.CacheRegion); CacheManager.ClearRegion(user.CacheRegion);
Logger.LogInformation( Logger.LogTrace(
$"{(createdBookmark ? "Created" : "Updated")} Bookmark `{userBookmark}` for User `{roadieUser}`"); $"{(createdBookmark ? "Created" : "Updated")} Bookmark `{userBookmark}` for User `{roadieUser}`");
return new subsonic.SubsonicOperationResult<subsonic.Response> return new subsonic.SubsonicOperationResult<subsonic.Response>
{ {
@ -326,7 +326,7 @@ namespace Roadie.Api.Services
} }
await DbContext.SaveChangesAsync(); await DbContext.SaveChangesAsync();
Logger.LogInformation( Logger.LogTrace(
$"Subsonic: User `{roadieUser}` {(didCreate ? "created" : "modified")} Playlist `{playlist}` added [{songRoadieIds.Count()}] Tracks."); $"Subsonic: User `{roadieUser}` {(didCreate ? "created" : "modified")} Playlist `{playlist}` added [{songRoadieIds.Count()}] Tracks.");
request.id = subsonic.Request.PlaylistdIdentifier + playlist.RoadieId; request.id = subsonic.Request.PlaylistdIdentifier + playlist.RoadieId;
return await GetPlaylist(request, roadieUser); return await GetPlaylist(request, roadieUser);
@ -355,7 +355,7 @@ namespace Roadie.Api.Services
var user = GetUser(roadieUser.UserId); var user = GetUser(roadieUser.UserId);
CacheManager.ClearRegion(user.CacheRegion); CacheManager.ClearRegion(user.CacheRegion);
Logger.LogInformation($"Subsonic: Deleted Bookmark `{userBookmark}` for User `{roadieUser}`"); Logger.LogTrace($"Subsonic: Deleted Bookmark `{userBookmark}` for User `{roadieUser}`");
} }
return new subsonic.SubsonicOperationResult<subsonic.Response> return new subsonic.SubsonicOperationResult<subsonic.Response>
@ -372,28 +372,27 @@ namespace Roadie.Api.Services
/// <summary> /// <summary>
/// Deletes a saved playlist. /// Deletes a saved playlist.
/// </summary> /// </summary>
public async Task<subsonic.SubsonicOperationResult<subsonic.Response>> DeletePlaylist(subsonic.Request request, public async Task<subsonic.SubsonicOperationResult<subsonic.Response>> DeletePlaylist(subsonic.Request request,User roadieUser)
User roadieUser)
{ {
if (!request.PlaylistId.HasValue) //request.PlaylistId.Value
return new subsonic.SubsonicOperationResult<subsonic.Response>(
subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Invalid Playlist Id [{request.id}]");
var playlist = GetPlaylist(request.PlaylistId.Value);
if (playlist == null)
return new subsonic.SubsonicOperationResult<subsonic.Response>(
subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Invalid Playlist Id [{request.TrackId.Value}]");
if (playlist.UserId != roadieUser.Id && !roadieUser.IsAdmin)
return new subsonic.SubsonicOperationResult<subsonic.Response>(
subsonic.ErrorCodes.UserIsNotAuthorizedForGivenOperation,
"User is not allowed to delete playlist.");
DbContext.Playlists.Remove(playlist);
await DbContext.SaveChangesAsync();
var user = GetUser(roadieUser.UserId);
CacheManager.ClearRegion(user.CacheRegion);
Logger.LogInformation($"Subsonic: Deleted Playlist `{playlist}` for User `{roadieUser}`");
var deleteResult = await PlaylistService.DeletePlaylist(roadieUser, request.PlaylistId.Value);
if (deleteResult == null || deleteResult.IsNotFoundResult)
{
return new subsonic.SubsonicOperationResult<subsonic.Response>(subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Invalid Playlist Id [{request.id}]");
}
if (!deleteResult.IsSuccess)
{
if (deleteResult.IsAccessDeniedResult)
{
return new subsonic.SubsonicOperationResult<subsonic.Response>(subsonic.ErrorCodes.UserIsNotAuthorizedForGivenOperation, "User is not allowed to delete playlist.");
}
if (deleteResult.Messages?.Any() ?? false)
{
return new subsonic.SubsonicOperationResult<subsonic.Response>(subsonic.ErrorCodes.Generic, deleteResult.Messages.First());
}
return new subsonic.SubsonicOperationResult<subsonic.Response>(subsonic.ErrorCodes.Generic, "An Error Occured");
}
return new subsonic.SubsonicOperationResult<subsonic.Response> return new subsonic.SubsonicOperationResult<subsonic.Response>
{ {
IsSuccess = true, IsSuccess = true,

View file

@ -204,8 +204,10 @@ namespace Roadie.Api.Services
}; };
rowCount = playlistTrackInfos.Count(); rowCount = playlistTrackInfos.Count();
playListTrackPositions = playlistTrackInfos.Skip(request.SkipValue).Take(request.LimitValue) playListTrackPositions = playlistTrackInfos
.ToDictionary(x => x.Id, x => x.ListNumber); .Skip(request.SkipValue)
.Take(request.LimitValue)
.ToDictionary(x => x.Id, x => x.ListNumber);
playlistTrackIds = playListTrackPositions.Select(x => x.Key).ToArray(); playlistTrackIds = playListTrackPositions.Select(x => x.Key).ToArray();
request.Sort = "TrackNumber"; request.Sort = "TrackNumber";
request.Order = "ASC"; request.Order = "ASC";
@ -225,7 +227,10 @@ namespace Roadie.Api.Services
join t in DbContext.Tracks on rm.Id equals t.ReleaseMediaId join t in DbContext.Tracks on rm.Id equals t.ReleaseMediaId
where c.RoadieId == request.FilterToCollectionId.Value where c.RoadieId == request.FilterToCollectionId.Value
orderby cr.ListNumber, rm.MediaNumber, t.TrackNumber orderby cr.ListNumber, rm.MediaNumber, t.TrackNumber
select t.Id).Skip(request.SkipValue).Take(request.LimitValue).ToArray(); select t.Id)
.Skip(request.SkipValue)
.Take(request.LimitValue)
.ToArray();
} }
IQueryable<int> topTrackids = null; IQueryable<int> topTrackids = null;
@ -247,43 +252,28 @@ namespace Roadie.Api.Services
int[] randomTrackIds = null; int[] randomTrackIds = null;
if (doRandomize ?? false) if (doRandomize ?? false)
{ {
var randomLimit = roadieUser?.RandomReleaseLimit ?? request.Limit ?? 50; var randomLimit = request.Limit ?? 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 JOIN `releasemedia` rm on(t.releaseMediaId = rm.id)
select ua.ArtistId).ToArray(); JOIN `release` r on(rm.releaseId = r.id)
var dislikedReleaseIds = (from ur in DbContext.UserReleases WHERE (t.id NOT IN(select trackId FROM `usertrack` where userId = {1} and isDisliked = 1)
where ur.UserId == userId AND r.id NOT IN(select releaseId FROM `userrelease` where userId = {1} and isDisliked = 1)
where ur.IsDisliked == true AND r.artistId NOT IN(select artistId FROM `userartist` where userId = {1} and isDisliked = 1)
select ur.ReleaseId).ToArray(); AND t.artistId NOT IN(select artistId FROM `userartist` where userId = {1} and isDisliked = 1))
var dislikedTrackIds = (from ut in DbContext.UserTracks OR (t.id IN(select trackId FROM `usertrack` where userId = {1} and isFavorite = 1)
where ut.UserId == userId AND {2} = 1)
where ut.IsDisliked == true order BY RIGHT(HEX((1 << 24) * (1 + RAND())), 6)
select ut.TrackId).ToArray(); LIMIT 0, {0}";
int[] favoritedTrackIds = null;
if (request.FilterFavoriteOnly) randomTrackIds = TrackList.Shuffle((from tr in DbContext.Tracks.FromSql(sql, randomLimit, userId, request.FilterFavoriteOnly ? "1" : "0")
{ join t in DbContext.Tracks on tr.Id equals t.Id
favoritedTrackIds = (from ut in DbContext.UserTracks
where ut.UserId == userId
where ut.IsFavorite == true
select ut.TrackId).ToArray();
favoriteTrackIds = new int[0].AsQueryable();
request.FilterFavoriteOnly = false;
}
randomTrackIds = TrackList.Shuffle((from t in DbContext.Tracks
join rm in DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id join rm in DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id
join r in DbContext.Releases on rm.ReleaseId equals r.Id join r in DbContext.Releases on rm.ReleaseId equals r.Id
join a in DbContext.Artists on r.ArtistId equals a.Id join a in DbContext.Artists on r.ArtistId equals a.Id
where !request.FilterRatedOnly || request.FilterRatedOnly && t.Rating > 0
where !dislikedArtistIds.Contains(r.ArtistId)
where !dislikedArtistIds.Contains(t.ArtistId ?? 0)
where !dislikedReleaseIds.Contains(r.Id)
where !dislikedTrackIds.Contains(t.Id)
where favoritedTrackIds == null || favoritedTrackIds.Contains(t.Id)
where t.Hash != null
select new TrackList select new TrackList
{ {
DatabaseId = t.Id, DatabaseId = t.Id,
@ -293,13 +283,12 @@ namespace Roadie.Api.Services
}, },
Release = new ReleaseList Release = new ReleaseList
{ {
Release = new DataToken { Value = r.RoadieId.ToString(), Text = r.Title} Release = new DataToken { Value = r.RoadieId.ToString(), Text = r.Title }
} }
}) }).ToArray())
.OrderBy(x => x.RandomSortId) .Select(x => x.DatabaseId)
.Take(randomLimit)) .ToArray();
.Select(x => x.DatabaseId) rowCount = DbContext.Tracks.Count();
.ToArray();
} }
Guid?[] filterToTrackIds = null; Guid?[] filterToTrackIds = null;
@ -516,19 +505,21 @@ namespace Roadie.Api.Services
} }
} }
if (doRandomize ?? false) if(doRandomize ?? false)
{ {
var randomLimit = roadieUser?.RandomReleaseLimit ?? request.Limit; //rows = result.OrderBy(x => x.Artist.RandomSortId)
request.Limit = request.LimitValue > randomLimit ? randomLimit : request.LimitValue; // .ThenBy(x => x.RandomSortId)
// .ToArray();
rows = result.OrderBy(x => x.Artist.RandomSortId) rows = result.ToArray();
.ThenBy(x => x.RandomSortId)
.Take(request.LimitValue)
.ToArray();
} }
else else
{ {
rows = result.OrderBy(sortBy).Skip(request.SkipValue).Take(request.LimitValue).ToArray(); rows = result
.OrderBy(sortBy)
.Skip(request.SkipValue)
.Take(request.LimitValue)
.ToArray();
} }
if (rows.Any() && roadieUser != null) if (rows.Any() && roadieUser != null)

View file

@ -350,7 +350,7 @@ namespace Roadie.Api.Services
timings.Add("SetTrackRating", sw.ElapsedMilliseconds); timings.Add("SetTrackRating", sw.ElapsedMilliseconds);
result.AdditionalData.Add("Timing", sw.ElapsedMilliseconds); result.AdditionalData.Add("Timing", sw.ElapsedMilliseconds);
Logger.LogInformation( Logger.LogTrace(
$"User `{roadieUser}` set rating [{rating}] on TrackId [{trackId}]. Result [{JsonConvert.SerializeObject(result)}]"); $"User `{roadieUser}` set rating [{rating}] on TrackId [{trackId}]. Result [{JsonConvert.SerializeObject(result)}]");
return result; return result;
} }
@ -546,7 +546,7 @@ namespace Roadie.Api.Services
CacheManager.ClearRegion(ApplicationUser.CacheRegionUrn(user.RoadieId)); CacheManager.ClearRegion(ApplicationUser.CacheRegionUrn(user.RoadieId));
Logger.LogInformation($"User `{user}` Updated LastFm SessionKey"); Logger.LogTrace($"User `{user}` Updated LastFm SessionKey");
return new OperationResult<bool> return new OperationResult<bool>
{ {

View file

@ -87,7 +87,7 @@ namespace Roadie.Api.Controllers
var result = UserManager.ConfirmEmailAsync(user, code).Result; var result = UserManager.ConfirmEmailAsync(user, code).Result;
if (result.Succeeded) if (result.Succeeded)
{ {
Logger.LogInformation("User [{0}] Confirmed Email Successfully", userid); Logger.LogTrace("User [{0}] Confirmed Email Successfully", userid);
return Content($"Email for {RoadieSettings.SiteName} account confirmed successfully!"); return Content($"Email for {RoadieSettings.SiteName} account confirmed successfully!");
} }
@ -113,7 +113,7 @@ namespace Roadie.Api.Controllers
user.LastUpdated = now; user.LastUpdated = now;
await UserManager.UpdateAsync(user); await UserManager.UpdateAsync(user);
var t = await TokenService.GenerateToken(user, UserManager); var t = await TokenService.GenerateToken(user, UserManager);
Logger.LogInformation($"Successfully authenticated User [{model.Username}]"); Logger.LogTrace($"Successfully authenticated User [{model.Username}]");
if (!user.EmailConfirmed) if (!user.EmailConfirmed)
try try
{ {
@ -194,7 +194,7 @@ namespace Roadie.Api.Controllers
var tokenValidation = await AdminService.ValidateInviteToken(registerModel.InviteToken); var tokenValidation = await AdminService.ValidateInviteToken(registerModel.InviteToken);
if(!tokenValidation.IsSuccess) if(!tokenValidation.IsSuccess)
{ {
Logger.LogInformation("Invalid Token"); Logger.LogTrace("Invalid Invite Token");
return StatusCode((int)HttpStatusCode.BadRequest, new { Title = "Invite Token Is Required" }); return StatusCode((int)HttpStatusCode.BadRequest, new { Title = "Invite Token Is Required" });
} }
} }
@ -217,7 +217,7 @@ namespace Roadie.Api.Controllers
await SignInManager.SignInAsync(user, false); await SignInManager.SignInAsync(user, false);
var t = await TokenService.GenerateToken(user, UserManager); var t = await TokenService.GenerateToken(user, UserManager);
Logger.LogInformation($"Successfully created and authenticated User [{registerModel.Username}]"); Logger.LogTrace($"Successfully created and authenticated User [{registerModel.Username}]");
CacheManager.ClearRegion(EntityControllerBase.ControllerCacheRegionUrn); CacheManager.ClearRegion(EntityControllerBase.ControllerCacheRegionUrn);
var avatarUrl = $"{RoadieHttpContext.ImageBaseUrl}/user/{user.RoadieId}/{RoadieSettings.ThumbnailImageSize.Width}/{RoadieSettings.ThumbnailImageSize.Height}"; var avatarUrl = $"{RoadieHttpContext.ImageBaseUrl}/user/{user.RoadieId}/{RoadieSettings.ThumbnailImageSize.Width}/{RoadieSettings.ThumbnailImageSize.Height}";
if (registerModel.InviteToken.HasValue) if (registerModel.InviteToken.HasValue)
@ -307,7 +307,7 @@ namespace Roadie.Api.Controllers
{ {
await EmailSender.SendEmailAsync(user.Email, $"Reset your {RoadieSettings.SiteName} password", await EmailSender.SendEmailAsync(user.Email, $"Reset your {RoadieSettings.SiteName} password",
$"A request has been made to reset your password for your {RoadieSettings.SiteName} account. To proceed <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>click here</a>."); $"A request has been made to reset your password for your {RoadieSettings.SiteName} account. To proceed <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>click here</a>.");
Logger.LogInformation("User [{0}] Email [{1}] Requested Password Reset Callback [{2}]", username, Logger.LogTrace("User [{0}] Email [{1}] Requested Password Reset Callback [{2}]", username,
user.Email, callbackUrl); user.Email, callbackUrl);
return Ok(); return Ok();
} }

View file

@ -34,7 +34,7 @@ namespace Roadie.Api.Controllers
public IActionResult ClearCache() public IActionResult ClearCache()
{ {
CacheManager.Clear(); CacheManager.Clear();
Logger.LogInformation("Cache Cleared"); Logger.LogWarning("Cache Cleared");
return Ok(); return Ok();
} }

View file

@ -1,5 +1,4 @@
using Mapster; using Mapster;
using Microsoft.AspNet.OData;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -15,11 +14,12 @@ 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
{ {
public abstract class EntityControllerBase : ODataController public abstract class EntityControllerBase : Controller
{ {
public const string ControllerCacheRegionUrn = "urn:controller_cache"; public const string ControllerCacheRegionUrn = "urn:controller_cache";
@ -132,8 +132,7 @@ namespace Roadie.Api.Controllers
}; };
await playActivityService.NowPlaying(user, scrobble); await playActivityService.NowPlaying(user, scrobble);
sw.Stop(); sw.Stop();
Logger.LogInformation( Logger.LogTrace($"StreamTrack ElapsedTime [{sw.ElapsedMilliseconds}], Timings [{JsonConvert.SerializeObject(timings)}], StreamInfo `{info?.Data}`");
$"StreamTrack ElapsedTime [{sw.ElapsedMilliseconds}], Timings [{JsonConvert.SerializeObject(timings)}], StreamInfo `{info?.Data}`");
return new EmptyResult(); return new EmptyResult();
} }

View file

@ -39,10 +39,15 @@ namespace Roadie.Api.Controllers
[ProducesResponseType(404)] [ProducesResponseType(404)]
public async Task<IActionResult> Get(Guid id, string inc = null) public async Task<IActionResult> Get(Guid id, string inc = null)
{ {
var result = await ReleaseService.ById(await CurrentUserModel(), id, var result = await ReleaseService.ById(await CurrentUserModel(), id, (inc ?? Release.DefaultIncludes).ToLower().Split(","));
(inc ?? Release.DefaultIncludes).ToLower().Split(",")); if (result == null || result.IsNotFoundResult)
if (result == null || result.IsNotFoundResult) return NotFound(); {
if (!result.IsSuccess) return StatusCode((int)HttpStatusCode.InternalServerError); return NotFound();
}
if (!result.IsSuccess)
{
return StatusCode((int)HttpStatusCode.InternalServerError);
}
return Ok(result); return Ok(result);
} }

View file

@ -15,9 +15,7 @@ namespace Roadie.Api
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)
.AddJsonFile( .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", true)
$"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json",
true)
.AddEnvironmentVariables() .AddEnvironmentVariables()
.Build(); .Build();
@ -25,7 +23,6 @@ namespace Roadie.Api
{ {
Log.Logger = new LoggerConfiguration() Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(Configuration) .ReadFrom.Configuration(Configuration)
.WriteTo.RollingFileAlternate("logs", "errors", LogEventLevel.Error)
.CreateLogger(); .CreateLogger();
try try
@ -36,13 +33,11 @@ namespace Roadie.Api
#if DEBUG #if DEBUG
// Logging Output tests // Logging Output tests
Log.Verbose( Log.Verbose(":: Log Test: Verbose (Trace,None)"); // Microsoft.Extensions.Logging.LogLevel.Trace and Microsoft.Extensions.Logging.LogLevel.None
":: Log Test: Verbose (Trace,None)"); // Microsoft.Extensions.Logging.LogLevel.Trace and Microsoft.Extensions.Logging.LogLevel.None
Log.Debug(":: Log Test: Debug"); // Microsoft.Extensions.Logging.LogLevel.Debug Log.Debug(":: Log Test: Debug"); // Microsoft.Extensions.Logging.LogLevel.Debug
Log.Information(":: Log Test: Information"); // Microsoft.Extensions.Logging.LogLevel.Information Log.Information(":: Log Test: Information"); // Microsoft.Extensions.Logging.LogLevel.Information
Log.Warning(":: Log Test: Warning"); // Microsoft.Extensions.Logging.LogLevel.Warning Log.Warning(":: Log Test: Warning"); // Microsoft.Extensions.Logging.LogLevel.Warning
Log.Error(new Exception("Log Test Exception"), Log.Error(new Exception("Log Test Exception"), "Log Test Error Message"); // Microsoft.Extensions.Logging.LogLevel.Error
"Log Test Error Message"); // Microsoft.Extensions.Logging.LogLevel.Error
Log.Fatal(":: Log Test: Fatal (Critial)"); // Microsoft.Extensions.Logging.LogLevel.Critical Log.Fatal(":: Log Test: Fatal (Critial)"); // Microsoft.Extensions.Logging.LogLevel.Critical
Trace.WriteLine(":: Log Test: Trace WriteLine()"); Trace.WriteLine(":: Log Test: Trace WriteLine()");
#endif #endif

View file

@ -18,7 +18,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="wwwroot\Images\" /> <Folder Include="wwwroot\images\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -27,16 +27,19 @@
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.10.0" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.10.0" />
<PackageReference Include="Microsoft.AspNet.SignalR" Version="2.4.1" /> <PackageReference Include="Microsoft.AspNet.SignalR" Version="2.4.1" />
<PackageReference Include="Microsoft.AspNetCore.All" /> <PackageReference Include="Microsoft.AspNetCore.All" />
<PackageReference Include="Microsoft.AspNetCore.OData" Version="7.1.0" /> <PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.2.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.1.0" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.2.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.1.0" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.2.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.1.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.3" /> <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.3" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" /> <PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="2.1.3" />
<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" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" /> <PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" />
<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.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.5.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.18" /> <PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.18" />

View file

@ -7,7 +7,7 @@
} }
}, },
"Serilog": { "Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.RollingFileAlternate" ], "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.RollingFileAlternate", "Serilog.Sinks.LiteDB" ],
"MinimumLevel": { "MinimumLevel": {
"Default": "Verbose", "Default": "Verbose",
"Override": { "Override": {
@ -21,16 +21,23 @@
"Name": "Console", "Name": "Console",
"Args": { "Args": {
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console", "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
"restrictedToMinimumLevel": "Information"
}
},
{
"Name": "LiteDB",
"Args": {
"databaseUrl": "logs\\logs.db",
"restrictedToMinimumLevel": "Verbose" "restrictedToMinimumLevel": "Verbose"
} }
}, },
{ {
"Name": "RollingFileAlternate", "Name": "RollingFileAlternate",
"Args": { "Args": {
"restrictedToMinimumLevel": "Warning", "minimumLevel": "Verbose",
"path": "{Date}.log",
"logDirectory": "logs", "logDirectory": "logs",
"fileSizeLimitBytes": 26214400, "fileSizeLimitBytes": 26214400,
"retainedFileCountLimit": 30,
"buffered": true "buffered": true
} }
} }

View file

@ -21,7 +21,7 @@
"Name": "Console", "Name": "Console",
"Args": { "Args": {
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console", "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
"restrictedToMinimumLevel": "Verbose" "restrictedToMinimumLevel": "Warning"
} }
}, },
{ {