Small buf fixes and many ToListAsync implementations.

This commit is contained in:
Steven Hildreth 2019-11-24 15:58:38 -06:00
parent c357c6dab9
commit d9a5a917f6
59 changed files with 1269 additions and 867 deletions

View file

@ -8,9 +8,11 @@ namespace Roadie.Library.Data
[Table("collection")]
public partial class Collection : NamedEntityBase
{
[Column("collectionCount")] public int CollectionCount { get; set; }
[Column("collectionCount")]
public int CollectionCount { get; set; }
[Column("collectionType")] public CollectionType? CollectionType { get; set; }
[Column("collectionType")]
public CollectionType? CollectionType { get; set; }
public ICollection<Comment> Comments { get; set; }
@ -18,7 +20,9 @@ namespace Roadie.Library.Data
[MaxLength(4000)]
public string Description { get; set; }
[Column("edition")] [MaxLength(200)] public string Edition { get; set; }
[Column("edition")]
[MaxLength(200)]
public string Edition { get; set; }
[Column("listInCSV", TypeName = "text")]
[MaxLength(65535)]
@ -28,7 +32,8 @@ namespace Roadie.Library.Data
[MaxLength(200)]
public string ListInCSVFormat { get; set; }
[Column("maintainerId")] public int MaintainerId { get; set; }
[Column("maintainerId")]
public int MaintainerId { get; set; }
public ICollection<CollectionRelease> Releases { get; set; }
}

View file

@ -24,6 +24,8 @@ namespace Roadie.Library.Data.Context
DbSet<Collection> Collections { get; set; }
DbSet<CommentReaction> CommentReactions { get; set; }
DbSet<Comment> Comments { get; set; }
DbSet<Credit> Credits { get; set; }
DbSet<CreditCategory> CreditCategory { get; set; }
DatabaseFacade Database { get; }
DbSet<Genre> Genres { get; set; }
DbSet<Label> Labels { get; set; }

View file

@ -113,9 +113,14 @@ namespace Roadie.Library.Data.Context.Implementation
}
else
{
randomArtists = await Artists.OrderBy(x => Guid.NewGuid())
.Take(randomLimit)
.ToListAsync();
randomArtists = await (from a in Artists
join ua in UserArtists on a.Id equals ua.ArtistId into uag
from ua in uag.DefaultIfEmpty()
where (ua == null || (ua.UserId == userId && ua.IsDisliked == false))
select a)
.OrderBy(x => Guid.NewGuid())
.Take(randomLimit)
.ToListAsync();
}
var dict = randomArtists.Select((x, i) => new { key = i, value = x.Id }).Take(randomLimit).ToDictionary(x => x.key, x => x.value);
return new SortedDictionary<int, int>(dict);
@ -164,9 +169,14 @@ namespace Roadie.Library.Data.Context.Implementation
}
else
{
randomReleases = await Releases.OrderBy(x => Guid.NewGuid())
.Take(randomLimit)
.ToListAsync();
randomReleases = await(from r in Releases
join ur in UserReleases on r.Id equals ur.ReleaseId into urg
from ur in urg.DefaultIfEmpty()
where (ur == null || (ur.UserId == userId && ur.IsDisliked == false))
select r)
.OrderBy(x => Guid.NewGuid())
.Take(randomLimit)
.ToListAsync();
}
var dict = randomReleases.Select((x, i) => new { key = i, value = x.Id }).Take(randomLimit).ToDictionary(x => x.key, x => x.value);
return new SortedDictionary<int, int>(dict);
@ -199,9 +209,14 @@ namespace Roadie.Library.Data.Context.Implementation
}
else
{
randomTracks = await Tracks.OrderBy(x => Guid.NewGuid())
.Take(randomLimit)
.ToListAsync();
randomTracks = await (from t in Tracks
join ut in UserTracks on t.Id equals ut.TrackId into utg
from ut in utg.DefaultIfEmpty()
where (ut == null || (ut.UserId == userId && ut.IsDisliked == false))
select t)
.OrderBy(x => Guid.NewGuid())
.Take(randomLimit)
.ToListAsync();
}
var dict = randomTracks.Select((x, i) => new { key = i, value = x.Id }).Take(randomLimit).ToDictionary(x => x.key, x => x.value);
return new SortedDictionary<int, int>(dict);

View file

@ -32,6 +32,9 @@ namespace Roadie.Library.Data.Context
public DbSet<Comment> Comments { get; set; }
public DbSet<Credit> Credits { get; set; }
public DbSet<CreditCategory> CreditCategory { get; set; }
public DbSet<Genre> Genres { get; set; }
public DbSet<Label> Labels { get; set; }

View file

@ -0,0 +1,43 @@
using Roadie.Library.Enums;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Roadie.Library.Data
{
[Table("credit")]
public partial class Credit : NamedEntityBase
{
[Column("creditCategoryId")]
public int CreditCategoryId { get; set; }
[Column("description")]
[MaxLength(4000)]
public string Description { get; set; }
/// <summary>
/// Full Name when not an Artist via ArtistId (like a Producer)
/// </summary>
[Column("creditToName")]
[MaxLength(500)]
public string CreditToName { get; set; }
[Column("artistId")]
public int? ArtistId { get; set; }
[Column("releaseId")]
public int? ReleaseId { get; set; }
[Column("trackId")]
public int? TrackId { get; set; }
[NotMapped]
public override string Name { get; set; }
[NotMapped]
public override string SortName { get; set; }
[NotMapped]
public override string AlternateNames { get; set; }
}
}

View file

@ -0,0 +1,20 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Roadie.Library.Data
{
[Table("creditCategory")]
public partial class CreditCategory : NamedEntityBase
{
[Column("description")]
[MaxLength(4000)]
public string Description { get; set; }
[MaxLength(100)]
[Column("name")]
public override string Name { get; set; }
[NotMapped]
public override string SortName { get; set; }
}
}

View file

@ -16,11 +16,15 @@ namespace Roadie.Library.Data
public virtual bool? IsLocked { get; set; }
[Column("lastUpdated")] public DateTime? LastUpdated { get; set; }
[Column("lastUpdated")]
public DateTime? LastUpdated { get; set; }
[Column("RoadieId")] [Required] public Guid RoadieId { get; set; }
[Column("RoadieId")]
[Required]
public Guid RoadieId { get; set; }
[Column("status")] public Statuses? Status { get; set; }
[Column("status")]
public Statuses? Status { get; set; }
public EntityBase()
{

View file

@ -8,25 +8,24 @@ namespace Roadie.Library.Data
{
[Column("alternateNames", TypeName = "text")]
[MaxLength(65535)]
public string AlternateNames { get; set; }
public virtual string AlternateNames { get; set; }
[MaxLength(250)] [Column("name")] public string Name { get; set; }
[MaxLength(250)]
[Column("name")]
public virtual string Name { get; set; }
[Column("sortName")] [MaxLength(250)] public string SortName { get; set; }
[Column("sortName")]
[MaxLength(250)]
public virtual string SortName { get; set; }
public string SortNameValue => string.IsNullOrEmpty(SortName) ? Name : SortName;
public virtual string SortNameValue => string.IsNullOrEmpty(SortName) ? Name : SortName;
[Column("tags", TypeName = "text")]
[MaxLength(65535)]
public string Tags { get; set; }
[Obsolete("Images moved to file system")]
[Column("thumbnail", TypeName = "blob")]
[MaxLength(65535)]
public byte[] Thumbnail { get; set; }
public virtual string Tags { get; set; }
[Column("urls", TypeName = "text")]
[MaxLength(65535)]
public string URLs { get; set; }
public virtual string URLs { get; set; }
}
}

View file

@ -2,6 +2,7 @@
using Roadie.Library.Enums;
using Roadie.Library.Extensions;
using Roadie.Library.MetaData.Audio;
using models = Roadie.Library.Models;
using Roadie.Library.SearchEngines.Imaging;
using Roadie.Library.Utility;
using SixLabors.ImageSharp;
@ -398,5 +399,101 @@ namespace Roadie.Library.Imaging
return imageMetaData;
}
public static models.Image MakeThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id, string type, int? width = null, int? height = null, bool includeCachebuster = false)
{
return MakeImage(configuration, httpContext, id, type, width ?? configuration.ThumbnailImageSize.Width, height ?? configuration.ThumbnailImageSize.Height, null, includeCachebuster);
}
public static models.Image MakeNewImage(IHttpContext httpContext, string type)
{
return new models.Image($"{httpContext.ImageBaseUrl}/{type}.jpg", null, null);
}
public static models.Image MakePlaylistThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
{
return MakeThumbnailImage(configuration, httpContext, id, "playlist");
}
public static models.Image MakeReleaseThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
{
return MakeThumbnailImage(configuration, httpContext, id, "release");
}
public static models.Image MakeTrackThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
{
return MakeThumbnailImage(configuration, httpContext, id, "track");
}
public static models.Image MakeUserThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
{
return MakeThumbnailImage(configuration, httpContext, id, "user");
}
public static models.Image MakeLabelThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
{
return MakeThumbnailImage(configuration, httpContext, id, "label");
}
public static models.Image MakeArtistThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid? id)
{
if (!id.HasValue) return null;
return MakeThumbnailImage(configuration, httpContext, id.Value, "artist");
}
public static models.Image MakeCollectionThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
{
return MakeThumbnailImage(configuration, httpContext, id, "collection");
}
public static models.Image MakeFullsizeImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id, string caption = null)
{
return new models.Image($"{httpContext.ImageBaseUrl}/{id}", caption,
$"{httpContext.ImageBaseUrl}/{id}/{configuration.SmallImageSize.Width}/{configuration.SmallImageSize.Height}");
}
public static models.Image MakeFullsizeSecondaryImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id, ImageType type, int imageId, string caption = null)
{
if (type == ImageType.ArtistSecondary)
{
return new models.Image($"{httpContext.ImageBaseUrl}/artist-secondary/{id}/{imageId}", caption, $"{httpContext.ImageBaseUrl}/artist-secondary/{id}/{imageId}/{configuration.SmallImageSize.Width}/{configuration.SmallImageSize.Height}");
}
return new models.Image($"{httpContext.ImageBaseUrl}/release-secondary/{id}/{imageId}", caption, $"{httpContext.ImageBaseUrl}/release-secondary/{id}/{imageId}/{configuration.SmallImageSize.Width}/{configuration.SmallImageSize.Height}");
}
public static models.Image MakeGenreThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
{
return MakeThumbnailImage(configuration, httpContext, id, "genre");
}
public static models.Image MakeUnknownImage(IHttpContext httpContext, string unknownType = "unknown")
{
return new models.Image($"{httpContext.ImageBaseUrl}/{ unknownType }.jpg");
}
public static models.Image MakeImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id, int width = 200, int height = 200, string caption = null, bool includeCachebuster = false)
{
return new models.Image($"{httpContext.ImageBaseUrl}/{id}/{width}/{height}/{(includeCachebuster ? DateTime.UtcNow.Ticks.ToString() : string.Empty)}",
caption,
$"{httpContext.ImageBaseUrl}/{id}/{configuration.SmallImageSize.Width}/{configuration.SmallImageSize.Height}");
}
public static models.Image MakeImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id, string type, IImageSize imageSize)
{
return MakeImage(configuration, httpContext, id, type, imageSize.Width, imageSize.Height);
}
public static models.Image MakeImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id, string type, int? width, int? height, string caption = null, bool includeCachebuster = false)
{
if (width.HasValue && height.HasValue && (width.Value != configuration.ThumbnailImageSize.Width ||
height.Value != configuration.ThumbnailImageSize.Height))
return new models.Image(
$"{httpContext.ImageBaseUrl}/{type}/{id}/{width}/{height}/{(includeCachebuster ? DateTime.UtcNow.Ticks.ToString() : string.Empty)}",
caption,
$"{httpContext.ImageBaseUrl}/{type}/{id}/{configuration.ThumbnailImageSize.Width}/{configuration.ThumbnailImageSize.Height}");
return new models.Image($"{httpContext.ImageBaseUrl}/{type}/{id}", caption, null);
}
}
}

View file

@ -14,8 +14,7 @@ namespace Roadie.Library.Models
[Serializable]
public class Artist : EntityModelBase
{
public const string DefaultIncludes =
"stats,images,associatedartists,similarartists,comments,collections,playlists,contributions,labels";
public const string DefaultIncludes = "stats,images,associatedartists,similarartists,comments,collections,playlists,contributions,labels,genres";
public IEnumerable<ReleaseList> ArtistContributionReleases;
public IEnumerable<LabelList> ArtistLabels;
@ -40,7 +39,7 @@ namespace Roadie.Library.Models
[MaxLength(50)] public string DiscogsId { get; set; }
public IEnumerable<DataToken> Genres { get; set; }
public IEnumerable<GenreList> Genres { get; set; }
public IEnumerable<Image> Images { get; set; }

View file

@ -8,7 +8,7 @@ namespace Roadie.Library.Models
{
[Serializable]
[DebuggerDisplay("Artist Id {Id}, Name {Artist.Text}")]
public class ArtistList : EntityInfoModelBase
public sealed class ArtistList : EntityInfoModelBase
{
public DataToken Artist { get; set; }
public bool IsValid => Id != Guid.Empty;

View file

@ -8,11 +8,12 @@ using System;
namespace Roadie.Library.Models
{
[Serializable]
public class BookmarkList : EntityInfoModelBase
public sealed class BookmarkList : EntityInfoModelBase
{
public ArtistList Artist { get; set; }
public DataToken Bookmark { get; set; }
[JsonIgnore] public int BookmarkTargetId { get; set; }
[JsonIgnore]
public int BookmarkTargetId { get; set; }
public string BookmarkType => Type.ToString();
public CollectionList Collection { get; set; }
public string Comment { get; set; }

View file

@ -3,7 +3,7 @@
namespace Roadie.Library.Models.Collections
{
[Serializable]
public class CollectionList : EntityInfoModelBase
public sealed class CollectionList : EntityInfoModelBase
{
public DataToken Artist { get; set; }
public DataToken Collection { get; set; }

View file

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;
namespace Roadie.Library.Models
{
[Serializable]
public class Credit : EntityModelBase
{
public int CreditCategoryId { get; set; }
[MaxLength(4000)]
public string Description { get; set; }
/// <summary>
/// Full Name when not an Artist via ArtistId (like a Producer)
/// </summary>
[MaxLength(500)]
public string CreditToName { get; set; }
public int ArtistId { get; set; }
public int ReleaseId { get; set; }
public int TrackId { get; set; }
}
}

View file

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;
namespace Roadie.Library.Models
{
[Serializable]
public class CreditCategory : EntityModelBase
{
[MaxLength(100)]
public string Name { get; set; }
[MaxLength(4000)]
public string Description { get; set; }
}
}

View file

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Roadie.Library.Models
{
[Serializable]
public sealed class CreditList : EntityModelBase
{
public ArtistList Artist { get; set; }
public string CreditName { get; set; }
public DataToken Category { get; set; }
public string Description { get; set; }
}
}

View file

@ -26,7 +26,8 @@ namespace Roadie.Library.Models
public DateTime? LastUpdated { get; set; }
[MaxLength(250)] public string SortName { get; set; }
[MaxLength(250)]
public virtual string SortName { get; set; }
/// <summary>
/// Random int to sort when Random Request

View file

@ -21,9 +21,9 @@ namespace Roadie.Library.Models
[MaxLength(65535)]
[JsonIgnore]
[IgnoreDataMember]
public string AlternateNames { get; set; }
public virtual string AlternateNames { get; set; }
public IEnumerable<string> AlternateNamesList
public virtual IEnumerable<string> AlternateNamesList
{
get
{
@ -39,11 +39,12 @@ namespace Roadie.Library.Models
set => _alternateNamesList = value;
}
public DateTime? BeginDate { get; set; }
public virtual DateTime? BeginDate { get; set; }
[Required] public virtual DateTime? CreatedDate { get; set; }
[Required]
public virtual DateTime? CreatedDate { get; set; }
public DateTime? EndDate { get; set; }
public virtual DateTime? EndDate { get; set; }
/// <summary>
/// This is the exposed Id for API consumers, not the Database Id.
@ -51,22 +52,23 @@ namespace Roadie.Library.Models
[AdaptMember("RoadieId")]
public virtual Guid? Id { get; set; }
public bool? IsLocked { get; set; }
public virtual bool? IsLocked { get; set; }
public DateTime? LastUpdated { get; set; }
public virtual DateTime? LastUpdated { get; set; }
[MaxLength(250)] public string SortName { get; set; }
[MaxLength(250)]
public virtual string SortName { get; set; }
public int? Status { get; set; }
public virtual int? Status { get; set; }
public string StatusVerbose => SafeParser.ToEnum<Statuses>(Status).ToString();
[MaxLength(65535)]
[JsonIgnore]
[IgnoreDataMember]
public string Tags { get; set; }
public virtual string Tags { get; set; }
public IEnumerable<string> TagsList
public virtual IEnumerable<string> TagsList
{
get
{
@ -84,9 +86,9 @@ namespace Roadie.Library.Models
[MaxLength(65535)]
[JsonIgnore]
[IgnoreDataMember]
public string URLs { get; set; }
public virtual string URLs { get; set; }
public IEnumerable<string> URLsList
public virtual IEnumerable<string> URLsList
{
get
{
@ -101,7 +103,7 @@ namespace Roadie.Library.Models
set => _urlsList = value;
}
public bool? UserBookmarked { get; set; }
public virtual bool? UserBookmarked { get; set; }
public EntityModelBase()
{

View file

@ -3,11 +3,30 @@
namespace Roadie.Library.Models
{
[Serializable]
public class GenreList : EntityInfoModelBase
public sealed class GenreList : EntityInfoModelBase
{
public int? ArtistCount { get; set; }
public DataToken Genre { get; set; }
public int? ReleaseCount { get; set; }
public Image Thumbnail { get; set; }
public static GenreList FromDataGenre(Data.Genre genre, Image genreThumbnail, int? artistCount, int? releaseCount)
{
return new GenreList
{
Id = genre.RoadieId,
Genre = new DataToken
{
Text = genre.Name,
Value = genre.RoadieId.ToString()
},
SortName = genre.SortName,
CreatedDate = genre.CreatedDate,
LastUpdated = genre.LastUpdated,
ArtistCount = artistCount,
ReleaseCount = releaseCount,
Thumbnail = genreThumbnail
};
}
}
}

View file

@ -4,39 +4,40 @@ using System.ComponentModel.DataAnnotations;
namespace Roadie.Library.Models
{
/// <summary>
/// Image class served to API consumers.
/// Image model class served to API consumers.
/// </summary>
[Serializable]
public class Image : EntityModelBase
public sealed class Image : EntityModelBase
{
public byte[] Bytes { get; set; }
public byte[] Bytes { get; }
[MaxLength(100)] public string Caption { get; set; }
[MaxLength(100)]
public string Caption { get; }
[Obsolete("Only here for transition. Will be removed in future release.")]
public Guid? ArtistId { get; set; }
[Obsolete("Only here for transition. Will be removed in future release.")]
public Guid? ReleaseId { get; set; }
[MaxLength(50)] public string Signature { get; set; }
public string ThumbnailUrl { get; }
[MaxLength(500)] public string ThumbnailUrl { get; set; }
[MaxLength(500)] public string Url { get; set; }
public string Url { get; }
public Image()
{
}
/// <summary>
/// Set image Url to given value and nullify other entity values, intended to be used in List collection (like images
/// for an artist)
/// Set image Url to given value and nullify other entity values, intended to be used in List collection (like images for an artist)
/// </summary>
public Image(string url) : this(url, null, null)
public Image(string url)
: this(url, null, null)
{
}
public Image(string url, string caption, string thumbnailUrl)
public Image(byte[] bytes)
: this(null, null, null, bytes)
{
}
public Image(string url, string caption, string thumbnailUrl, byte[] bytes = null)
{
Bytes = bytes;
Url = url;
ThumbnailUrl = thumbnailUrl;
CreatedDate = null;
@ -44,10 +45,5 @@ namespace Roadie.Library.Models
Status = null;
Caption = caption;
}
public Image(byte[] bytes)
{
Bytes = bytes;
}
}
}

View file

@ -11,12 +11,15 @@ namespace Roadie.Library.Models
{
public const string DefaultIncludes = "comments,stats";
[MaxLength(65535)] public string BioContext { get; set; }
[MaxLength(65535)]
public string BioContext { get; set; }
public DateTime? BirthDate { get; set; }
public IEnumerable<Comment> Comments { get; set; }
[MaxLength(50)] public string DiscogsId { get; set; }
[MaxLength(50)]
public string DiscogsId { get; set; }
public decimal? Duration { get; set; }
@ -30,14 +33,18 @@ namespace Roadie.Library.Models
}
public Image MediumThumbnail { get; set; }
[MaxLength(100)] public string MusicBrainzId { get; set; }
[MaxLength(100)]
public string MusicBrainzId { get; set; }
[MaxLength(250)] public string Name { get; set; }
[MaxLength(250)]
public string Name { get; set; }
// When populated a "data:image" base64 byte array of an image to use as new Thumbnail
public string NewThumbnailData { get; set; }
[MaxLength(65535)] public string Profile { get; set; }
[MaxLength(65535)]
public string Profile { get; set; }
public ReleaseGroupingStatistics Statistics { get; set; }
public Image Thumbnail { get; set; }

View file

@ -4,7 +4,7 @@ using System;
namespace Roadie.Library.Models
{
[Serializable]
public class LabelList : EntityInfoModelBase
public sealed class LabelList : EntityInfoModelBase
{
public int? ArtistCount { get; set; }
public DataToken Label { get; set; }

View file

@ -5,7 +5,7 @@ using System;
namespace Roadie.Library.Models.Playlists
{
[Serializable]
public class PlaylistList : EntityInfoModelBase
public sealed class PlaylistList : EntityInfoModelBase
{
public decimal? Duration { get; set; }

View file

@ -3,7 +3,7 @@
namespace Roadie.Library.Models.Playlists
{
[Serializable]
public class PlaylistTrackList : EntityInfoModelBase
public sealed class PlaylistTrackList : EntityInfoModelBase
{
public DataToken Artist { get; set; }
public string ArtistThumbnailUrl { get; set; }

View file

@ -10,7 +10,7 @@ namespace Roadie.Library.Models.Releases
[Serializable]
public class Release : EntityModelBase
{
public const string DefaultIncludes = "tracks,stats,images,comments,collections,labels,playlists,genres";
public const string DefaultIncludes = "tracks,stats,images,comments,collections,labels,playlists,genres,credits";
public const string DefaultListIncludes = "";
[MaxLength(50)] public string AmgId { get; set; }
@ -19,10 +19,12 @@ namespace Roadie.Library.Models.Releases
public List<ReleaseInCollection> Collections { get; set; }
public IEnumerable<CreditList> Credits { get; set; }
public IEnumerable<Comment> Comments { get; set; }
[MaxLength(50)] public string DiscogsId { get; set; }
public IEnumerable<DataToken> Genres { get; set; }
public IEnumerable<GenreList> Genres { get; set; }
public IEnumerable<Image> Images { get; set; }
public bool? IsVirtual { get; set; }

View file

@ -4,7 +4,7 @@ using System;
namespace Roadie.Library.Models.Releases
{
[Serializable]
public class ReleaseLabelList : EntityInfoModelBase
public sealed class ReleaseLabelList : EntityInfoModelBase
{
public string BeginDate => BeginDatedDateTime.HasValue ? BeginDatedDateTime.Value.ToString("s") : null;
[JsonIgnore] public DateTime? BeginDatedDateTime { get; set; }

View file

@ -11,7 +11,7 @@ namespace Roadie.Library.Models.Releases
{
[Serializable]
[DebuggerDisplay("DatabaseId [{ DatabaseId }] Name [{ ReleaseName }] IsValid [{ IsValid }]")]
public class ReleaseList : EntityInfoModelBase
public sealed class ReleaseList : EntityInfoModelBase
{
public DataToken Artist { get; set; }
public Image ArtistThumbnail { get; set; }

View file

@ -5,7 +5,7 @@ using System.Linq;
namespace Roadie.Library.Models.Releases
{
[Serializable]
public class ReleaseMediaList : EntityInfoModelBase
public sealed class ReleaseMediaList : EntityInfoModelBase
{
public short? MediaNumber { get; set; }
public string SubTitle { get; set; }

View file

@ -13,14 +13,14 @@ namespace Roadie.Library.Models
[Serializable]
public class Track : EntityModelBase
{
public const string DefaultIncludes = "comments,stats";
public const string DefaultIncludes = "comments,stats,credits";
private IEnumerable<string> _partTitles;
[MaxLength(50)] public string AmgId { get; set; }
public ArtistList Artist { get; set; }
public IEnumerable<CreditList> Credits { get; set; }
public Image ArtistThumbnail { get; set; }
public IEnumerable<Comment> Comments { get; set; }
public int Duration { get; set; }

View file

@ -15,7 +15,7 @@ namespace Roadie.Library.Models
{
[Serializable]
[DebuggerDisplay("Trackid [{ TrackId }], Track Name [{ TrackName }}, Release Name [{ ReleaseName }]")]
public class TrackList : EntityInfoModelBase
public sealed class TrackList : EntityInfoModelBase
{
public ArtistList Artist { get; set; }
public int? Duration { get; set; }

View file

@ -6,7 +6,7 @@ using System.Linq;
namespace Roadie.Library.Models.Users
{
[Serializable]
public class UserList : EntityInfoModelBase
public sealed class UserList : EntityInfoModelBase
{
public bool IsEditor { get; set; }
public bool IsAdmin { get; set; }

View file

@ -11,7 +11,7 @@
<PackageReference Include="AutoCompare.Core" Version="1.0.0" />
<PackageReference Include="CsvHelper" Version="12.2.1" />
<PackageReference Include="EFCore.BulkExtensions" Version="3.0.3" />
<PackageReference Include="FluentFTP" Version="28.0.1" />
<PackageReference Include="FluentFTP" Version="28.0.2" />
<PackageReference Include="Hashids.net" Version="1.3.0" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.16" />
<PackageReference Include="IdSharp.Common" Version="1.0.1" />

View file

@ -90,7 +90,7 @@ namespace Roadie.Api.Services
if (result?.Data != null && roadieUser != null)
{
tsw.Restart();
var artist = GetArtist(id);
var artist = await GetArtist(id);
tsw.Stop();
timings.Add("getArtist", tsw.ElapsedMilliseconds);
tsw.Restart();
@ -285,7 +285,7 @@ namespace Roadie.Api.Services
Text = a.Name,
Value = a.RoadieId.ToString()
},
Thumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, a.RoadieId),
Thumbnail = ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, a.RoadieId),
Rating = a.Rating,
Rank = a.Rank,
CreatedDate = a.CreatedDate,
@ -303,7 +303,7 @@ namespace Roadie.Api.Services
if (doRandomize ?? false)
{
var resultData = result.ToArray();
var resultData = await result.ToArrayAsync();
rows = (from r in resultData
join ra in randomArtistData on r.DatabaseId equals ra.Value
orderby ra.Key
@ -323,16 +323,16 @@ namespace Roadie.Api.Services
{
sortBy = request.OrderValue(new Dictionary<string, string> { { "SortName", "ASC" }, { "Artist.Text", "ASC" } });
}
rows = result.OrderBy(sortBy).Skip(request.SkipValue).Take(request.LimitValue).ToArray();
rows = await result.OrderBy(sortBy).Skip(request.SkipValue).Take(request.LimitValue).ToArrayAsync();
}
if (rows.Any() && roadieUser != null)
{
var rowIds = rows.Select(x => x.DatabaseId).ToArray();
var userArtistRatings = (from ua in DbContext.UserArtists
where ua.UserId == roadieUser.Id
where rowIds.Contains(ua.ArtistId)
select ua).ToArray();
var userArtistRatings = await (from ua in DbContext.UserArtists
where ua.UserId == roadieUser.Id
where rowIds.Contains(ua.ArtistId)
select ua).ToArrayAsync();
foreach (var userArtistRating in userArtistRatings.Where(x => rows.Select(r => r.DatabaseId).Contains(x.ArtistId)))
{
@ -667,6 +667,10 @@ namespace Roadie.Api.Services
Directory.Move(originalArtistFolder, newArtistFolder);
}
}
if (!Directory.Exists(newArtistFolder))
{
Directory.CreateDirectory(newArtistFolder);
}
var artistImage = ImageHelper.ImageDataFromUrl(model.NewThumbnailData);
if (artistImage != null)
@ -707,14 +711,14 @@ namespace Roadie.Api.Services
// Remove existing Genres not in model list
foreach (var genre in artist.Genres.ToList())
{
var doesExistInModel = model.Genres.Any(x => SafeParser.ToGuid(x.Value) == genre.Genre.RoadieId);
var doesExistInModel = model.Genres.Any(x => SafeParser.ToGuid(x.Genre.Value) == genre.Genre.RoadieId);
if (!doesExistInModel) artist.Genres.Remove(genre);
}
// Add new Genres in model not in data
foreach (var genre in model.Genres)
{
var genreId = SafeParser.ToGuid(genre.Value);
var genreId = SafeParser.ToGuid(genre.Genre.Value);
var doesExistInData = artist.Genres.Any(x => x.Genre.RoadieId == genreId);
if (!doesExistInData)
{
@ -806,12 +810,6 @@ namespace Roadie.Api.Services
var similarArtists = DbContext.ArtistSimilar.Include(x => x.SimilarArtist).Where(x => x.ArtistId == artist.Id || x.SimilarArtistId == artist.Id).ToList();
DbContext.ArtistSimilar.RemoveRange(similarArtists);
}
if (model.Images != null && model.Images.Any())
{
// TODO
}
artist.LastUpdated = now;
await DbContext.SaveChangesAsync();
if (didRenameArtist)
@ -876,7 +874,7 @@ namespace Roadie.Api.Services
sw.Start();
tsw.Restart();
var artist = GetArtist(id);
var artist = await GetArtist(id);
tsw.Stop();
timings.Add("getArtist", tsw.ElapsedMilliseconds);
@ -897,41 +895,60 @@ namespace Roadie.Api.Services
tsw.Stop();
timings.Add("adapt", tsw.ElapsedMilliseconds);
tsw.Restart();
result.Thumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, id);
result.MediumThumbnail = MakeThumbnailImage(Configuration, HttpContext, id, "artist", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
result.Genres = artist.Genres.Select(x => new DataToken
{
Text = x.Genre.Name,
Value = x.Genre.RoadieId.ToString()
});
tsw.Stop();
timings.Add("genres", tsw.ElapsedMilliseconds);
result.Thumbnail = ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, id);
result.MediumThumbnail = ImageHelper.MakeThumbnailImage(Configuration, HttpContext, id, "artist", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
if (includes != null && includes.Any())
{
tsw.Restart();
if(includes.Contains("genres"))
{
var artistGenreIds = artist.Genres.Select(x => x.GenreId).ToArray();
result.Genres = (await (from g in DbContext.Genres
let releaseCount = (from rg in DbContext.ReleaseGenres
where rg.GenreId == g.Id
select rg.Id).Count()
let artistCount = (from rg in DbContext.ArtistGenres
where rg.GenreId == g.Id
select rg.Id).Count()
where artistGenreIds.Contains(g.Id)
select new { g, releaseCount, artistCount }).ToListAsync())
.Select(x => GenreList.FromDataGenre(x.g,
ImageHelper.MakeGenreThumbnailImage(Configuration, HttpContext, x.g.RoadieId),
x.artistCount,
x.releaseCount))
.ToArray();
tsw.Stop();
timings.Add("genres", tsw.ElapsedMilliseconds);
}
if (includes.Contains("releases"))
{
tsw.Restart();
var dtoReleases = new List<ReleaseList>();
foreach (var release in DbContext.Releases
foreach (var release in await DbContext.Releases
.Include("Medias")
.Include("Medias.Tracks")
.Include("Medias.Tracks")
.Where(x => x.ArtistId == artist.Id)
.ToArray())
.ToArrayAsync())
{
var releaseList = release.Adapt<ReleaseList>();
releaseList.Thumbnail = MakeReleaseThumbnailImage(Configuration, HttpContext, release.RoadieId);
releaseList.Thumbnail = ImageHelper.MakeReleaseThumbnailImage(Configuration, HttpContext, release.RoadieId);
var dtoReleaseMedia = new List<ReleaseMediaList>();
if (includes.Contains("tracks"))
foreach (var releasemedia in release.Medias.OrderBy(x => x.MediaNumber).ToArray())
{
var dtoMedia = releasemedia.Adapt<ReleaseMediaList>();
var tracks = new List<TrackList>();
foreach (var t in DbContext.Tracks
foreach (var t in await DbContext.Tracks
.Where(x => x.ReleaseMediaId == releasemedia.Id)
.OrderBy(x => x.TrackNumber)
.ToArray())
.ToArrayAsync())
{
var track = t.Adapt<TrackList>();
ArtistList trackArtist = null;
@ -939,18 +956,14 @@ namespace Roadie.Api.Services
{
var ta = DbContext.Artists.FirstOrDefault(x => x.Id == t.ArtistId.Value);
if (ta != null)
trackArtist = ArtistList.FromDataArtist(ta,
MakeArtistThumbnailImage(Configuration, HttpContext, ta.RoadieId));
trackArtist = ArtistList.FromDataArtist(ta, ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, ta.RoadieId));
}
track.TrackArtist = trackArtist;
tracks.Add(track);
}
dtoMedia.Tracks = tracks;
dtoReleaseMedia.Add(dtoMedia);
}
releaseList.Media = dtoReleaseMedia;
dtoReleases.Add(releaseList);
}
@ -1007,7 +1020,7 @@ namespace Roadie.Api.Services
var artistImagesInFolder = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(artistFolder), ImageType.ArtistSecondary, SearchOption.TopDirectoryOnly);
if (artistImagesInFolder.Any())
{
result.Images = artistImagesInFolder.Select((x, i) => MakeFullsizeSecondaryImage(Configuration, HttpContext, id, ImageType.ArtistSecondary, i));
result.Images = artistImagesInFolder.Select((x, i) => ImageHelper.MakeFullsizeSecondaryImage(Configuration, HttpContext, id, ImageType.ArtistSecondary, i));
}
tsw.Stop();
@ -1017,7 +1030,7 @@ namespace Roadie.Api.Services
if (includes.Contains("associatedartists"))
{
tsw.Restart();
var associatedWithArtists = (from aa in DbContext.ArtistAssociations
var associatedWithArtists = await (from aa in DbContext.ArtistAssociations
join a in DbContext.Artists on aa.AssociatedArtistId equals a.Id
where aa.ArtistId == artist.Id
select new ArtistList
@ -1029,7 +1042,7 @@ namespace Roadie.Api.Services
Text = a.Name,
Value = a.RoadieId.ToString()
},
Thumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, a.RoadieId),
Thumbnail = ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, a.RoadieId),
Rating = a.Rating,
Rank = a.Rank,
CreatedDate = a.CreatedDate,
@ -1039,9 +1052,9 @@ namespace Roadie.Api.Services
ReleaseCount = a.ReleaseCount,
TrackCount = a.TrackCount,
SortName = a.SortName
}).ToArray();
}).ToArrayAsync();
var associatedArtists = (from aa in DbContext.ArtistAssociations
var associatedArtists = await (from aa in DbContext.ArtistAssociations
join a in DbContext.Artists on aa.ArtistId equals a.Id
where aa.AssociatedArtistId == artist.Id
select new ArtistList
@ -1053,7 +1066,7 @@ namespace Roadie.Api.Services
Text = a.Name,
Value = a.RoadieId.ToString()
},
Thumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, a.RoadieId),
Thumbnail = ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, a.RoadieId),
Rating = a.Rating,
Rank = a.Rank,
CreatedDate = a.CreatedDate,
@ -1063,9 +1076,8 @@ namespace Roadie.Api.Services
ReleaseCount = a.ReleaseCount,
TrackCount = a.TrackCount,
SortName = a.SortName
}).ToArray();
result.AssociatedArtists = associatedArtists.Union(associatedWithArtists, new ArtistListComparer())
.OrderBy(x => x.SortName);
}).ToArrayAsync();
result.AssociatedArtists = associatedArtists.Union(associatedWithArtists, new ArtistListComparer()).OrderBy(x => x.SortName);
result.AssociatedArtistsTokens = result.AssociatedArtists.Select(x => x.Artist).ToArray();
tsw.Stop();
timings.Add("associatedartists", tsw.ElapsedMilliseconds);
@ -1074,7 +1086,7 @@ namespace Roadie.Api.Services
if (includes.Contains("similarartists"))
{
tsw.Restart();
var similarWithArtists = (from aa in DbContext.ArtistSimilar
var similarWithArtists = await (from aa in DbContext.ArtistSimilar
join a in DbContext.Artists on aa.SimilarArtistId equals a.Id
where aa.ArtistId == artist.Id
select new ArtistList
@ -1086,7 +1098,7 @@ namespace Roadie.Api.Services
Text = a.Name,
Value = a.RoadieId.ToString()
},
Thumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, a.RoadieId),
Thumbnail = ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, a.RoadieId),
Rating = a.Rating,
Rank = a.Rank,
CreatedDate = a.CreatedDate,
@ -1096,9 +1108,9 @@ namespace Roadie.Api.Services
ReleaseCount = a.ReleaseCount,
TrackCount = a.TrackCount,
SortName = a.SortName
}).ToArray();
}).ToArrayAsync();
var similarArtists = (from aa in DbContext.ArtistSimilar
var similarArtists = await (from aa in DbContext.ArtistSimilar
join a in DbContext.Artists on aa.ArtistId equals a.Id
where aa.SimilarArtistId == artist.Id
select new ArtistList
@ -1110,7 +1122,7 @@ namespace Roadie.Api.Services
Text = a.Name,
Value = a.RoadieId.ToString()
},
Thumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, a.RoadieId),
Thumbnail = ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, a.RoadieId),
Rating = a.Rating,
Rank = a.Rank,
CreatedDate = a.CreatedDate,
@ -1120,9 +1132,8 @@ namespace Roadie.Api.Services
ReleaseCount = a.ReleaseCount,
TrackCount = a.TrackCount,
SortName = a.SortName
}).ToArray();
result.SimilarArtists = similarWithArtists.Union(similarArtists, new ArtistListComparer())
.OrderBy(x => x.SortName);
}).ToArrayAsync();
result.SimilarArtists = similarWithArtists.Union(similarArtists, new ArtistListComparer()).OrderBy(x => x.SortName);
result.SimilarArtistsTokens = result.SimilarArtists.Select(x => x.Artist).ToArray();
tsw.Stop();
timings.Add("similarartists", tsw.ElapsedMilliseconds);
@ -1135,8 +1146,7 @@ namespace Roadie.Api.Services
{
Limit = 100
};
var r = await CollectionService.List(null,
collectionPagedRequest, artistId: artist.RoadieId);
var r = await CollectionService.List(null, collectionPagedRequest, artistId: artist.RoadieId);
if (r.IsSuccess) result.CollectionsWithArtistReleases = r.Rows.ToArray();
tsw.Stop();
timings.Add("collections", tsw.ElapsedMilliseconds);
@ -1145,8 +1155,10 @@ namespace Roadie.Api.Services
if (includes.Contains("comments"))
{
tsw.Restart();
var artistComments = DbContext.Comments.Include(x => x.User).Where(x => x.ArtistId == artist.Id)
.OrderByDescending(x => x.CreatedDate).ToArray();
var artistComments = await DbContext.Comments.Include(x => x.User)
.Where(x => x.ArtistId == artist.Id)
.OrderByDescending(x => x.CreatedDate)
.ToArrayAsync();
if (artistComments.Any())
{
var comments = new List<Comment>();
@ -1159,7 +1171,7 @@ namespace Roadie.Api.Services
var comment = artistComment.Adapt<Comment>();
comment.DatabaseId = artistComment.Id;
comment.User = UserList.FromDataUser(artistComment.User,
MakeUserThumbnailImage(Configuration, HttpContext, artistComment.User.RoadieId));
ImageHelper.MakeUserThumbnailImage(Configuration, HttpContext, artistComment.User.RoadieId));
comment.DislikedCount = userCommentReactions.Count(x =>
x.CommentId == artistComment.Id && x.ReactionValue == CommentReaction.Dislike);
comment.LikedCount = userCommentReactions.Count(x =>
@ -1198,17 +1210,16 @@ namespace Roadie.Api.Services
join r in DbContext.Releases on rm.ReleaseId equals r.Id
where t.ArtistId == artist.Id
select r.Id)
.ToArray()
.Distinct();
if (artistContributingTracks?.Any() ?? false)
{
result.ArtistContributionReleases = (from r in DbContext.Releases.Include(x => x.Artist)
result.ArtistContributionReleases = (await (from r in DbContext.Releases.Include(x => x.Artist)
where artistContributingTracks.Contains(r.Id)
select r)
.OrderBy(x => x.Title)
.ToArray()
.Select(r => ReleaseList.FromDataRelease(r, r.Artist, HttpContext.BaseUrl, MakeArtistThumbnailImage(Configuration, HttpContext, r.Artist.RoadieId), MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId)));
.ToArrayAsync())
.Select(r => ReleaseList.FromDataRelease(r, r.Artist, HttpContext.BaseUrl, ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, r.Artist.RoadieId), ImageHelper.MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId)));
result.ArtistContributionReleases = result.ArtistContributionReleases.Any()
? result.ArtistContributionReleases
@ -1221,13 +1232,13 @@ namespace Roadie.Api.Services
if (includes.Contains("labels"))
{
tsw.Restart();
result.ArtistLabels = (from l in DbContext.Labels
result.ArtistLabels = (await (from l in DbContext.Labels
join rl in DbContext.ReleaseLabels on l.Id equals rl.LabelId
join r in DbContext.Releases on rl.ReleaseId equals r.Id
where r.ArtistId == artist.Id
orderby l.SortName
select LabelList.FromDataLabel(l, MakeLabelThumbnailImage(Configuration, HttpContext, l.RoadieId)))
.ToArray()
select LabelList.FromDataLabel(l, ImageHelper.MakeLabelThumbnailImage(Configuration, HttpContext, l.RoadieId)))
.ToArrayAsync())
.GroupBy(x => x.Label.Value)
.Select(x => x.First())
.OrderBy(x => x.SortName)
@ -1466,7 +1477,7 @@ namespace Roadie.Api.Services
return new OperationResult<Library.Models.Image>
{
IsSuccess = !errors.Any(),
Data = MakeThumbnailImage(Configuration, HttpContext, id, "artist", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height, true),
Data = ImageHelper.MakeThumbnailImage(Configuration, HttpContext, id, "artist", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height, true),
OperationTime = sw.ElapsedMilliseconds,
Errors = errors
};

View file

@ -5,6 +5,7 @@ using Roadie.Library.Configuration;
using Roadie.Library.Data.Context;
using Roadie.Library.Encoding;
using Roadie.Library.Enums;
using Roadie.Library.Imaging;
using Roadie.Library.Models.Collections;
using Roadie.Library.Models.Pagination;
using Roadie.Library.Models.Playlists;
@ -34,8 +35,7 @@ namespace Roadie.Api.Services
{
}
public Task<Library.Models.Pagination.PagedResult<models.BookmarkList>> List(User roadieUser,
PagedRequest request, bool? doRandomize = false, BookmarkType? filterType = null)
public async Task<Library.Models.Pagination.PagedResult<models.BookmarkList>> List(User roadieUser, PagedRequest request, bool? doRandomize = false, BookmarkType? filterType = null)
{
var sw = new Stopwatch();
sw.Start();
@ -66,7 +66,7 @@ namespace Roadie.Api.Services
var rowCount = result.Count();
var rows = result.OrderBy(sortBy).Skip(request.SkipValue).Take(request.LimitValue).ToArray();
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
foreach (var row in rows)
switch (row.Type)
@ -80,8 +80,8 @@ namespace Roadie.Api.Services
Value = artist.RoadieId.ToString()
};
row.Artist =
models.ArtistList.FromDataArtist(artist, MakeArtistThumbnailImage(Configuration, HttpContext, artist.RoadieId));
row.Thumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, artist.RoadieId);
models.ArtistList.FromDataArtist(artist, ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, artist.RoadieId));
row.Thumbnail = ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, artist.RoadieId);
row.SortName = artist.SortName ?? artist.Name;
break;
@ -95,9 +95,9 @@ namespace Roadie.Api.Services
Value = release.RoadieId.ToString()
};
row.Release = ReleaseList.FromDataRelease(release, release.Artist, HttpContext.BaseUrl,
MakeArtistThumbnailImage(Configuration, HttpContext, release.Artist.RoadieId),
MakeReleaseThumbnailImage(Configuration, HttpContext, release.RoadieId));
row.Thumbnail = MakeReleaseThumbnailImage(Configuration, HttpContext, release.RoadieId);
ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, release.Artist.RoadieId),
ImageHelper.MakeReleaseThumbnailImage(Configuration, HttpContext, release.RoadieId));
row.Thumbnail = ImageHelper.MakeReleaseThumbnailImage(Configuration, HttpContext, release.RoadieId);
row.SortName = release.SortTitleValue;
break;
@ -114,21 +114,21 @@ namespace Roadie.Api.Services
Text = track.Title,
Value = track.RoadieId.ToString()
};
row.Track = models.TrackList.FromDataTrack(MakeTrackPlayUrl(user, HttpContext.BaseUrl, track.Id, track.RoadieId),
row.Track = models.TrackList.FromDataTrack(MakeTrackPlayUrl(user, HttpContext.BaseUrl, track.RoadieId),
track,
track.ReleaseMedia.MediaNumber,
track.ReleaseMedia.Release,
track.ReleaseMedia.Release.Artist,
track.TrackArtist,
HttpContext.BaseUrl,
MakeTrackThumbnailImage(Configuration, HttpContext, track.RoadieId),
MakeReleaseThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.RoadieId),
MakeArtistThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.Artist.RoadieId),
MakeArtistThumbnailImage(Configuration, HttpContext, track.TrackArtist == null
ImageHelper.MakeTrackThumbnailImage(Configuration, HttpContext, track.RoadieId),
ImageHelper.MakeReleaseThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.RoadieId),
ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.Artist.RoadieId),
ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, track.TrackArtist == null
? null
: (Guid?)track.TrackArtist.RoadieId));
row.Track.TrackPlayUrl = MakeTrackPlayUrl(user, HttpContext.BaseUrl, track.Id, track.RoadieId);
row.Thumbnail = MakeTrackThumbnailImage(Configuration, HttpContext, track.RoadieId);
row.Track.TrackPlayUrl = MakeTrackPlayUrl(user, HttpContext.BaseUrl, track.RoadieId);
row.Thumbnail = ImageHelper.MakeTrackThumbnailImage(Configuration, HttpContext, track.RoadieId);
row.SortName = track.Title;
break;
@ -143,9 +143,9 @@ namespace Roadie.Api.Services
Value = playlist.RoadieId.ToString()
};
row.Playlist = PlaylistList.FromDataPlaylist(playlist, playlist.User,
MakePlaylistThumbnailImage(Configuration, HttpContext, playlist.RoadieId),
MakeUserThumbnailImage(Configuration, HttpContext, playlist.User.RoadieId));
row.Thumbnail = MakePlaylistThumbnailImage(Configuration, HttpContext, playlist.RoadieId);
ImageHelper.MakePlaylistThumbnailImage(Configuration, HttpContext, playlist.RoadieId),
ImageHelper.MakeUserThumbnailImage(Configuration, HttpContext, playlist.User.RoadieId));
row.Thumbnail = ImageHelper.MakePlaylistThumbnailImage(Configuration, HttpContext, playlist.RoadieId);
row.SortName = playlist.Name;
break;
@ -160,8 +160,8 @@ namespace Roadie.Api.Services
row.Collection = CollectionList.FromDataCollection(collection,
(from crc in DbContext.CollectionReleases
where crc.CollectionId == collection.Id
select crc.Id).Count(), MakeCollectionThumbnailImage(Configuration, HttpContext, collection.RoadieId));
row.Thumbnail = MakeCollectionThumbnailImage(Configuration, HttpContext, collection.RoadieId);
select crc.Id).Count(), ImageHelper.MakeCollectionThumbnailImage(Configuration, HttpContext, collection.RoadieId));
row.Thumbnail = ImageHelper.MakeCollectionThumbnailImage(Configuration, HttpContext, collection.RoadieId);
row.SortName = collection.SortName ?? collection.Name;
break;
@ -173,22 +173,22 @@ namespace Roadie.Api.Services
Text = label.Name,
Value = label.RoadieId.ToString()
};
row.Label = models.LabelList.FromDataLabel(label, MakeLabelThumbnailImage(Configuration, HttpContext, label.RoadieId));
row.Thumbnail = MakeLabelThumbnailImage(Configuration, HttpContext, label.RoadieId);
row.Label = models.LabelList.FromDataLabel(label, ImageHelper.MakeLabelThumbnailImage(Configuration, HttpContext, label.RoadieId));
row.Thumbnail = ImageHelper.MakeLabelThumbnailImage(Configuration, HttpContext, label.RoadieId);
row.SortName = label.SortName ?? label.Name;
break;
}
;
sw.Stop();
return Task.FromResult(new Library.Models.Pagination.PagedResult<models.BookmarkList>
return new Library.Models.Pagination.PagedResult<models.BookmarkList>
{
TotalCount = rowCount,
CurrentPage = request.PageValue,
TotalPages = (int)Math.Ceiling((double)rowCount / request.LimitValue),
OperationTime = sw.ElapsedMilliseconds,
Rows = rows
});
};
}
}
}

View file

@ -60,8 +60,8 @@ namespace Roadie.Api.Services
};
var result = collection.Adapt<Collection>();
result.Id = id;
result.Thumbnail = MakeNewImage("collection");
result.MediumThumbnail = MakeNewImage("collection");
result.Thumbnail = ImageHelper.MakeNewImage(HttpContext,"collection");
result.MediumThumbnail = ImageHelper.MakeNewImage(HttpContext,"collection");
result.Maintainer = new DataToken
{
Value = roadieUser.UserId.ToString(),
@ -94,7 +94,7 @@ namespace Roadie.Api.Services
var userBookmarkResult = await BookmarkService.List(roadieUser, new PagedRequest(), false, BookmarkType.Collection);
if (userBookmarkResult.IsSuccess)
{
result.Data.UserBookmarked = userBookmarkResult?.Rows?.FirstOrDefault(x => x.Bookmark.Text == result.Data.Id.ToString()) != null;
result.Data.UserBookmarked = userBookmarkResult?.Rows?.FirstOrDefault(x => x.Bookmark.Value == result.Data.Id.ToString()) != null;
}
if (result.Data.Comments.Any())
{
@ -215,7 +215,7 @@ namespace Roadie.Api.Services
CreatedDate = c.CreatedDate,
IsLocked = c.IsLocked,
LastUpdated = c.LastUpdated,
Thumbnail = MakeCollectionThumbnailImage(Configuration, HttpContext, c.RoadieId)
Thumbnail = ImageHelper.MakeCollectionThumbnailImage(Configuration, HttpContext, c.RoadieId)
};
var sortBy = string.IsNullOrEmpty(request.Sort)
@ -327,7 +327,7 @@ namespace Roadie.Api.Services
};
}
private Task<OperationResult<Collection>> CollectionByIdAction(Guid id, IEnumerable<string> includes = null)
private async Task<OperationResult<Collection>> CollectionByIdAction(Guid id, IEnumerable<string> includes = null)
{
var timings = new Dictionary<string, long>();
var tsw = new Stopwatch();
@ -336,13 +336,13 @@ namespace Roadie.Api.Services
sw.Start();
tsw.Restart();
var collection = GetCollection(id);
var collection = await GetCollection(id);
tsw.Stop();
timings.Add("getCollection", tsw.ElapsedMilliseconds);
if (collection == null)
{
return Task.FromResult(new OperationResult<Collection>(true, string.Format("Collection Not Found [{0}]", id)));
return new OperationResult<Collection>(true, string.Format("Collection Not Found [{0}]", id));
}
var result = collection.Adapt<Collection>();
var maintainer = DbContext.Users.FirstOrDefault(x => x.Id == collection.MaintainerId);
@ -354,8 +354,8 @@ namespace Roadie.Api.Services
result.AlternateNames = collection.AlternateNames;
result.Tags = collection.Tags;
result.URLs = collection.URLs;
result.Thumbnail = MakeCollectionThumbnailImage(Configuration, HttpContext, collection.RoadieId);
result.MediumThumbnail = MakeThumbnailImage(Configuration, HttpContext, id, "collection", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
result.Thumbnail = ImageHelper.MakeCollectionThumbnailImage(Configuration, HttpContext, collection.RoadieId);
result.MediumThumbnail = ImageHelper.MakeThumbnailImage(Configuration, HttpContext, id, "collection", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
result.CollectionFoundCount = (from crc in DbContext.CollectionReleases
where crc.CollectionId == collection.Id
select crc.Id).Count();
@ -384,7 +384,7 @@ namespace Roadie.Api.Services
select new CollectionRelease
{
ListNumber = crc.ListNumber,
Release = ReleaseList.FromDataRelease(r, r.Artist, HttpContext.BaseUrl, MakeArtistThumbnailImage(Configuration, HttpContext, r.Artist.RoadieId), MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId))
Release = ReleaseList.FromDataRelease(r, r.Artist, HttpContext.BaseUrl, ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, r.Artist.RoadieId), ImageHelper.MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId))
}).ToArray();
tsw.Stop();
timings.Add("releases", tsw.ElapsedMilliseconds);
@ -438,7 +438,7 @@ namespace Roadie.Api.Services
{
var comment = collectionComment.Adapt<Comment>();
comment.DatabaseId = collectionComment.Id;
comment.User = UserList.FromDataUser(collectionComment.User, MakeUserThumbnailImage(Configuration, HttpContext, collectionComment.User.RoadieId));
comment.User = UserList.FromDataUser(collectionComment.User, ImageHelper.MakeUserThumbnailImage(Configuration, HttpContext, collectionComment.User.RoadieId));
comment.DislikedCount = userCommentReactions.Count(x => x.CommentId == collectionComment.Id && x.ReactionValue == CommentReaction.Dislike);
comment.LikedCount = userCommentReactions.Count(x => x.CommentId == collectionComment.Id && x.ReactionValue == CommentReaction.Like);
comments.Add(comment);
@ -451,12 +451,12 @@ namespace Roadie.Api.Services
}
Logger.LogInformation($"ByIdAction: Collection `{ collection }`: includes [{includes.ToCSV()}], timings: [{ timings.ToTimings() }]");
sw.Stop();
return Task.FromResult(new OperationResult<Collection>
return new OperationResult<Collection>
{
Data = result,
IsSuccess = result != null,
OperationTime = sw.ElapsedMilliseconds
});
};
}
}
}

View file

@ -129,9 +129,8 @@ namespace Roadie.Api.Services
ArtistCount = artistCount,
CreatedDate = g.CreatedDate,
LastUpdated = g.LastUpdated,
Thumbnail = MakeGenreThumbnailImage(Configuration, HttpContext, g.RoadieId)
Thumbnail = ImageHelper.MakeGenreThumbnailImage(Configuration, HttpContext, g.RoadieId)
};
GenreList[] rows;
rowCount = rowCount ?? result.Count();
if (doRandomize ?? false)
@ -276,8 +275,8 @@ namespace Roadie.Api.Services
var result = genre.Adapt<Genre>();
result.AlternateNames = genre.AlternateNames;
result.Tags = genre.Tags;
result.Thumbnail = MakeGenreThumbnailImage(Configuration, HttpContext, genre.RoadieId);
result.MediumThumbnail = MakeThumbnailImage(Configuration, HttpContext, id, "genre", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
result.Thumbnail = ImageHelper.MakeGenreThumbnailImage(Configuration, HttpContext, genre.RoadieId);
result.MediumThumbnail = ImageHelper.MakeThumbnailImage(Configuration, HttpContext, id, "genre", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
tsw.Stop();
timings.Add("adapt", tsw.ElapsedMilliseconds);
if (includes != null && includes.Any())
@ -344,7 +343,7 @@ namespace Roadie.Api.Services
return new OperationResult<Library.Models.Image>
{
IsSuccess = !errors.Any(),
Data = MakeThumbnailImage(Configuration, HttpContext, id, "genre", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height, true),
Data = ImageHelper.MakeThumbnailImage(Configuration, HttpContext, id, "genre", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height, true),
OperationTime = sw.ElapsedMilliseconds,
Errors = errors
};

View file

@ -20,8 +20,6 @@ namespace Roadie.Api.Services
Task<FileOperationResult<IImage>> ArtistSecondaryImage(Guid id, int imageId, int? width, int? height, EntityTagHeaderValue etag = null);
Task<FileOperationResult<IImage>> ById(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
Task<FileOperationResult<IImage>> CollectionImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
Task<FileOperationResult<IImage>> GenreImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);

View file

@ -24,5 +24,7 @@ namespace Roadie.Api.Services
Task<OperationResult<IEnumerable<DataToken>>> RequestStatus();
Task<OperationResult<IEnumerable<DataToken>>> Status();
Task<OperationResult<IEnumerable<DataToken>>> CreditCategories();
}
}

View file

@ -11,11 +11,9 @@ namespace Roadie.Api.Services
Task<SubsonicOperationResult<SubsonicAuthenticateResponse>> Authenticate(Request request);
Task<SubsonicOperationResult<Response>> CreateBookmark(Request request, User roadieUser, int position,
string comment);
Task<SubsonicOperationResult<Response>> CreateBookmark(Request request, User roadieUser, int position, string comment);
Task<SubsonicOperationResult<Response>> CreatePlaylist(Request request, User roadieUser, string name,
string[] songIds, string playlistId = null);
Task<SubsonicOperationResult<Response>> CreatePlaylist(Request request, User roadieUser, string name, string[] songIds, string playlistId = null);
Task<SubsonicOperationResult<Response>> DeleteBookmark(Request request, User roadieUser);
@ -23,16 +21,13 @@ namespace Roadie.Api.Services
Task<SubsonicOperationResult<Response>> GetAlbum(Request request, User roadieUser);
Task<SubsonicOperationResult<Response>>
GetAlbumInfo(Request request, User roadieUser, AlbumInfoVersion version);
Task<SubsonicOperationResult<Response>> GetAlbumInfo(Request request, User roadieUser, AlbumInfoVersion version);
Task<SubsonicOperationResult<Response>> GetAlbumList(Request request, User roadieUser,
AlbumListVersions version);
Task<SubsonicOperationResult<Response>> GetAlbumList(Request request, User roadieUser, AlbumListVersions version);
Task<SubsonicOperationResult<Response>> GetArtist(Request request, User roadieUser);
Task<SubsonicOperationResult<Response>> GetArtistInfo(Request request, int? count, bool includeNotPresent,
ArtistInfoVersion version);
Task<SubsonicOperationResult<Response>> GetArtistInfo(Request request, int? count, bool includeNotPresent, ArtistInfoVersion version);
Task<SubsonicOperationResult<Response>> GetArtists(Request request, User roadieUser);
@ -40,12 +35,11 @@ namespace Roadie.Api.Services
Task<SubsonicOperationResult<Response>> GetChatMessages(Request request, User roadieUser, long? since);
Task<SubsonicFileOperationResult<Image>> GetCoverArt(Request request, int? size);
Task<SubsonicFileOperationResult<Library.Models.Image>> GetCoverArt(Request request, int? size);
Task<SubsonicOperationResult<Response>> GetGenres(Request request);
Task<SubsonicOperationResult<Response>> GetIndexes(Request request, User roadieUser,
long? ifModifiedSince = null);
Task<SubsonicOperationResult<Response>> GetIndexes(Request request, User roadieUser, long? ifModifiedSince = null);
SubsonicOperationResult<Response> GetLicense(Request request);
@ -67,8 +61,7 @@ namespace Roadie.Api.Services
Task<SubsonicOperationResult<Response>> GetRandomSongs(Request request, User roadieUser);
Task<SubsonicOperationResult<Response>> GetSimliarSongs(Request request, User roadieUser,
SimilarSongsVersion version, int? count = 50);
Task<SubsonicOperationResult<Response>> GetSimliarSongs(Request request, User roadieUser, SimilarSongsVersion version, int? count = 50);
Task<SubsonicOperationResult<Response>> GetSong(Request request, User roadieUser);
@ -84,15 +77,13 @@ namespace Roadie.Api.Services
SubsonicOperationResult<Response> Ping(Request request);
Task<SubsonicOperationResult<Response>> SavePlayQueue(Request request, User roadieUser, string current,
long? position);
Task<SubsonicOperationResult<Response>> SavePlayQueue(Request request, User roadieUser, string current, long? position);
Task<SubsonicOperationResult<Response>> Search(Request request, User roadieUser, SearchVersion version);
Task<SubsonicOperationResult<Response>> SetRating(Request request, User roadieUser, short rating);
Task<SubsonicOperationResult<Response>> ToggleStar(Request request, User roadieUser, bool star,
string[] albumIds = null, string[] artistIds = null);
Task<SubsonicOperationResult<Response>> ToggleStar(Request request, User roadieUser, bool star, string[] albumIds = null, string[] artistIds = null);
Task<SubsonicOperationResult<Response>> UpdatePlaylist(Request request, User roadieUser, string playlistId,
string name = null, string comment = null, bool? isPublic = null, string[] songIdsToAdd = null,

View file

@ -13,6 +13,8 @@ namespace Roadie.Api.Services
Task<PagedResult<UserList>> List(PagedRequest request);
Task<OperationResult<bool>> DeleteAllBookmarks(User roadieUser);
Task<OperationResult<bool>> SetArtistBookmark(Guid artistId, User roadieUser, bool isBookmarked);
Task<OperationResult<bool>> SetArtistDisliked(Guid artistId, User roadieUser, bool isDisliked);

View file

@ -1,5 +1,4 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
using Roadie.Library;
using Roadie.Library.Caching;
@ -44,7 +43,7 @@ namespace Roadie.Api.Services
ImageSearchManager = imageSearchManager;
}
public ImageService(IRoadieSettings configuration, IRoadieDbContext dbContext, ICacheManager cacheManager,
public ImageService(IRoadieSettings configuration, IRoadieDbContext dbContext, ICacheManager cacheManager,
ILogger logger, DefaultNotFoundImages defaultNotFoundImages)
: base(configuration, null, dbContext, cacheManager, logger, null)
{
@ -73,17 +72,6 @@ namespace Roadie.Api.Services
etag);
}
public async Task<FileOperationResult<IImage>> ById(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
{
return await GetImageFileOperation("ImageById",
Library.Imaging.Image.CacheRegionUrn(id),
id,
width,
height,
async () => { return await ImageByIdAction(id, etag); },
etag);
}
public async Task<FileOperationResult<IImage>> CollectionImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
{
return await GetImageFileOperation("CollectionThumbnail",
@ -201,14 +189,14 @@ namespace Roadie.Api.Services
/// <summary>
/// Get image for an artist, see if the artist has an image in their folder and use that else use Artist.Thumbnail, is also not found use Artist DefaultNotFound image.
/// </summary>
private Task<FileOperationResult<IImage>> ArtistImageAction(Guid id, EntityTagHeaderValue etag = null)
private async Task<FileOperationResult<IImage>> ArtistImageAction(Guid id, EntityTagHeaderValue etag = null)
{
try
{
var artist = GetArtist(id);
var artist = await GetArtist(id);
if (artist == null)
{
return Task.FromResult(new FileOperationResult<IImage>(true, string.Format("Artist Not Found [{0}]", id)));
return new FileOperationResult<IImage>(true, string.Format("Artist Not Found [{0}]", id));
}
byte[] imageBytes = null;
string artistFolder = null;
@ -242,24 +230,24 @@ namespace Roadie.Api.Services
{
image = DefaultNotFoundImages.Artist;
}
return Task.FromResult(GenerateFileOperationResult(id, image, etag));
return GenerateFileOperationResult(id, image, etag);
}
catch (Exception ex)
{
Logger.LogError($"Error fetching Artist Thumbnail [{id}]", ex);
}
return Task.FromResult(new FileOperationResult<IImage>(OperationMessages.ErrorOccured));
return new FileOperationResult<IImage>(OperationMessages.ErrorOccured);
}
private Task<FileOperationResult<IImage>> ArtistSecondaryImageAction(Guid id, int imageId, EntityTagHeaderValue etag = null)
private async Task<FileOperationResult<IImage>> ArtistSecondaryImageAction(Guid id, int imageId, EntityTagHeaderValue etag = null)
{
try
{
var artist = GetArtist(id);
var artist = await GetArtist(id);
if (artist == null)
{
return Task.FromResult(new FileOperationResult<IImage>(true, string.Format("Release Not Found [{0}]", id)));
return new FileOperationResult<IImage>(true, string.Format("Release Not Found [{0}]", id));
}
byte[] imageBytes = null;
string artistFolder = null;
@ -290,24 +278,24 @@ namespace Roadie.Api.Services
Bytes = imageBytes,
CreatedDate = artist.CreatedDate
};
return Task.FromResult(GenerateFileOperationResult(id, image, etag));
return GenerateFileOperationResult(id, image, etag);
}
catch (Exception ex)
{
Logger.LogError($"Error fetching Release Thumbnail [{id}]", ex);
}
return Task.FromResult(new FileOperationResult<IImage>(OperationMessages.ErrorOccured));
return new FileOperationResult<IImage>(OperationMessages.ErrorOccured);
}
private Task<FileOperationResult<IImage>> CollectionImageAction(Guid id, EntityTagHeaderValue etag = null)
private async Task<FileOperationResult<IImage>> CollectionImageAction(Guid id, EntityTagHeaderValue etag = null)
{
try
{
var collection = GetCollection(id);
var collection = await GetCollection(id);
if (collection == null)
{
return Task.FromResult(new FileOperationResult<IImage>(true, string.Format("Collection Not Found [{0}]", id)));
return new FileOperationResult<IImage>(true, string.Format("Collection Not Found [{0}]", id));
}
IImage image = new Library.Imaging.Image(id)
{
@ -329,14 +317,14 @@ namespace Roadie.Api.Services
{
image = DefaultNotFoundImages.Collection;
}
return Task.FromResult(GenerateFileOperationResult(id, image, etag));
return GenerateFileOperationResult(id, image, etag);
}
catch (Exception ex)
{
Logger.LogError($"Error fetching Collection Thumbnail [{id}]", ex);
}
return Task.FromResult(new FileOperationResult<IImage>(OperationMessages.ErrorOccured));
return new FileOperationResult<IImage>(OperationMessages.ErrorOccured);
}
private FileOperationResult<IImage> GenerateFileOperationResult(Guid id, IImage image, EntityTagHeaderValue etag = null, string contentType = "image/jpeg")
@ -362,14 +350,14 @@ namespace Roadie.Api.Services
};
}
private Task<FileOperationResult<IImage>> GenreImageAction(Guid id, EntityTagHeaderValue etag = null)
private async Task<FileOperationResult<IImage>> GenreImageAction(Guid id, EntityTagHeaderValue etag = null)
{
try
{
var genre = GetGenre(id);
var genre = await GetGenre(id);
if (genre == null)
{
return Task.FromResult(new FileOperationResult<IImage>(true, string.Format("Genre Not Found [{0}]", id)));
return new FileOperationResult<IImage>(true, string.Format("Genre Not Found [{0}]", id));
}
IImage image = new Library.Imaging.Image(id)
{
@ -391,14 +379,14 @@ namespace Roadie.Api.Services
{
image = DefaultNotFoundImages.Genre;
}
return Task.FromResult(GenerateFileOperationResult(id, image, etag));
return GenerateFileOperationResult(id, image, etag);
}
catch (Exception ex)
{
Logger.LogError($"Error fetching Label Thumbnail [{id}]", ex);
}
return Task.FromResult(new FileOperationResult<IImage>(OperationMessages.ErrorOccured));
return new FileOperationResult<IImage>(OperationMessages.ErrorOccured);
}
private async Task<FileOperationResult<IImage>> GetImageFileOperation(string type, string regionUrn, Guid id, int? width, int? height, Func<Task<FileOperationResult<IImage>>> action, EntityTagHeaderValue etag = null)
@ -458,40 +446,15 @@ namespace Roadie.Api.Services
return new FileOperationResult<IImage>("System Error");
}
private Task<FileOperationResult<IImage>> ImageByIdAction(Guid id, EntityTagHeaderValue etag = null)
private async Task<FileOperationResult<IImage>> LabelImageAction(Guid id, EntityTagHeaderValue etag = null)
{
try
{
// TODO #29; fetch image by ID
throw new NotImplementedException();
//var image = DbContext.Images
// .Include("Release")
// .Include("Artist")
// .FirstOrDefault(x => x.RoadieId == id);
//if (image == null)
//{
// return Task.FromResult(new FileOperationResult<IImage>(true, string.Format("ImageById Not Found [{0}]", id)));
//}
//return Task.FromResult(GenerateFileOperationResult(id, image, etag));
}
catch (Exception ex)
{
Logger.LogError($"Error fetching Image [{id}]", ex);
}
return Task.FromResult(new FileOperationResult<IImage>(OperationMessages.ErrorOccured));
}
private Task<FileOperationResult<IImage>> LabelImageAction(Guid id, EntityTagHeaderValue etag = null)
{
try
{
var label = GetLabel(id);
var label = await GetLabel(id);
if (label == null)
return Task.FromResult(new FileOperationResult<IImage>(true,
string.Format("Label Not Found [{0}]", id)));
{
return new FileOperationResult<IImage>(true, string.Format("Label Not Found [{0}]", id));
}
IImage image = new Library.Imaging.Image(id)
{
CreatedDate = label.CreatedDate
@ -512,24 +475,25 @@ namespace Roadie.Api.Services
{
image = DefaultNotFoundImages.Label;
}
return Task.FromResult(GenerateFileOperationResult(id, image, etag));
return GenerateFileOperationResult(id, image, etag);
}
catch (Exception ex)
{
Logger.LogError($"Error fetching Label Thumbnail [{id}]", ex);
}
return Task.FromResult(new FileOperationResult<IImage>(OperationMessages.ErrorOccured));
return new FileOperationResult<IImage>(OperationMessages.ErrorOccured);
}
private Task<FileOperationResult<IImage>> PlaylistImageAction(Guid id, EntityTagHeaderValue etag = null)
private async Task<FileOperationResult<IImage>> PlaylistImageAction(Guid id, EntityTagHeaderValue etag = null)
{
try
{
var playlist = GetPlaylist(id);
var playlist = await GetPlaylist(id);
if (playlist == null)
return Task.FromResult(new FileOperationResult<IImage>(true,
string.Format("Playlist Not Found [{0}]", id)));
{
return new FileOperationResult<IImage>(true, string.Format("Playlist Not Found [{0}]", id));
}
IImage image = new Library.Imaging.Image(id)
{
CreatedDate = playlist.CreatedDate
@ -550,27 +514,27 @@ namespace Roadie.Api.Services
{
image = DefaultNotFoundImages.Playlist;
}
return Task.FromResult(GenerateFileOperationResult(id, image, etag));
return GenerateFileOperationResult(id, image, etag);
}
catch (Exception ex)
{
Logger.LogError($"Error fetching Playlist Thumbnail [{id}]", ex);
}
return Task.FromResult(new FileOperationResult<IImage>(OperationMessages.ErrorOccured));
return new FileOperationResult<IImage>(OperationMessages.ErrorOccured);
}
/// <summary>
/// Get image for Release from Release folder, if not exists then use Release.Thumbnail if that is not set then use Release DefaultNotFound image.
/// </summary>
private Task<FileOperationResult<IImage>> ReleaseImageAction(Guid id, EntityTagHeaderValue etag = null)
private async Task<FileOperationResult<IImage>> ReleaseImageAction(Guid id, EntityTagHeaderValue etag = null)
{
try
{
var release = GetRelease(id);
var release = await GetRelease(id);
if (release == null)
{
return Task.FromResult(new FileOperationResult<IImage>(true, string.Format("Release Not Found [{0}]", id)));
return new FileOperationResult<IImage>(true, string.Format("Release Not Found [{0}]", id));
}
byte[] imageBytes = null;
string artistFolder = null;
@ -613,25 +577,24 @@ namespace Roadie.Api.Services
{
image = DefaultNotFoundImages.Release;
}
return Task.FromResult(GenerateFileOperationResult(id, image, etag));
return GenerateFileOperationResult(id, image, etag);
}
catch (Exception ex)
{
Logger.LogError($"Error fetching Release Thumbnail [{id}]", ex);
}
return Task.FromResult(new FileOperationResult<IImage>(OperationMessages.ErrorOccured));
return new FileOperationResult<IImage>(OperationMessages.ErrorOccured);
}
private Task<FileOperationResult<IImage>> ReleaseSecondaryImageAction(Guid id, int imageId,
EntityTagHeaderValue etag = null)
private async Task<FileOperationResult<IImage>> ReleaseSecondaryImageAction(Guid id, int imageId, EntityTagHeaderValue etag = null)
{
try
{
var release = GetRelease(id);
var release = await GetRelease(id);
if (release == null)
{
return Task.FromResult(new FileOperationResult<IImage>(true, string.Format("Release Not Found [{0}]", id)));
return new FileOperationResult<IImage>(true, string.Format("Release Not Found [{0}]", id));
}
byte[] imageBytes = null;
string artistFolder = null;
@ -672,21 +635,21 @@ namespace Roadie.Api.Services
Bytes = imageBytes,
CreatedDate = release.CreatedDate
};
return Task.FromResult(GenerateFileOperationResult(id, image, etag));
return GenerateFileOperationResult(id, image, etag);
}
catch (Exception ex)
{
Logger.LogError($"Error fetching Release Thumbnail [{id}]", ex);
}
return Task.FromResult(new FileOperationResult<IImage>(OperationMessages.ErrorOccured));
return new FileOperationResult<IImage>(OperationMessages.ErrorOccured);
}
private async Task<FileOperationResult<IImage>> TrackImageAction(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
{
try
{
var track = GetTrack(id);
var track = await GetTrack(id);
if (track == null)
{
return new FileOperationResult<IImage>(true, string.Format("Track Not Found [{0}]", id));
@ -715,14 +678,14 @@ namespace Roadie.Api.Services
return new FileOperationResult<IImage>(OperationMessages.ErrorOccured);
}
private Task<FileOperationResult<IImage>> UserImageAction(Guid id, EntityTagHeaderValue etag = null)
private async Task<FileOperationResult<IImage>> UserImageAction(Guid id, EntityTagHeaderValue etag = null)
{
try
{
var user = GetUser(id);
var user = await GetUser(id);
if (user == null)
{
return Task.FromResult(new FileOperationResult<IImage>(true, string.Format("User Not Found [{0}]", id)));
return new FileOperationResult<IImage>(true, string.Format("User Not Found [{0}]", id));
}
IImage image = new Library.Imaging.Image(id)
{
@ -744,14 +707,14 @@ namespace Roadie.Api.Services
{
image = DefaultNotFoundImages.User;
}
return Task.FromResult(GenerateFileOperationResult(id, image, etag, "image/png"));
return GenerateFileOperationResult(id, image, etag, "image/png");
}
catch (Exception ex)
{
Logger.LogError($"Error fetching User Thumbnail [{id}]", ex);
}
return Task.FromResult(new FileOperationResult<IImage>(OperationMessages.ErrorOccured));
return new FileOperationResult<IImage>(OperationMessages.ErrorOccured);
}
}
}

View file

@ -57,7 +57,7 @@ namespace Roadie.Api.Services
var userBookmarkResult = await BookmarkService.List(roadieUser, new PagedRequest(), false, BookmarkType.Label);
if (userBookmarkResult.IsSuccess)
{
result.Data.UserBookmarked = userBookmarkResult?.Rows?.FirstOrDefault(x => x.Bookmark.Text == result.Data.Id.ToString()) != null;
result.Data.UserBookmarked = userBookmarkResult?.Rows?.FirstOrDefault(x => x.Bookmark.Value == result.Data.Id.ToString()) != null;
}
if (result.Data.Comments.Any())
{
@ -162,7 +162,7 @@ namespace Roadie.Api.Services
ArtistCount = l.ArtistCount,
ReleaseCount = l.ReleaseCount,
TrackCount = l.TrackCount,
Thumbnail = MakeLabelThumbnailImage(Configuration, HttpContext, l.RoadieId)
Thumbnail = ImageHelper.MakeLabelThumbnailImage(Configuration, HttpContext, l.RoadieId)
};
LabelList[] rows = null;
rowCount = rowCount ?? result.Count();
@ -356,7 +356,7 @@ namespace Roadie.Api.Services
return await SaveImageBytes(user, id, bytes);
}
private Task<OperationResult<Label>> LabelByIdAction(Guid id, IEnumerable<string> includes = null)
private async Task<OperationResult<Label>> LabelByIdAction(Guid id, IEnumerable<string> includes = null)
{
var timings = new Dictionary<string, long>();
var tsw = new Stopwatch();
@ -365,20 +365,20 @@ namespace Roadie.Api.Services
sw.Start();
tsw.Restart();
var label = GetLabel(id);
var label = await GetLabel(id);
tsw.Stop();
timings.Add("GetLabel", tsw.ElapsedMilliseconds);
if (label == null)
{
return Task.FromResult(new OperationResult<Label>(true, string.Format("Label Not Found [{0}]", id)));
return new OperationResult<Label>(true, string.Format("Label Not Found [{0}]", id));
}
tsw.Restart();
var result = label.Adapt<Label>();
result.AlternateNames = label.AlternateNames;
result.Tags = label.Tags;
result.URLs = label.URLs;
result.Thumbnail = MakeLabelThumbnailImage(Configuration, HttpContext, label.RoadieId);
result.MediumThumbnail = MakeThumbnailImage(Configuration, HttpContext, id, "label", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
result.Thumbnail = ImageHelper.MakeLabelThumbnailImage(Configuration, HttpContext, label.RoadieId);
result.MediumThumbnail = ImageHelper.MakeThumbnailImage(Configuration, HttpContext, id, "label", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
tsw.Stop();
timings.Add("adapt", tsw.ElapsedMilliseconds);
if (includes != null && includes.Any())
@ -430,7 +430,7 @@ namespace Roadie.Api.Services
{
var comment = labelComment.Adapt<Comment>();
comment.DatabaseId = labelComment.Id;
comment.User = UserList.FromDataUser(labelComment.User, MakeUserThumbnailImage(Configuration, HttpContext, labelComment.User.RoadieId));
comment.User = UserList.FromDataUser(labelComment.User, ImageHelper.MakeUserThumbnailImage(Configuration, HttpContext, labelComment.User.RoadieId));
comment.DislikedCount = userCommentReactions.Count(x => x.CommentId == labelComment.Id && x.ReactionValue == CommentReaction.Dislike);
comment.LikedCount = userCommentReactions.Count(x => x.CommentId == labelComment.Id && x.ReactionValue == CommentReaction.Like);
comments.Add(comment);
@ -444,12 +444,12 @@ namespace Roadie.Api.Services
sw.Stop();
Logger.LogInformation($"ByIdAction: Label `{ label }`: includes [{includes.ToCSV()}], timings: [{ timings.ToTimings() }]");
return Task.FromResult(new OperationResult<Label>
return new OperationResult<Label>
{
Data = result,
IsSuccess = result != null,
OperationTime = sw.ElapsedMilliseconds
});
};
}
private async Task<OperationResult<Library.Models.Image>> SaveImageBytes(User user, Guid id, byte[] imageBytes)
@ -483,7 +483,7 @@ namespace Roadie.Api.Services
return new OperationResult<Library.Models.Image>
{
IsSuccess = !errors.Any(),
Data = MakeThumbnailImage(Configuration, HttpContext, id, "label", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height, true),
Data = ImageHelper.MakeThumbnailImage(Configuration, HttpContext, id, "label", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height, true),
OperationTime = sw.ElapsedMilliseconds,
Errors = errors
};

View file

@ -1,4 +1,5 @@
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Roadie.Library;
using Roadie.Library.Caching;
using Roadie.Library.Configuration;
@ -21,6 +22,8 @@ namespace Roadie.Api.Services
/// </summary>
public class LookupService : ServiceBase, ILookupService
{
public const string CreditCategoriesCacheKey = "urn:creditCategories";
public LookupService(IRoadieSettings configuration,
IHttpEncoder httpEncoder,
IHttpContext httpContext,
@ -119,6 +122,25 @@ namespace Roadie.Api.Services
});
}
public async Task<OperationResult<IEnumerable<DataToken>>> CreditCategories()
{
var sw = Stopwatch.StartNew();
var data = await CacheManager.GetAsync(CreditCategoriesCacheKey, async () =>
{
return (await DbContext.CreditCategory.ToListAsync()).Select(x => new DataToken
{
Value = x.RoadieId.ToString(),
Text = x.Name
}).ToArray();
}, CacheManagerBase.SystemCacheRegionUrn);
return new OperationResult<IEnumerable<DataToken>>
{
Data = data,
IsSuccess = true,
OperationTime = sw.ElapsedMilliseconds
};
}
public Task<OperationResult<IEnumerable<DataToken>>> Status()
{
var sw = Stopwatch.StartNew();

View file

@ -7,6 +7,7 @@ using Roadie.Library.Caching;
using Roadie.Library.Configuration;
using Roadie.Library.Data.Context;
using Roadie.Library.Encoding;
using Roadie.Library.Imaging;
using Roadie.Library.Models;
using Roadie.Library.Models.Pagination;
using Roadie.Library.Models.Users;
@ -81,10 +82,10 @@ namespace Roadie.Api.Services
releaseArtist,
trackArtist,
HttpContext.BaseUrl,
MakeTrackThumbnailImage(Configuration, HttpContext, t.RoadieId),
MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId),
MakeArtistThumbnailImage(Configuration, HttpContext, releaseArtist.RoadieId),
MakeArtistThumbnailImage(Configuration, HttpContext, trackArtist == null ? null : (Guid?)trackArtist.RoadieId)),
ImageHelper.MakeTrackThumbnailImage(Configuration, HttpContext, t.RoadieId),
ImageHelper.MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId),
ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, releaseArtist.RoadieId),
ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, trackArtist == null ? null : (Guid?)trackArtist.RoadieId)),
User = new DataToken
{
Text = u.UserName,
@ -108,10 +109,10 @@ namespace Roadie.Api.Services
UserRating = usertrack.Rating,
TrackPlayUrl = $"{HttpContext.BaseUrl}/play/track/{t.RoadieId}.mp3",
ArtistThumbnail =
MakeArtistThumbnailImage(Configuration, HttpContext,
ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext,
trackArtist != null ? trackArtist.RoadieId : releaseArtist.RoadieId),
ReleaseThumbnail = MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId),
UserThumbnail = MakeUserThumbnailImage(Configuration, HttpContext, u.RoadieId)
ReleaseThumbnail = ImageHelper.MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId),
UserThumbnail = ImageHelper.MakeUserThumbnailImage(Configuration, HttpContext, u.RoadieId)
};
var sortBy = string.IsNullOrEmpty(request.Sort)
@ -198,10 +199,10 @@ namespace Roadie.Api.Services
track.ReleaseMedia.Release.Artist,
track.TrackArtist,
HttpContext.BaseUrl,
MakeTrackThumbnailImage(Configuration, HttpContext, track.RoadieId),
MakeReleaseThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.RoadieId),
MakeArtistThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.Artist.RoadieId),
MakeArtistThumbnailImage(Configuration, HttpContext, track.TrackArtist == null
ImageHelper.MakeTrackThumbnailImage(Configuration, HttpContext, track.RoadieId),
ImageHelper.MakeReleaseThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.RoadieId),
ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.Artist.RoadieId),
ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, track.TrackArtist == null
? null
: (Guid?)track.TrackArtist.RoadieId)),
User = new DataToken
@ -209,17 +210,17 @@ namespace Roadie.Api.Services
Text = roadieUser.UserName,
Value = roadieUser.UserId.ToString()
},
ArtistThumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, track.TrackArtist != null
ArtistThumbnail = ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, track.TrackArtist != null
? track.TrackArtist.RoadieId
: track.ReleaseMedia.Release.Artist.RoadieId),
PlayedDateDateTime = scrobble.TimePlayed,
IsNowPlaying = isNowPlaying,
Rating = track.Rating,
ReleasePlayUrl = $"{HttpContext.BaseUrl}/play/release/{track.ReleaseMedia.Release.RoadieId}",
ReleaseThumbnail = MakeReleaseThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.RoadieId),
ReleaseThumbnail = ImageHelper.MakeReleaseThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.RoadieId),
TrackPlayUrl = $"{HttpContext.BaseUrl}/play/track/{track.RoadieId}.mp3",
UserRating = userTrack?.Rating,
UserThumbnail = MakeUserThumbnailImage(Configuration, HttpContext, roadieUser.UserId)
UserThumbnail = ImageHelper.MakeUserThumbnailImage(Configuration, HttpContext, roadieUser.UserId)
};
try
{

View file

@ -123,10 +123,10 @@ namespace Roadie.Api.Services
{
if (result?.Data?.Tracks != null)
{
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
foreach (var track in result.Data.Tracks)
{
track.Track.TrackPlayUrl = MakeTrackPlayUrl(user, HttpContext.BaseUrl, track.Track.DatabaseId, track.Track.Id);
track.Track.TrackPlayUrl = MakeTrackPlayUrl(user, HttpContext.BaseUrl, track.Track.Id);
}
}
@ -134,7 +134,7 @@ namespace Roadie.Api.Services
var userBookmarkResult = await BookmarkService.List(roadieUser, new PagedRequest(), false, BookmarkType.Playlist);
if (userBookmarkResult.IsSuccess)
{
result.Data.UserBookmarked = userBookmarkResult?.Rows?.FirstOrDefault(x => x.Bookmark.Text == result.Data.Id.ToString()) != null;
result.Data.UserBookmarked = userBookmarkResult?.Rows?.FirstOrDefault(x => x.Bookmark.Value == result.Data.Id.ToString()) != null;
}
if (result.Data.Comments.Any())
{
@ -255,9 +255,9 @@ namespace Roadie.Api.Services
TrackCount = pl.TrackCount,
CreatedDate = pl.CreatedDate,
LastUpdated = pl.LastUpdated,
UserThumbnail = MakeUserThumbnailImage(Configuration, HttpContext, u.RoadieId),
UserThumbnail = ImageHelper.MakeUserThumbnailImage(Configuration, HttpContext, u.RoadieId),
Id = pl.RoadieId,
Thumbnail = MakePlaylistThumbnailImage(Configuration, HttpContext, pl.RoadieId)
Thumbnail = ImageHelper.MakePlaylistThumbnailImage(Configuration, HttpContext, pl.RoadieId)
};
var sortBy = string.IsNullOrEmpty(request.Sort)
? request.OrderValue(new Dictionary<string, string> { { "Playlist.Text", "ASC" } })
@ -441,7 +441,7 @@ namespace Roadie.Api.Services
};
}
private Task<OperationResult<Playlist>> PlaylistByIdAction(Guid id, IEnumerable<string> includes = null)
private async Task<OperationResult<Playlist>> PlaylistByIdAction(Guid id, IEnumerable<string> includes = null)
{
var timings = new Dictionary<string, long>();
var tsw = new Stopwatch();
@ -450,13 +450,13 @@ namespace Roadie.Api.Services
sw.Start();
tsw.Restart();
var playlist = GetPlaylist(id);
var playlist = await GetPlaylist(id);
tsw.Stop();
timings.Add("getPlaylist", tsw.ElapsedMilliseconds);
if (playlist == null)
{
return Task.FromResult(new OperationResult<Playlist>(true, string.Format("Playlist Not Found [{0}]", id)));
return new OperationResult<Playlist>(true, string.Format("Playlist Not Found [{0}]", id));
}
tsw.Restart();
var result = playlist.Adapt<Playlist>();
@ -464,9 +464,9 @@ namespace Roadie.Api.Services
result.Tags = playlist.Tags;
result.URLs = playlist.URLs;
var maintainer = DbContext.Users.Include(x => x.UserRoles).Include("UserRoles.Role").FirstOrDefault(x => x.Id == playlist.UserId);
result.Maintainer = UserList.FromDataUser(maintainer, MakeUserThumbnailImage(Configuration, HttpContext, maintainer.RoadieId));
result.Thumbnail = MakePlaylistThumbnailImage(Configuration, HttpContext, playlist.RoadieId);
result.MediumThumbnail = MakeThumbnailImage(Configuration, HttpContext, id, "playlist", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
result.Maintainer = UserList.FromDataUser(maintainer, ImageHelper.MakeUserThumbnailImage(Configuration, HttpContext, maintainer.RoadieId));
result.Thumbnail = ImageHelper.MakePlaylistThumbnailImage(Configuration, HttpContext, playlist.RoadieId);
result.MediumThumbnail = ImageHelper.MakeThumbnailImage(Configuration, HttpContext, id, "playlist", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
tsw.Stop();
timings.Add("adapt", tsw.ElapsedMilliseconds);
if (includes != null && includes.Any())
@ -509,10 +509,10 @@ namespace Roadie.Api.Services
releaseArtist,
trackArtist,
HttpContext.BaseUrl,
MakeTrackThumbnailImage(Configuration, HttpContext, plt.t.RoadieId),
MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId),
MakeArtistThumbnailImage(Configuration, HttpContext, releaseArtist.RoadieId),
MakeArtistThumbnailImage(Configuration, HttpContext, trackArtist == null ? null : (Guid?)trackArtist.RoadieId))
ImageHelper.MakeTrackThumbnailImage(Configuration, HttpContext, plt.t.RoadieId),
ImageHelper.MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId),
ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, releaseArtist.RoadieId),
ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, trackArtist == null ? null : (Guid?)trackArtist.RoadieId))
}).ToArray();
tsw.Stop();
timings.Add("tracks", tsw.ElapsedMilliseconds);
@ -535,7 +535,7 @@ namespace Roadie.Api.Services
{
var comment = playlistComment.Adapt<Comment>();
comment.DatabaseId = playlistComment.Id;
comment.User = UserList.FromDataUser(playlistComment.User, MakeUserThumbnailImage(Configuration, HttpContext, playlistComment.User.RoadieId));
comment.User = UserList.FromDataUser(playlistComment.User, ImageHelper.MakeUserThumbnailImage(Configuration, HttpContext, playlistComment.User.RoadieId));
comment.DislikedCount = userCommentReactions.Count(x => x.CommentId == playlistComment.Id && x.ReactionValue == CommentReaction.Dislike);
comment.LikedCount = userCommentReactions.Count(x => x.CommentId == playlistComment.Id && x.ReactionValue == CommentReaction.Like);
comments.Add(comment);
@ -549,12 +549,12 @@ namespace Roadie.Api.Services
sw.Stop();
Logger.LogInformation($"ByIdAction: Playlist `{ playlist }`: includes [{includes.ToCSV()}], timings: [{ timings.ToTimings() }]");
return Task.FromResult(new OperationResult<Playlist>
return new OperationResult<Playlist>
{
Data = result,
IsSuccess = result != null,
OperationTime = sw.ElapsedMilliseconds
});
};
}
}
}

View file

@ -85,7 +85,7 @@ namespace Roadie.Api.Services
if (result?.Data != null && roadieUser != null)
{
tsw.Restart();
var release = GetRelease(id);
var release = await GetRelease(id);
tsw.Stop();
timings.Add("getRelease", tsw.ElapsedMilliseconds);
@ -97,14 +97,14 @@ namespace Roadie.Api.Services
if (result.Data.Medias != null)
{
tsw.Restart();
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
tsw.Stop();
timings.Add("getUser", tsw.ElapsedMilliseconds);
tsw.Restart();
Parallel.ForEach(result.Data.Medias.SelectMany(x => x.Tracks), track =>
{
track.TrackPlayUrl = MakeTrackPlayUrl(user, HttpContext.BaseUrl, track.DatabaseId, track.Id);
track.TrackPlayUrl = MakeTrackPlayUrl(user, HttpContext.BaseUrl, track.Id);
});
tsw.Stop();
@ -460,11 +460,6 @@ namespace Roadie.Api.Services
request.Order = "ASC";
}
}
//
// TODO list should honor disliked artist and albums for random
//
var isEqualFilter = false;
if (!string.IsNullOrEmpty(request.FilterValue))
{
@ -525,7 +520,7 @@ namespace Roadie.Api.Services
Text = r.Title,
Value = r.RoadieId.ToString()
},
ArtistThumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, a.RoadieId),
ArtistThumbnail = ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, a.RoadieId),
CreatedDate = r.CreatedDate,
Duration = r.Duration,
LastPlayed = r.LastPlayed,
@ -537,7 +532,7 @@ namespace Roadie.Api.Services
ReleaseDateDateTime = r.ReleaseDate,
ReleasePlayUrl = $"{HttpContext.BaseUrl}/play/release/{r.RoadieId}",
Status = r.Status,
Thumbnail = MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId),
Thumbnail = ImageHelper.MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId),
TrackCount = r.TrackCount,
TrackPlayedCount = r.PlayedCount
});
@ -548,7 +543,7 @@ namespace Roadie.Api.Services
if (doRandomize ?? false)
{
var resultData = result.ToArray();
var resultData = await result.ToArrayAsync();
rows = (from r in resultData
join ra in randomReleaseData on r.DatabaseId equals ra.Value
orderby ra.Key
@ -583,24 +578,24 @@ namespace Roadie.Api.Services
if (request.FilterToCollectionId.HasValue)
{
rows = result.ToArray();
rows = await result.ToArrayAsync();
}
else
{
sortBy = sortBy.Replace("ReleaseDate ", "ReleaseDateDateTime ");
rows = result
.OrderBy(sortBy)
.Skip(request.SkipValue)
.Take(request.LimitValue)
.ToArray();
rows = await result
.OrderBy(sortBy)
.Skip(request.SkipValue)
.Take(request.LimitValue)
.ToArrayAsync();
}
}
if (rows.Any())
{
var rowIds = rows.Select(x => x.DatabaseId).ToArray();
var genreData = (from rg in DbContext.ReleaseGenres
var genreData = await (from rg in DbContext.ReleaseGenres
join g in DbContext.Genres on rg.GenreId equals g.Id
where rowIds.Contains(rg.ReleaseId)
orderby rg.Id
@ -612,7 +607,7 @@ namespace Roadie.Api.Services
Text = g.Name,
Value = g.RoadieId.ToString()
}
}).ToArray();
}).ToArrayAsync();
foreach (var release in rows)
{
@ -623,7 +618,7 @@ namespace Roadie.Api.Services
if (request.FilterToCollectionId.HasValue)
{
var newRows = new List<ReleaseList>(rows);
var collection = GetCollection(request.FilterToCollectionId.Value);
var collection = await GetCollection(request.FilterToCollectionId.Value);
var collectionReleases = from c in DbContext.Collections
join cr in DbContext.CollectionReleases on c.Id equals cr.CollectionId
where c.RoadieId == request.FilterToCollectionId
@ -654,8 +649,8 @@ namespace Roadie.Api.Services
Text = par.Release
},
Status = Statuses.Missing,
ArtistThumbnail = new Image($"{HttpContext.ImageBaseUrl}/unknown.jpg"),
Thumbnail = new Image($"{HttpContext.ImageBaseUrl}/unknown.jpg"),
ArtistThumbnail = ImageHelper.MakeUnknownImage(HttpContext),
Thumbnail = ImageHelper.MakeUnknownImage(HttpContext),
ListNumber = par.Position
});
}
@ -676,10 +671,10 @@ namespace Roadie.Api.Services
if (roadieUser != null)
{
var userReleaseRatings = (from ur in DbContext.UserReleases
where ur.UserId == roadieUser.Id
where rowIds.Contains(ur.ReleaseId)
select ur).ToArray();
var userReleaseRatings = await (from ur in DbContext.UserReleases
where ur.UserId == roadieUser.Id
where rowIds.Contains(ur.ReleaseId)
select ur).ToArrayAsync();
foreach (var userReleaseRating in userReleaseRatings.Where(x =>
rows.Select(r => r.DatabaseId).Contains(x.ReleaseId)))
@ -708,13 +703,13 @@ namespace Roadie.Api.Services
if (includes.Contains("tracks"))
{
var rowIds = rows.Select(x => x.DatabaseId).ToArray();
var userRatingsForResult = (from ut in DbContext.UserTracks.Include(x => x.Track)
join t in DbContext.Tracks on ut.TrackId equals t.Id
join rm in DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id
where rowIds.Contains(rm.ReleaseId)
where ut.UserId == roadieUser.Id
select ut)
.ToArray() ?? new data.UserTrack[0];
var userRatingsForResult = await (from ut in DbContext.UserTracks.Include(x => x.Track)
join t in DbContext.Tracks on ut.TrackId equals t.Id
join rm in DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id
where rowIds.Contains(rm.ReleaseId)
where ut.UserId == roadieUser.Id
select ut)
.ToArrayAsync() ?? new data.UserTrack[0];
foreach (var release in rows)
{
@ -725,7 +720,7 @@ namespace Roadie.Api.Services
.AsQueryable()
.ProjectToType<ReleaseMediaList>()
.OrderBy(x => x.MediaNumber)
.ToArray();
.ToArray(); // Async operation on Project Mapping async throws error
Parallel.ForEach(release.Media, (media) =>
{
@ -752,7 +747,10 @@ namespace Roadie.Api.Services
}
}
if (request.FilterFavoriteOnly) rows = rows.OrderBy(x => x.UserRating.Rating).ToArray();
if (request.FilterFavoriteOnly)
{
rows = rows.OrderBy(x => x.UserRating.Rating).ToArray();
}
sw.Stop();
return new Library.Models.Pagination.PagedResult<ReleaseList>
{
@ -1065,12 +1063,11 @@ namespace Roadie.Api.Services
};
}
public Task<FileOperationResult<byte[]>> ReleaseZipped(User roadieUser, Guid id)
public async Task<FileOperationResult<byte[]>> ReleaseZipped(User roadieUser, Guid id)
{
var release = GetRelease(id);
var release = await GetRelease(id);
if (release == null)
return Task.FromResult(new FileOperationResult<byte[]>(true,
string.Format("Release Not Found [{0}]", id)));
return new FileOperationResult<byte[]>(true, string.Format("Release Not Found [{0}]", id));
byte[] zipBytes = null;
string zipFileName = null;
@ -1081,8 +1078,7 @@ namespace Roadie.Api.Services
if (!Directory.Exists(releaseFolder))
{
Logger.LogCritical($"Release Folder [{releaseFolder}] not found for Release `{release}`");
return Task.FromResult(new FileOperationResult<byte[]>(true,
string.Format("Release Folder Not Found [{0}]", id)));
return new FileOperationResult<byte[]>(true, string.Format("Release Folder Not Found [{0}]", id));
}
var releaseFiles = Directory.GetFiles(releaseFolder);
@ -1119,12 +1115,12 @@ namespace Roadie.Api.Services
Logger.LogError(ex, "Error creating zip for Release `{0}`", release.ToString());
}
return Task.FromResult(new FileOperationResult<byte[]>
return new FileOperationResult<byte[]>
{
IsSuccess = zipBytes != null,
Data = zipBytes,
AdditionalData = new Dictionary<string, object> { { "ZipFileName", zipFileName } }
});
};
}
/// <summary>
@ -1668,15 +1664,17 @@ namespace Roadie.Api.Services
// Remove existing Genres not in model list
foreach (var genre in release.Genres.ToList())
{
var doesExistInModel =
model.Genres.Any(x => SafeParser.ToGuid(x.Value) == genre.Genre.RoadieId);
if (!doesExistInModel) release.Genres.Remove(genre);
var doesExistInModel = model.Genres.Any(x => SafeParser.ToGuid(x.Genre.Value) == genre.Genre.RoadieId);
if (!doesExistInModel)
{
release.Genres.Remove(genre);
}
}
// Add new Genres in model not in data
foreach (var genre in model.Genres)
{
var genreId = SafeParser.ToGuid(genre.Value);
var genreId = SafeParser.ToGuid(genre.Genre.Value);
var doesExistInData = release.Genres.Any(x => x.Genre.RoadieId == genreId);
if (!doesExistInData)
{
@ -1696,10 +1694,98 @@ namespace Roadie.Api.Services
release.Genres.Clear();
}
if (model.Labels != null && model.Labels.Any())
if(model.Labels == null || !model.Labels.Any())
{
// TODO
// Delete all existing labels for release
var releaseLabelsToDelete = (from l in DbContext.ReleaseLabels
where l.ReleaseId == release.Id
select l).ToArray();
DbContext.ReleaseLabels.RemoveRange(releaseLabelsToDelete);
}
else if (model.Labels != null && model.Labels.Any())
{
var releaseLabelIds = model.Labels.Select(x => x.Id).ToArray();
// Delete any labels not in given model (removed by edit operation)
var releaseLabelsToDelete = (from l in DbContext.ReleaseLabels
where l.ReleaseId == release.Id
where !releaseLabelIds.Contains(l.RoadieId)
select l).ToArray();
DbContext.ReleaseLabels.RemoveRange(releaseLabelsToDelete);
// Update any existing
foreach(var label in model.Labels)
{
var trackLabel = DbContext.ReleaseLabels.FirstOrDefault(x => x.RoadieId == label.Id);
if (trackLabel == null)
{
// Add new
trackLabel = new data.ReleaseLabel
{
ReleaseId = release.Id,
CreatedDate = now
};
DbContext.ReleaseLabels.Add(trackLabel);
}
trackLabel.CatalogNumber = label.CatalogNumber;
trackLabel.BeginDate = label.BeginDate;
trackLabel.EndDate = label.EndDate;
var releaseLabel = await GetLabel(SafeParser.ToGuid(label.Label.Label.Value).Value);
trackLabel.LabelId = releaseLabel.Id;
trackLabel.IsLocked = label.IsLocked;
trackLabel.Status = SafeParser.ToEnum<Statuses>(label.Status);
trackLabel.LastUpdated = now;
}
}
if (model.Credits == null || !model.Credits.Any())
{
// Delete all existing credits for release
var releaseCreditsToDelete = (from c in DbContext.Credits
where c.ReleaseId == release.Id
select c).ToArray();
DbContext.Credits.RemoveRange(releaseCreditsToDelete);
}
else if (model.Credits != null && model.Credits.Any())
{
var releaseCreditIds = model.Credits.Select(x => x.Id).ToArray();
// Delete any credits not given in model (removed by edit operation)
var releaseCreditsToDelete = (from c in DbContext.Credits
where c.TrackId == release.Id
where !releaseCreditIds.Contains(c.RoadieId)
select c).ToArray();
DbContext.Credits.RemoveRange(releaseCreditsToDelete);
// Update any existing
foreach (var credit in model.Credits)
{
var trackCredit = DbContext.Credits.FirstOrDefault(x => x.RoadieId == credit.Id);
if (trackCredit == null)
{
// Add new
trackCredit = new data.Credit
{
ReleaseId = release.Id,
CreatedDate = now
};
DbContext.Credits.Add(trackCredit);
}
data.Artist artistForCredit = null;
if (credit.Artist != null)
{
artistForCredit = await GetArtist(credit.Artist.Id);
}
var creditCategory = DbContext.CreditCategory.FirstOrDefault(x => x.RoadieId.ToString() == credit.Category.Value);
trackCredit.CreditCategoryId = creditCategory.Id;
trackCredit.ArtistId = artistForCredit == null ? null : (int?)artistForCredit.Id;
trackCredit.IsLocked = credit.IsLocked;
trackCredit.Status = SafeParser.ToEnum<Statuses>(credit.Status);
trackCredit.CreditToName = artistForCredit == null ? credit.CreditName : null;
trackCredit.Description = credit.Description;
trackCredit.URLs = credit.URLs;
trackCredit.Tags = credit.Tags;
trackCredit.LastUpdated = now;
}
}
release.LastUpdated = now;
await DbContext.SaveChangesAsync();
@ -1761,7 +1847,7 @@ namespace Roadie.Api.Services
sw.Start();
tsw.Restart();
var release = GetRelease(id);
var release = await GetRelease(id);
tsw.Stop();
timings.Add("getRelease", tsw.ElapsedMilliseconds);
@ -1771,9 +1857,9 @@ namespace Roadie.Api.Services
}
tsw.Restart();
var result = release.Adapt<Release>();
result.Artist = ArtistList.FromDataArtist(release.Artist, MakeArtistThumbnailImage(Configuration, HttpContext, release.Artist.RoadieId));
result.Thumbnail = MakeReleaseThumbnailImage(Configuration, HttpContext, release.RoadieId);
result.MediumThumbnail = MakeThumbnailImage(Configuration, HttpContext, id, "release", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
result.Artist = ArtistList.FromDataArtist(release.Artist, ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, release.Artist.RoadieId));
result.Thumbnail = ImageHelper.MakeReleaseThumbnailImage(Configuration, HttpContext, release.RoadieId);
result.MediumThumbnail = ImageHelper.MakeThumbnailImage(Configuration, HttpContext, id, "release", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
result.ReleasePlayUrl = $"{HttpContext.BaseUrl}/play/release/{release.RoadieId}";
result.Profile = release.Profile;
result.ReleaseDate = release.ReleaseDate.Value;
@ -1804,7 +1890,7 @@ namespace Roadie.Api.Services
Text = submission.User.UserName,
Value = submission.User.RoadieId.ToString()
},
UserThumbnail = MakeUserThumbnailImage(Configuration, HttpContext, submission.User.RoadieId),
UserThumbnail = ImageHelper.MakeUserThumbnailImage(Configuration, HttpContext, submission.User.RoadieId),
SubmittedDate = submission.CreatedDate
};
}
@ -1815,14 +1901,50 @@ namespace Roadie.Api.Services
if (includes != null && includes.Any())
{
if(includes.Contains("credits"))
{
tsw.Restart();
result.Credits = (await (from c in DbContext.Credits
join cc in DbContext.CreditCategory on c.CreditCategoryId equals cc.Id
join a in DbContext.Artists on c.ArtistId equals a.Id into agg
from a in agg.DefaultIfEmpty()
where c.ReleaseId == release.Id
select new { c, cc, a })
.ToListAsync())
.Select(x => new CreditList
{
Id = x.c.RoadieId,
Artist = x.a == null ? null : ArtistList.FromDataArtist(x.a, ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, x.a.RoadieId)),
Category = new DataToken {
Text =x.cc.Name,
Value = x.cc.RoadieId.ToString()
},
CreditName = x.a?.Name ?? x.c.CreditToName,
Description = x.c.Description
}).ToArray();
tsw.Stop();
timings.Add("credits", tsw.ElapsedMilliseconds);
}
if (includes.Contains("genres"))
{
tsw.Restart();
result.Genres = release.Genres.Select(x => new DataToken
{
Text = x.Genre.Name,
Value = x.Genre.RoadieId.ToString()
});
var releaseGenreIds = release.Genres.Select(x => x.GenreId).ToArray();
result.Genres = (await (from g in DbContext.Genres
let releaseCount = (from rg in DbContext.ReleaseGenres
where rg.GenreId == g.Id
select rg.Id).Count()
let artistCount = (from rg in DbContext.ArtistGenres
where rg.GenreId == g.Id
select rg.Id).Count()
where releaseGenreIds.Contains(g.Id)
select new { g, releaseCount, artistCount }).ToListAsync())
.Select(x => GenreList.FromDataGenre(x.g,
ImageHelper.MakeGenreThumbnailImage(Configuration, HttpContext, x.g.RoadieId),
x.artistCount,
x.releaseCount))
.ToArray();
tsw.Stop();
timings.Add("genres", tsw.ElapsedMilliseconds);
}
@ -1873,7 +1995,7 @@ namespace Roadie.Api.Services
var releaseImagesInFolder = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(releaseFolder), ImageType.ReleaseSecondary, SearchOption.TopDirectoryOnly);
if (releaseImagesInFolder.Any())
{
result.Images = releaseImagesInFolder.Select((x, i) => MakeFullsizeSecondaryImage(Configuration, HttpContext, id, ImageType.ReleaseSecondary, i));
result.Images = releaseImagesInFolder.Select((x, i) => ImageHelper.MakeFullsizeSecondaryImage(Configuration, HttpContext, id, ImageType.ReleaseSecondary, i));
}
tsw.Stop();
timings.Add("images", tsw.ElapsedMilliseconds);
@ -1930,7 +2052,7 @@ namespace Roadie.Api.Services
ArtistCount = releaseLabel.l.ArtistCount,
ReleaseCount = releaseLabel.l.ReleaseCount,
TrackCount = releaseLabel.l.TrackCount,
Thumbnail = MakeLabelThumbnailImage(Configuration, HttpContext, releaseLabel.l.RoadieId)
Thumbnail = ImageHelper.MakeLabelThumbnailImage(Configuration, HttpContext, releaseLabel.l.RoadieId)
}
};
labels.Add(rl);
@ -1975,7 +2097,7 @@ namespace Roadie.Api.Services
CreatedDate = releaseCollection.Collection.CreatedDate,
IsLocked = releaseCollection.Collection.IsLocked,
LastUpdated = releaseCollection.Collection.LastUpdated,
Thumbnail = MakeCollectionThumbnailImage(Configuration, HttpContext, releaseCollection.Collection.RoadieId)
Thumbnail = ImageHelper.MakeCollectionThumbnailImage(Configuration, HttpContext, releaseCollection.Collection.RoadieId)
},
ListNumber = releaseCollection.ListNumber
});
@ -2004,7 +2126,7 @@ namespace Roadie.Api.Services
{
var comment = releaseComment.Adapt<Comment>();
comment.DatabaseId = releaseComment.Id;
comment.User = UserList.FromDataUser(releaseComment.User, MakeUserThumbnailImage(Configuration, HttpContext, releaseComment.User.RoadieId));
comment.User = UserList.FromDataUser(releaseComment.User, ImageHelper.MakeUserThumbnailImage(Configuration, HttpContext, releaseComment.User.RoadieId));
comment.DislikedCount = userCommentReactions.Count(x => x.CommentId == releaseComment.Id && x.ReactionValue == CommentReaction.Dislike);
comment.LikedCount = userCommentReactions.Count(x => x.CommentId == releaseComment.Id && x.ReactionValue == CommentReaction.Like);
comments.Add(comment);
@ -2035,7 +2157,7 @@ namespace Roadie.Api.Services
t.Status = track.Status;
t.TrackArtist = track.TrackArtist != null
? ArtistList.FromDataArtist(track.TrackArtist,
MakeArtistThumbnailImage(Configuration, HttpContext, track.TrackArtist.RoadieId))
ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, track.TrackArtist.RoadieId))
: null;
rmTracks.Add(t);
}
@ -2091,7 +2213,7 @@ namespace Roadie.Api.Services
return new OperationResult<Image>
{
IsSuccess = !errors.Any(),
Data = MakeThumbnailImage(Configuration, HttpContext, id, "release", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height, true),
Data = ImageHelper.MakeThumbnailImage(Configuration, HttpContext, id, "release", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height, true),
OperationTime = sw.ElapsedMilliseconds,
Errors = errors
};

View file

@ -8,7 +8,6 @@ using Roadie.Library.Data.Context;
using Roadie.Library.Encoding;
using Roadie.Library.Enums;
using Roadie.Library.Identity;
using Roadie.Library.Models;
using Roadie.Library.Utility;
using System;
using System.Collections.Generic;
@ -72,10 +71,7 @@ namespace Roadie.Api.Services
return TrackPlayToken(user, trackRoadieId).Equals(token);
}
public static string MakeTrackPlayUrl(ApplicationUser user, string baseUrl, int trackId, Guid trackRoadieId)
{
return $"{baseUrl}/play/track/{user.Id}/{TrackPlayToken(user, trackRoadieId)}/{trackRoadieId}.mp3";
}
public static string MakeTrackPlayUrl(ApplicationUser user, string baseUrl, Guid trackRoadieId) => $"{baseUrl}/play/track/{user.Id}/{TrackPlayToken(user, trackRoadieId)}/{trackRoadieId}.mp3";
public static string TrackPlayToken(ApplicationUser user, Guid trackId)
{
@ -88,11 +84,6 @@ namespace Roadie.Api.Services
return token;
}
public static Image MakeThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id, string type, int? width = null, int? height = null, bool includeCachebuster = false)
{
return MakeImage(configuration, httpContext, id, type, width ?? configuration.ThumbnailImageSize.Width, height ?? configuration.ThumbnailImageSize.Height, null, includeCachebuster);
}
protected IEnumerable<int> ArtistIdsForRelease(int releaseId)
{
var trackArtistIds = (from r in DbContext.Releases
@ -105,219 +96,137 @@ namespace Roadie.Api.Services
return trackArtistIds.Distinct().ToArray();
}
protected data.Artist GetArtist(string artistName)
protected async Task<data.Artist> GetArtist(string artistName)
{
if (string.IsNullOrEmpty(artistName)) return null;
var artistByName = CacheManager.Get(data.Artist.CacheUrnByName(artistName), () =>
{
return DbContext.Artists
.FirstOrDefault(x => x.Name == artistName);
}, null);
var artistByName = await CacheManager.GetAsync(data.Artist.CacheUrnByName(artistName), async () =>
{
return await DbContext.Artists
.FirstOrDefaultAsync(x => x.Name == artistName);
}, null);
if (artistByName == null) return null;
return GetArtist(artistByName.RoadieId);
return await GetArtist(artistByName.RoadieId);
}
protected data.Artist GetArtist(Guid id)
protected async Task<data.Artist> GetArtist(Guid id)
{
return CacheManager.Get(data.Artist.CacheUrn(id), () =>
return await CacheManager.GetAsync(data.Artist.CacheUrn(id), async () =>
{
return DbContext.Artists
return await DbContext.Artists
.Include(x => x.Genres)
.Include("Genres.Genre")
.FirstOrDefault(x => x.RoadieId == id);
.FirstOrDefaultAsync(x => x.RoadieId == id);
}, data.Artist.CacheRegionUrn(id));
}
protected data.Collection GetCollection(Guid id)
protected async Task<data.Collection> GetCollection(Guid id)
{
return CacheManager.Get(data.Collection.CacheUrn(id), () =>
return await CacheManager.GetAsync(data.Collection.CacheUrn(id), async () =>
{
return DbContext.Collections
.FirstOrDefault(x => x.RoadieId == id);
return await DbContext.Collections
.FirstOrDefaultAsync(x => x.RoadieId == id);
}, data.Collection.CacheRegionUrn(id));
}
protected data.Genre GetGenre(Guid id)
protected async Task<data.Genre> GetGenre(Guid id)
{
return CacheManager.Get(data.Genre.CacheUrn(id), () =>
return await CacheManager.GetAsync(data.Genre.CacheUrn(id), async () =>
{
return DbContext.Genres
.FirstOrDefault(x => x.RoadieId == id);
return await DbContext.Genres
.FirstOrDefaultAsync(x => x.RoadieId == id);
}, data.Genre.CacheRegionUrn(id));
}
protected data.Label GetLabel(Guid id)
protected async Task<data.Label> GetLabel(Guid id)
{
return CacheManager.Get(data.Label.CacheUrn(id), () =>
return await CacheManager.GetAsync(data.Label.CacheUrn(id), async () =>
{
return DbContext.Labels
.FirstOrDefault(x => x.RoadieId == id);
return await DbContext.Labels
.FirstOrDefaultAsync(x => x.RoadieId == id);
}, data.Label.CacheRegionUrn(id));
}
protected data.Playlist GetPlaylist(Guid id)
protected async Task<data.Playlist> GetPlaylist(Guid id)
{
return CacheManager.Get(data.Playlist.CacheUrn(id), () =>
return await CacheManager.Get(data.Playlist.CacheUrn(id), async () =>
{
return DbContext.Playlists
return await DbContext.Playlists
.Include(x => x.User)
.FirstOrDefault(x => x.RoadieId == id);
.FirstOrDefaultAsync(x => x.RoadieId == id);
}, data.Playlist.CacheRegionUrn(id));
}
protected data.Release GetRelease(Guid id)
protected async Task<data.Release> GetRelease(Guid id)
{
return CacheManager.Get(data.Release.CacheUrn(id), () =>
return await CacheManager.Get(data.Release.CacheUrn(id), async () =>
{
return DbContext.Releases
return await DbContext.Releases
.Include(x => x.Artist)
.Include(x => x.Genres)
.Include("Genres.Genre")
.Include(x => x.Medias)
.Include("Medias.Tracks")
.Include("Medias.Tracks.TrackArtist")
.FirstOrDefault(x => x.RoadieId == id);
.FirstOrDefaultAsync(x => x.RoadieId == id);
}, data.Release.CacheRegionUrn(id));
}
/// <summary>
/// Get Track by Subsonic Id ("T:guid")
/// </summary>
protected data.Track GetTrack(string id)
protected async Task<data.Track> GetTrack(string id)
{
var trackId = Guid.Empty;
if (Guid.TryParse(id, out trackId)) return GetTrack(trackId);
if (Guid.TryParse(id, out Guid trackId))
{
return await GetTrack(trackId);
}
return null;
}
// Only read operations
protected data.Track GetTrack(Guid id)
protected async Task<data.Track> GetTrack(Guid id)
{
return CacheManager.Get(data.Track.CacheUrn(id), () =>
return await CacheManager.GetAsync(data.Track.CacheUrn(id), async () =>
{
return DbContext.Tracks
return await DbContext.Tracks
.Include(x => x.ReleaseMedia)
.Include(x => x.ReleaseMedia.Release)
.Include(x => x.ReleaseMedia.Release.Artist)
.Include(x => x.TrackArtist)
.FirstOrDefault(x => x.RoadieId == id);
.FirstOrDefaultAsync(x => x.RoadieId == id);
}, data.Track.CacheRegionUrn(id));
}
protected ApplicationUser GetUser(string username)
protected async Task<ApplicationUser> GetUser(string username)
{
if (string.IsNullOrEmpty(username)) return null;
var userByUsername = CacheManager.Get(ApplicationUser.CacheUrnByUsername(username),
() => { return DbContext.Users.FirstOrDefault(x => x.UserName == username); }, null);
return GetUser(userByUsername?.RoadieId);
}
protected ApplicationUser GetUser(Guid? id)
{
if (!id.HasValue) return null;
return CacheManager.Get(ApplicationUser.CacheUrn(id.Value), () =>
if (string.IsNullOrEmpty(username))
{
return DbContext.Users
.Include(x => x.UserRoles)
.Include("UserRoles.Role")
.Include("UserRoles.Role.RoleClaims")
.Include(x => x.Claims)
.Include(x => x.UserQues)
.Include("UserQues.Track")
.FirstOrDefault(x => x.RoadieId == id);
}, ApplicationUser.CacheRegionUrn(id.Value));
}
protected static Image MakeArtistThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid? id)
{
if (!id.HasValue) return null;
return MakeThumbnailImage(configuration, httpContext, id.Value, "artist");
}
protected static Image MakeCollectionThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
{
return MakeThumbnailImage(configuration, httpContext, id, "collection");
}
protected static Image MakeFullsizeImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id, string caption = null)
{
return new Image($"{httpContext.ImageBaseUrl}/{id}", caption,
$"{httpContext.ImageBaseUrl}/{id}/{configuration.SmallImageSize.Width}/{configuration.SmallImageSize.Height}");
}
protected static Image MakeFullsizeSecondaryImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id, ImageType type, int imageId, string caption = null)
{
if (type == ImageType.ArtistSecondary)
{
return new Image($"{httpContext.ImageBaseUrl}/artist-secondary/{id}/{imageId}", caption,
$"{httpContext.ImageBaseUrl}/artist-secondary/{id}/{imageId}/{configuration.SmallImageSize.Width}/{configuration.SmallImageSize.Height}");
return null;
}
return new Image($"{httpContext.ImageBaseUrl}/release-secondary/{id}/{imageId}", caption,
$"{httpContext.ImageBaseUrl}/release-secondary/{id}/{imageId}/{configuration.SmallImageSize.Width}/{configuration.SmallImageSize.Height}");
var userByUsername = await CacheManager.GetAsync(ApplicationUser.CacheUrnByUsername(username), async () =>
{
return await DbContext.Users.FirstOrDefaultAsync(x => x.UserName == username);
}, null);
return await GetUser(userByUsername?.RoadieId);
}
protected static Image MakeGenreThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
protected async Task<ApplicationUser> GetUser(Guid? id)
{
return MakeThumbnailImage(configuration, httpContext, id, "genre");
if (!id.HasValue) return null;
return await CacheManager.GetAsync(ApplicationUser.CacheUrn(id.Value), async () =>
{
return await DbContext.Users
.Include(x => x.UserRoles)
.Include("UserRoles.Role")
.Include("UserRoles.Role.RoleClaims")
.Include(x => x.Claims)
.Include(x => x.UserQues)
.Include("UserQues.Track")
.FirstOrDefaultAsync(x => x.RoadieId == id);
}, ApplicationUser.CacheRegionUrn(id.Value));
}
protected static Image MakeImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id, int width = 200, int height = 200, string caption = null, bool includeCachebuster = false)
{
return new Image(
$"{httpContext.ImageBaseUrl}/{id}/{width}/{height}/{(includeCachebuster ? DateTime.UtcNow.Ticks.ToString() : string.Empty)}",
caption,
$"{httpContext.ImageBaseUrl}/{id}/{configuration.SmallImageSize.Width}/{configuration.SmallImageSize.Height}");
}
protected static Image MakeImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id, string type, IImageSize imageSize)
{
return MakeImage(configuration, httpContext, id, type, imageSize.Width, imageSize.Height);
}
private static Image MakeImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id, string type, int? width, int? height, string caption = null, bool includeCachebuster = false)
{
if (width.HasValue && height.HasValue && (width.Value != configuration.ThumbnailImageSize.Width ||
height.Value != configuration.ThumbnailImageSize.Height))
return new Image(
$"{httpContext.ImageBaseUrl}/{type}/{id}/{width}/{height}/{(includeCachebuster ? DateTime.UtcNow.Ticks.ToString() : string.Empty)}",
caption,
$"{httpContext.ImageBaseUrl}/{type}/{id}/{configuration.ThumbnailImageSize.Width}/{configuration.ThumbnailImageSize.Height}");
return new Image($"{httpContext.ImageBaseUrl}/{type}/{id}", caption, null);
}
protected static Image MakeLabelThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
{
return MakeThumbnailImage(configuration, httpContext, id, "label");
}
protected string MakeLastFmUrl(string artistName, string releaseTitle)
{
return "http://www.last.fm/music/" + HttpEncoder.UrlEncode($"{artistName}/{releaseTitle}");
}
protected Image MakeNewImage(string type)
{
return new Image($"{HttpContext.ImageBaseUrl}/{type}.jpg", null, null);
}
protected static Image MakePlaylistThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
{
return MakeThumbnailImage(configuration, httpContext, id, "playlist");
}
protected static Image MakeReleaseThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
{
return MakeThumbnailImage(configuration, httpContext, id, "release");
}
protected static Image MakeTrackThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
{
return MakeThumbnailImage(configuration, httpContext, id, "track");
}
protected static Image MakeUserThumbnailImage(IRoadieSettings configuration, IHttpContext httpContext, Guid id)
{
return MakeThumbnailImage(configuration, httpContext, id, "user");
}
protected string MakeLastFmUrl(string artistName, string releaseTitle) => "http://www.last.fm/music/" + HttpEncoder.UrlEncode($"{artistName}/{releaseTitle}");
protected async Task<OperationResult<short>> SetArtistRating(Guid artistId, ApplicationUser user, short rating)
{
@ -358,7 +267,7 @@ namespace Roadie.Api.Services
CacheManager.ClearRegion(user.CacheRegion);
CacheManager.ClearRegion(artist.CacheRegion);
artist = GetArtist(artistId);
artist = await GetArtist(artistId);
return new OperationResult<short>
{
@ -367,8 +276,7 @@ namespace Roadie.Api.Services
};
}
protected async Task<OperationResult<short>> SetReleaseRating(Guid releaseId, ApplicationUser user,
short rating)
protected async Task<OperationResult<short>> SetReleaseRating(Guid releaseId, ApplicationUser user, short rating)
{
var release = DbContext.Releases
.Include(x => x.Artist)
@ -413,7 +321,7 @@ namespace Roadie.Api.Services
CacheManager.ClearRegion(release.CacheRegion);
CacheManager.ClearRegion(release.Artist.CacheRegion);
release = GetRelease(releaseId);
release = await GetRelease(releaseId);
return new OperationResult<short>
{
@ -477,8 +385,7 @@ namespace Roadie.Api.Services
};
}
protected async Task<OperationResult<bool>> ToggleArtistDisliked(Guid artistId, ApplicationUser user,
bool isDisliked)
protected async Task<OperationResult<bool>> ToggleArtistDisliked(Guid artistId, ApplicationUser user, bool isDisliked)
{
var artist = DbContext.Artists
.Include(x => x.Genres)
@ -594,8 +501,7 @@ namespace Roadie.Api.Services
};
}
protected async Task<OperationResult<bool>> ToggleReleaseFavorite(Guid releaseId, ApplicationUser user,
bool isFavorite)
protected async Task<OperationResult<bool>> ToggleReleaseFavorite(Guid releaseId, ApplicationUser user, bool isFavorite)
{
var release = DbContext.Releases
.Include(x => x.Artist)
@ -845,6 +751,7 @@ namespace Roadie.Api.Services
join t in DbContext.Tracks on rm.Id equals t.ReleaseMediaId
where rl.LabelId == label.Id
select t).Count();
label.LastUpdated = now;
await DbContext.SaveChangesAsync();
CacheManager.ClearRegion(label.CacheRegion);
}
@ -883,6 +790,7 @@ namespace Roadie.Api.Services
join rm in DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id
where rm.ReleaseId == releaseId
select t).Sum(x => x.Duration);
release.LastUpdated = now;
await DbContext.SaveChangesAsync();
CacheManager.ClearRegion(release.CacheRegion);
}
@ -941,7 +849,5 @@ namespace Roadie.Api.Services
updateArtistRank);
}
}
}
}

View file

@ -10,6 +10,7 @@ using Roadie.Library.Encoding;
using Roadie.Library.Enums;
using Roadie.Library.Extensions;
using Roadie.Library.Identity;
using Roadie.Library.Imaging;
using Roadie.Library.Models;
using Roadie.Library.Models.Pagination;
using Roadie.Library.Models.Playlists;
@ -228,7 +229,7 @@ namespace Roadie.Api.Services
await DbContext.SaveChangesAsync();
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
CacheManager.ClearRegion(user.CacheRegion);
Logger.LogTrace(
@ -353,7 +354,7 @@ namespace Roadie.Api.Services
DbContext.Bookmarks.Remove(userBookmark);
await DbContext.SaveChangesAsync();
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
CacheManager.ClearRegion(user.CacheRegion);
Logger.LogTrace($"Subsonic: Deleted Bookmark `{userBookmark}` for User `{roadieUser}`");
@ -417,7 +418,7 @@ namespace Roadie.Api.Services
if (!releaseId.HasValue)
return new subsonic.SubsonicOperationResult<subsonic.Response>(
subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Invalid Release [{request.ReleaseId}]");
var release = GetRelease(releaseId.Value);
var release = await GetRelease(releaseId.Value);
if (release == null)
return new subsonic.SubsonicOperationResult<subsonic.Response>(
subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Invalid Release [{request.ReleaseId}]");
@ -473,22 +474,19 @@ namespace Roadie.Api.Services
/// <summary>
/// Returns album notes, image URLs etc, using data from last.fm.
/// </summary>
public Task<subsonic.SubsonicOperationResult<subsonic.Response>> GetAlbumInfo(subsonic.Request request,
User roadieUser, subsonic.AlbumInfoVersion version)
public async Task<subsonic.SubsonicOperationResult<subsonic.Response>> GetAlbumInfo(subsonic.Request request, User roadieUser, subsonic.AlbumInfoVersion version)
{
var releaseId = SafeParser.ToGuid(request.id);
if (!releaseId.HasValue)
return Task.FromResult(new subsonic.SubsonicOperationResult<subsonic.Response>(
subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Invalid Release [{request.id}]"));
var release = GetRelease(releaseId.Value);
return new subsonic.SubsonicOperationResult<subsonic.Response>(subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Invalid Release [{request.id}]");
var release = await GetRelease(releaseId.Value);
if (release == null)
return Task.FromResult(new subsonic.SubsonicOperationResult<subsonic.Response>(
subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Invalid Release [{request.id}]"));
return new subsonic.SubsonicOperationResult<subsonic.Response>(subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Invalid Release [{request.id}]");
switch (version)
{
case subsonic.AlbumInfoVersion.One:
case subsonic.AlbumInfoVersion.Two:
return Task.FromResult(new subsonic.SubsonicOperationResult<subsonic.Response>
return new subsonic.SubsonicOperationResult<subsonic.Response>
{
IsSuccess = true,
Data = new subsonic.Response
@ -499,22 +497,22 @@ namespace Roadie.Api.Services
Item = new subsonic.AlbumInfo
{
largeImageUrl =
MakeImage(Configuration, HttpContext, release.RoadieId, "release", Configuration.LargeImageSize).Url,
mediumImageUrl = MakeImage(Configuration, HttpContext, release.RoadieId, "release", Configuration.MediumImageSize)
ImageHelper.MakeImage(Configuration, HttpContext, release.RoadieId, "release", Configuration.LargeImageSize).Url,
mediumImageUrl = ImageHelper.MakeImage(Configuration, HttpContext, release.RoadieId, "release", Configuration.MediumImageSize)
.Url,
smallImageUrl =
MakeImage(Configuration, HttpContext, release.RoadieId, "release", Configuration.SmallImageSize).Url,
ImageHelper.MakeImage(Configuration, HttpContext, release.RoadieId, "release", Configuration.SmallImageSize).Url,
lastFmUrl = MakeLastFmUrl(release.Artist.Name, release.Title),
musicBrainzId = release.MusicBrainzId,
notes = release.Profile
}
}
});
};
default:
return Task.FromResult(new subsonic.SubsonicOperationResult<subsonic.Response>(
return new subsonic.SubsonicOperationResult<subsonic.Response>(
subsonic.ErrorCodes.IncompatibleServerRestProtocolVersion,
$"Unknown Album Info Version [{request.Type}]"));
$"Unknown Album Info Version [{request.Type}]");
}
}
@ -631,22 +629,20 @@ namespace Roadie.Api.Services
/// <summary>
/// Returns artist info with biography, image URLs and similar artists, using data from last.fm.
/// </summary>
public Task<subsonic.SubsonicOperationResult<subsonic.Response>> GetArtistInfo(subsonic.Request request,
int? count, bool includeNotPresent, subsonic.ArtistInfoVersion version)
public async Task<subsonic.SubsonicOperationResult<subsonic.Response>> GetArtistInfo(subsonic.Request request, int? count, bool includeNotPresent, subsonic.ArtistInfoVersion version)
{
var artistId = SafeParser.ToGuid(request.id);
if (!artistId.HasValue)
return Task.FromResult(new subsonic.SubsonicOperationResult<subsonic.Response>(
subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Invalid ArtistId [{request.id}]"));
var artist = GetArtist(artistId.Value);
return new subsonic.SubsonicOperationResult<subsonic.Response>(subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Invalid ArtistId [{request.id}]");
var artist = await GetArtist(artistId.Value);
if (artist == null)
return Task.FromResult(new subsonic.SubsonicOperationResult<subsonic.Response>(
subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Invalid ArtistId [{request.id}]"));
{
return new subsonic.SubsonicOperationResult<subsonic.Response>(subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Invalid ArtistId [{request.id}]");
}
switch (version)
{
case subsonic.ArtistInfoVersion.One:
return Task.FromResult(new subsonic.SubsonicOperationResult<subsonic.Response>
return new subsonic.SubsonicOperationResult<subsonic.Response>
{
IsSuccess = true,
Data = new subsonic.Response
@ -656,10 +652,10 @@ namespace Roadie.Api.Services
ItemElementName = subsonic.ItemChoiceType.artistInfo,
Item = SubsonicArtistInfoForArtist(artist)
}
});
};
case subsonic.ArtistInfoVersion.Two:
return Task.FromResult(new subsonic.SubsonicOperationResult<subsonic.Response>
return new subsonic.SubsonicOperationResult<subsonic.Response>
{
IsSuccess = true,
Data = new subsonic.Response
@ -669,12 +665,12 @@ namespace Roadie.Api.Services
ItemElementName = subsonic.ItemChoiceType.artistInfo2,
Item = SubsonicArtistInfo2InfoForArtist(artist)
}
});
};
default:
return Task.FromResult(new subsonic.SubsonicOperationResult<subsonic.Response>(
return new subsonic.SubsonicOperationResult<subsonic.Response>(
subsonic.ErrorCodes.IncompatibleServerRestProtocolVersion,
$"Unknown ArtistInfoVersion [{version}]"));
$"Unknown ArtistInfoVersion [{version}]");
}
}
@ -756,59 +752,55 @@ namespace Roadie.Api.Services
/// <summary>
/// Returns a cover art image.
/// </summary>
public async Task<subsonic.SubsonicFileOperationResult<Image>> GetCoverArt(subsonic.Request request, int? size)
public async Task<subsonic.SubsonicFileOperationResult<Library.Models.Image>> GetCoverArt(subsonic.Request request, int? size)
{
var sw = Stopwatch.StartNew();
var result = new subsonic.SubsonicFileOperationResult<Image>
{
Data = new Image()
};
var result = new subsonic.SubsonicFileOperationResult<Library.Models.Image>();
if (request.ArtistId != null)
{
var artistImage = await ImageService.ArtistImage(request.ArtistId.Value, size, size);
if (!artistImage.IsSuccess) return artistImage.Adapt<subsonic.SubsonicFileOperationResult<Image>>();
result.Data.Bytes = artistImage.Data.Bytes;
if (!artistImage.IsSuccess) return artistImage.Adapt<subsonic.SubsonicFileOperationResult<Library.Models.Image>>();
result.Data = new Library.Models.Image(artistImage.Data.Bytes);
}
else if (request.TrackId != null)
{
var trackimage = await ImageService.TrackImage(request.TrackId.Value, size, size);
if (!trackimage.IsSuccess) return trackimage.Adapt<subsonic.SubsonicFileOperationResult<Image>>();
result.Data.Bytes = trackimage.Data.Bytes;
if (!trackimage.IsSuccess) return trackimage.Adapt<subsonic.SubsonicFileOperationResult<Library.Models.Image>>();
result.Data = new Library.Models.Image(trackimage.Data.Bytes);
}
else if (request.CollectionId != null)
{
var collectionImage = await ImageService.CollectionImage(request.CollectionId.Value, size, size);
if (!collectionImage.IsSuccess)
return collectionImage.Adapt<subsonic.SubsonicFileOperationResult<Image>>();
result.Data.Bytes = collectionImage.Data.Bytes;
return collectionImage.Adapt<subsonic.SubsonicFileOperationResult<Library.Models.Image>>();
result.Data = new Library.Models.Image(collectionImage.Data.Bytes);
}
else if (request.ReleaseId != null)
{
var releaseimage = await ImageService.ReleaseImage(request.ReleaseId.Value, size, size);
if (!releaseimage.IsSuccess) return releaseimage.Adapt<subsonic.SubsonicFileOperationResult<Image>>();
result.Data.Bytes = releaseimage.Data.Bytes;
if (!releaseimage.IsSuccess) return releaseimage.Adapt<subsonic.SubsonicFileOperationResult<Library.Models.Image>>();
result.Data = new Library.Models.Image(releaseimage.Data.Bytes);
}
else if (request.PlaylistId != null)
{
var playlistImage = await ImageService.PlaylistImage(request.PlaylistId.Value, size, size);
if (!playlistImage.IsSuccess) return playlistImage.Adapt<subsonic.SubsonicFileOperationResult<Image>>();
result.Data.Bytes = playlistImage.Data.Bytes;
if (!playlistImage.IsSuccess) return playlistImage.Adapt<subsonic.SubsonicFileOperationResult<Library.Models.Image>>();
result.Data = new Library.Models.Image(playlistImage.Data.Bytes);
}
else if (!string.IsNullOrEmpty(request.u))
{
var user = GetUser(request.u);
var user = await GetUser(request.u);
if (user == null)
return new subsonic.SubsonicFileOperationResult<Image>(
return new subsonic.SubsonicFileOperationResult<Library.Models.Image>(
subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Invalid Username [{request.u}]");
var userImage = await ImageService.UserImage(user.RoadieId, size, size);
if (!userImage.IsSuccess) return userImage.Adapt<subsonic.SubsonicFileOperationResult<Image>>();
result.Data.Bytes = userImage.Data.Bytes;
if (!userImage.IsSuccess) return userImage.Adapt<subsonic.SubsonicFileOperationResult<Library.Models.Image>>();
result.Data = new Library.Models.Image(userImage.Data.Bytes);
}
result.IsSuccess = result.Data.Bytes != null;
sw.Stop();
return new subsonic.SubsonicFileOperationResult<Image>(result.Messages)
return new subsonic.SubsonicFileOperationResult<Library.Models.Image>(result.Messages)
{
Data = result.Data,
ETag = result.ETag,
@ -936,17 +928,16 @@ namespace Roadie.Api.Services
/// getMusicDirectory.
/// </param>
/// <returns></returns>
public async Task<subsonic.SubsonicOperationResult<subsonic.Response>> GetMusicDirectory(
subsonic.Request request, User roadieUser)
public async Task<subsonic.SubsonicOperationResult<subsonic.Response>> GetMusicDirectory(subsonic.Request request, User roadieUser)
{
var directory = new subsonic.Directory();
var user = GetUser(roadieUser?.UserId);
var user = await GetUser(roadieUser?.UserId);
// Request to get albums for an Artist
if (request.ArtistId != null)
{
var artistId = SafeParser.ToGuid(request.id);
var artist = GetArtist(artistId.Value);
var artist = await GetArtist(artistId.Value);
if (artist == null)
return new subsonic.SubsonicOperationResult<subsonic.Response>(
subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Invalid ArtistId [{request.id}]");
@ -972,7 +963,7 @@ namespace Roadie.Api.Services
else if (request.CollectionId != null)
{
var collectionId = SafeParser.ToGuid(request.id);
var collection = GetCollection(collectionId.Value);
var collection = await GetCollection(collectionId.Value);
if (collection == null)
return new subsonic.SubsonicOperationResult<subsonic.Response>(
subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Invalid CollectionId [{request.id}]");
@ -988,7 +979,7 @@ namespace Roadie.Api.Services
else if (request.ReleaseId.HasValue)
{
var releaseId = SafeParser.ToGuid(request.id);
var release = GetRelease(releaseId.Value);
var release = await GetRelease(releaseId.Value);
if (release == null)
return new subsonic.SubsonicOperationResult<subsonic.Response>(
subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Invalid ReleaseId [{request.id}]");
@ -1171,7 +1162,7 @@ namespace Roadie.Api.Services
public async Task<subsonic.SubsonicOperationResult<subsonic.Response>> GetPlayQueue(subsonic.Request request,
User roadieUser)
{
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
subsonic.PlayQueue playQue = null;
@ -1436,8 +1427,8 @@ namespace Roadie.Api.Services
{
data.Artist artist = null;
if (!string.IsNullOrEmpty(request.ArtistName))
artist = base.GetArtist(request.ArtistName);
else if (request.ArtistId.HasValue) artist = GetArtist(request.ArtistId.Value);
artist = await base.GetArtist(request.ArtistName);
else if (request.ArtistId.HasValue) artist = await GetArtist(request.ArtistId.Value);
if (artist == null)
return new subsonic.SubsonicOperationResult<subsonic.Response>(
subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Unknown Artist [{request.ArtistName}]");
@ -1470,7 +1461,7 @@ namespace Roadie.Api.Services
public async Task<subsonic.SubsonicOperationResult<subsonic.Response>> GetUser(subsonic.Request request,
string username)
{
var user = GetUser(username);
var user = await GetUser(username);
if (user == null)
return new subsonic.SubsonicOperationResult<subsonic.Response>(
subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Invalid Username [{username}]");
@ -1533,7 +1524,7 @@ namespace Roadie.Api.Services
User roadieUser, string current, long? position)
{
// Remove any existing Que for User
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
if (user.UserQues != null && user.UserQues.Any()) DbContext.UserQues.RemoveRange(user.UserQues);
// Create a new UserQue for each posted TrackId in ids
@ -1663,7 +1654,7 @@ namespace Roadie.Api.Services
public async Task<subsonic.SubsonicOperationResult<subsonic.Response>> SetRating(subsonic.Request request,
User roadieUser, short rating)
{
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
if (user == null)
return new subsonic.SubsonicOperationResult<subsonic.Response>(
subsonic.ErrorCodes.UserIsNotAuthorizedForGivenOperation, $"Invalid User [{roadieUser}]");
@ -1711,7 +1702,7 @@ namespace Roadie.Api.Services
public async Task<subsonic.SubsonicOperationResult<subsonic.Response>> ToggleStar(subsonic.Request request,
User roadieUser, bool star, string[] albumIds = null, string[] artistIds = null)
{
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
if (user == null)
return new subsonic.SubsonicOperationResult<subsonic.Response>(
subsonic.ErrorCodes.UserIsNotAuthorizedForGivenOperation, $"Invalid User [{roadieUser}]");
@ -1799,7 +1790,7 @@ namespace Roadie.Api.Services
if (!request.PlaylistId.HasValue)
return new subsonic.SubsonicOperationResult<subsonic.Response>(
subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Invalid Playlist Id [{request.id}]");
var playlist = GetPlaylist(request.PlaylistId.Value);
var playlist = await GetPlaylist(request.PlaylistId.Value);
if (playlist == null)
return new subsonic.SubsonicOperationResult<subsonic.Response>(
subsonic.ErrorCodes.TheRequestedDataWasNotFound, $"Invalid Playlist Id [{request.TrackId.Value}]");
@ -1842,7 +1833,7 @@ namespace Roadie.Api.Services
await DbContext.SaveChangesAsync();
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
CacheManager.ClearRegion(user.CacheRegion);
return new subsonic.SubsonicOperationResult<subsonic.Response>
@ -1941,7 +1932,7 @@ namespace Roadie.Api.Services
{
id = subsonic.Request.CollectionIdentifier + c.RoadieId,
name = c.Name,
artistImageUrl = MakeCollectionThumbnailImage(Configuration, HttpContext, c.RoadieId).Url,
artistImageUrl = ImageHelper.MakeCollectionThumbnailImage(Configuration, HttpContext, c.RoadieId).Url,
averageRating = 0,
userRating = 0
}).ToArray()
@ -2072,7 +2063,7 @@ namespace Roadie.Api.Services
{
id = subsonic.Request.ArtistIdIdentifier + artist.Artist.Value,
name = artist.Artist.Text,
artistImageUrl = MakeArtistThumbnailImage(Configuration, HttpContext, artist.Id).Url,
artistImageUrl = ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, artist.Id).Url,
averageRating = artist.Rating ?? 0,
averageRatingSpecified = true,
starred = artist.UserRating?.RatedDate ?? DateTime.UtcNow,
@ -2084,7 +2075,7 @@ namespace Roadie.Api.Services
private subsonic.ArtistID3 SubsonicArtistID3ForArtist(ArtistList artist)
{
var artistImageUrl = MakeArtistThumbnailImage(Configuration, HttpContext, artist.Id).Url;
var artistImageUrl = ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, artist.Id).Url;
return new subsonic.ArtistID3
{
id = subsonic.Request.ArtistIdIdentifier + artist.Artist.Value,
@ -2108,11 +2099,11 @@ namespace Roadie.Api.Services
return new subsonic.ArtistInfo2
{
biography = artist.BioContext,
largeImageUrl = MakeImage(Configuration, HttpContext, artist.RoadieId, "artist", Configuration.LargeImageSize).Url,
mediumImageUrl = MakeImage(Configuration, HttpContext, artist.RoadieId, "artist", Configuration.MediumImageSize).Url,
largeImageUrl = ImageHelper.MakeImage(Configuration, HttpContext, artist.RoadieId, "artist", Configuration.LargeImageSize).Url,
mediumImageUrl = ImageHelper.MakeImage(Configuration, HttpContext, artist.RoadieId, "artist", Configuration.MediumImageSize).Url,
musicBrainzId = artist.MusicBrainzId,
similarArtist = new subsonic.ArtistID3[0],
smallImageUrl = MakeImage(Configuration, HttpContext, artist.RoadieId, "artist", Configuration.SmallImageSize).Url
smallImageUrl = ImageHelper.MakeImage(Configuration, HttpContext, artist.RoadieId, "artist", Configuration.SmallImageSize).Url
};
}
@ -2121,11 +2112,11 @@ namespace Roadie.Api.Services
return new subsonic.ArtistInfo
{
biography = artist.BioContext,
largeImageUrl = MakeImage(Configuration, HttpContext, artist.RoadieId, "artist", Configuration.LargeImageSize).Url,
mediumImageUrl = MakeImage(Configuration, HttpContext, artist.RoadieId, "artist", Configuration.MediumImageSize).Url,
largeImageUrl = ImageHelper.MakeImage(Configuration, HttpContext, artist.RoadieId, "artist", Configuration.LargeImageSize).Url,
mediumImageUrl = ImageHelper.MakeImage(Configuration, HttpContext, artist.RoadieId, "artist", Configuration.MediumImageSize).Url,
musicBrainzId = artist.MusicBrainzId,
similarArtist = new subsonic.Artist[0],
smallImageUrl = MakeImage(Configuration, HttpContext, artist.RoadieId, "artist", Configuration.SmallImageSize).Url
smallImageUrl = ImageHelper.MakeImage(Configuration, HttpContext, artist.RoadieId, "artist", Configuration.SmallImageSize).Url
};
}
@ -2138,7 +2129,7 @@ namespace Roadie.Api.Services
private subsonic.ArtistWithAlbumsID3 SubsonicArtistWithAlbumsID3ForArtist(ArtistList artist,
subsonic.AlbumID3[] releases)
{
var artistImageUrl = MakeArtistThumbnailImage(Configuration, HttpContext, artist.Id).Url;
var artistImageUrl = ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, artist.Id).Url;
return new subsonic.ArtistWithAlbumsID3
{
id = subsonic.Request.ArtistIdIdentifier + artist.Artist.Value,
@ -2291,7 +2282,7 @@ namespace Roadie.Api.Services
{
return new subsonic.PlaylistWithSongs
{
coverArt = MakePlaylistThumbnailImage(Configuration, HttpContext, playlist.Id).Url,
coverArt = ImageHelper.MakePlaylistThumbnailImage(Configuration, HttpContext, playlist.Id).Url,
allowedUser = playlist.IsPublic ? AllowedUsers() : null,
changed = playlist.LastUpdated ?? playlist.CreatedDate ?? DateTime.UtcNow,
created = playlist.CreatedDate ?? DateTime.UtcNow,

View file

@ -129,16 +129,16 @@ namespace Roadie.Api.Services
if (result?.Data != null && roadieUser != null)
{
tsw.Restart();
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
tsw.Stop();
timings.Add("getUser", tsw.ElapsedMilliseconds);
tsw.Restart();
var track = GetTrack(id);
var track = await GetTrack(id);
tsw.Stop();
timings.Add("getTrack", tsw.ElapsedMilliseconds);
result.Data.TrackPlayUrl = MakeTrackPlayUrl(user, HttpContext.BaseUrl, track.Id, track.RoadieId);
result.Data.TrackPlayUrl = MakeTrackPlayUrl(user, HttpContext.BaseUrl, track.RoadieId);
tsw.Restart();
var userBookmarkResult = await BookmarkService.List(roadieUser, new PagedRequest(), false, BookmarkType.Track);
@ -227,7 +227,7 @@ namespace Roadie.Api.Services
var playlistTrackIds = new int[0];
if (request.FilterToPlaylistId.HasValue)
{
var playlistTrackInfos = (from plt in DbContext.PlaylistTracks
var playlistTrackInfos = await (from plt in DbContext.PlaylistTracks
join p in DbContext.Playlists on plt.PlayListId equals p.Id
join t in DbContext.Tracks on plt.TrackId equals t.Id
where p.RoadieId == request.FilterToPlaylistId.Value
@ -236,7 +236,7 @@ namespace Roadie.Api.Services
{
plt.ListNumber,
t.Id
}).ToArray();
}).ToArrayAsync();
rowCount = playlistTrackInfos.Count();
playListTrackPositions = playlistTrackInfos
@ -255,7 +255,7 @@ namespace Roadie.Api.Services
{
request.Limit = roadieUser?.PlayerTrackLimit ?? 50;
collectionTrackIds = (from cr in DbContext.CollectionReleases
collectionTrackIds = await (from cr in DbContext.CollectionReleases
join c in DbContext.Collections on cr.CollectionId equals c.Id
join r in DbContext.Releases on cr.ReleaseId equals r.Id
join rm in DbContext.ReleaseMedias on r.Id equals rm.ReleaseId
@ -265,7 +265,7 @@ namespace Roadie.Api.Services
select t.Id)
.Skip(request.SkipValue)
.Take(request.LimitValue)
.ToArray();
.ToArrayAsync();
}
IQueryable<int> topTrackids = null;
@ -388,7 +388,7 @@ namespace Roadie.Api.Services
Text = r.Title,
Value = r.RoadieId.ToString()
},
ArtistThumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, releaseArtist.RoadieId),
ArtistThumbnail = ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, releaseArtist.RoadieId),
CreatedDate = r.CreatedDate,
Duration = r.Duration,
LastPlayed = r.LastPlayed,
@ -400,7 +400,7 @@ namespace Roadie.Api.Services
ReleaseDateDateTime = r.ReleaseDate,
ReleasePlayUrl = $"{HttpContext.BaseUrl}/play/release/{r.RoadieId}",
Status = r.Status,
Thumbnail = MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId),
Thumbnail = ImageHelper.MakeReleaseThumbnailImage(Configuration, HttpContext, r.RoadieId),
TrackCount = r.TrackCount,
TrackPlayedCount = r.PlayedCount
},
@ -421,7 +421,7 @@ namespace Roadie.Api.Services
ReleaseCount = trackArtist.ReleaseCount,
TrackCount = trackArtist.TrackCount,
SortName = trackArtist.SortName,
Thumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, trackArtist.RoadieId)
Thumbnail = ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, trackArtist.RoadieId)
},
ra = new ArtistList
{
@ -438,7 +438,7 @@ namespace Roadie.Api.Services
ReleaseCount = releaseArtist.ReleaseCount,
TrackCount = releaseArtist.TrackCount,
SortName = releaseArtist.SortName,
Thumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, releaseArtist.RoadieId)
Thumbnail = ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, releaseArtist.RoadieId)
}
};
@ -452,7 +452,7 @@ namespace Roadie.Api.Services
}
}
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
var result = resultQuery.Select(x =>
new TrackList
{
@ -476,11 +476,11 @@ namespace Roadie.Api.Services
Rating = x.ti.Rating,
Release = x.rl,
ReleaseDate = x.rl.ReleaseDateDateTime,
Thumbnail = MakeTrackThumbnailImage(Configuration, HttpContext, x.ti.RoadieId),
Thumbnail = ImageHelper.MakeTrackThumbnailImage(Configuration, HttpContext, x.ti.RoadieId),
Title = x.ti.Title,
TrackArtist = x.ta,
TrackNumber = x.ti.TrackNumber,
TrackPlayUrl = MakeTrackPlayUrl(user, HttpContext.BaseUrl, x.ti.Id, x.ti.RoadieId)
TrackPlayUrl = MakeTrackPlayUrl(user, HttpContext.BaseUrl, x.ti.RoadieId)
});
string sortBy = null;
@ -513,7 +513,7 @@ namespace Roadie.Api.Services
if (doRandomize ?? false)
{
var resultData = result.ToArray();
var resultData = await result.ToArrayAsync();
rows = (from r in resultData
join ra in randomTrackData on r.DatabaseId equals ra.Value
orderby ra.Key
@ -522,19 +522,19 @@ namespace Roadie.Api.Services
}
else
{
rows = result
.OrderBy(sortBy)
.Skip(request.SkipValue)
.Take(request.LimitValue)
.ToArray();
rows = await result
.OrderBy(sortBy)
.Skip(request.SkipValue)
.Take(request.LimitValue)
.ToArrayAsync();
}
if (rows.Any() && roadieUser != null)
{
var rowIds = rows.Select(x => x.DatabaseId).ToArray();
var userTrackRatings = (from ut in DbContext.UserTracks
var userTrackRatings = await (from ut in DbContext.UserTracks
where ut.UserId == roadieUser.Id
where rowIds.Contains(ut.TrackId)
select ut).ToArray();
select ut).ToArrayAsync();
foreach (var userTrackRating in userTrackRatings)
{
var row = rows.FirstOrDefault(x => x.DatabaseId == userTrackRating.TrackId);
@ -552,10 +552,10 @@ namespace Roadie.Api.Services
}
var releaseIds = rows.Select(x => x.Release.DatabaseId).Distinct().ToArray();
var userReleaseRatings = (from ur in DbContext.UserReleases
var userReleaseRatings = await (from ur in DbContext.UserReleases
where ur.UserId == roadieUser.Id
where releaseIds.Contains(ur.ReleaseId)
select ur).ToArray();
select ur).ToArrayAsync();
foreach (var userReleaseRating in userReleaseRatings)
{
foreach (var row in rows.Where(x => x.Release.DatabaseId == userReleaseRating.ReleaseId))
@ -567,10 +567,10 @@ namespace Roadie.Api.Services
var artistIds = rows.Select(x => x.Artist.DatabaseId).ToArray();
if (artistIds != null && artistIds.Any())
{
var userArtistRatings = (from ua in DbContext.UserArtists
var userArtistRatings = await (from ua in DbContext.UserArtists
where ua.UserId == roadieUser.Id
where artistIds.Contains(ua.ArtistId)
select ua).ToArray();
select ua).ToArrayAsync();
foreach (var userArtistRating in userArtistRatings)
{
foreach (var artistTrack in rows.Where(
@ -584,10 +584,10 @@ namespace Roadie.Api.Services
var trackArtistIds = rows.Where(x => x.TrackArtist != null).Select(x => x.TrackArtist.DatabaseId).ToArray();
if (trackArtistIds != null && trackArtistIds.Any())
{
var userTrackArtistRatings = (from ua in DbContext.UserArtists
var userTrackArtistRatings = await (from ua in DbContext.UserArtists
where ua.UserId == roadieUser.Id
where trackArtistIds.Contains(ua.ArtistId)
select ua).ToArray();
select ua).ToArrayAsync();
if (userTrackArtistRatings != null && userTrackArtistRatings.Any())
{
foreach (var userTrackArtistRating in userTrackArtistRatings)
@ -606,10 +606,10 @@ namespace Roadie.Api.Services
if (rows.Any())
{
var rowIds = rows.Select(x => x.DatabaseId).ToArray();
var favoriteUserTrackRatings = (from ut in DbContext.UserTracks
var favoriteUserTrackRatings = await (from ut in DbContext.UserTracks
where ut.IsFavorite ?? false
where rowIds.Contains(ut.TrackId)
select ut).ToArray();
select ut).ToArrayAsync();
foreach (var row in rows)
{
row.FavoriteCount = favoriteUserTrackRatings.Where(x => x.TrackId == row.DatabaseId).Count();
@ -841,7 +841,7 @@ namespace Roadie.Api.Services
var artistId = SafeParser.ToGuid(model.TrackArtistToken.Value);
if (artistId.HasValue)
{
trackArtist = GetArtist(artistId.Value);
trackArtist = await GetArtist(artistId.Value);
if (trackArtist != null)
{
track.ArtistId = trackArtist.Id;
@ -853,6 +853,56 @@ namespace Roadie.Api.Services
track.ArtistId = null;
}
if(model.Credits == null || !model.Credits.Any())
{
// Delete all existing credits for track
var trackCreditsToDelete = (from c in DbContext.Credits
where c.TrackId == track.Id
select c).ToArray();
DbContext.Credits.RemoveRange(trackCreditsToDelete);
}
else if(model.Credits != null && model.Credits.Any())
{
var trackCreditIds = model.Credits.Select(x => x.Id).ToArray();
// Delete any credits not given in model (removed by edit operation)
var trackCreditsToDelete = (from c in DbContext.Credits
where c.TrackId == track.Id
where !trackCreditIds.Contains(c.RoadieId)
select c).ToArray();
DbContext.Credits.RemoveRange(trackCreditsToDelete);
// Update any existing
foreach(var credit in model.Credits)
{
var trackCredit = DbContext.Credits.FirstOrDefault(x => x.RoadieId == credit.Id);
if(trackCredit == null)
{
// Add new
trackCredit = new data.Credit
{
TrackId = track.Id,
CreatedDate = now
};
DbContext.Credits.Add(trackCredit);
}
data.Artist artistForCredit = null;
if (credit.Artist != null)
{
artistForCredit = await GetArtist(credit.Artist.Id);
}
var creditCategory = DbContext.CreditCategory.FirstOrDefault(x => x.RoadieId.ToString() == credit.Category.Value);
trackCredit.CreditCategoryId = creditCategory.Id;
trackCredit.ArtistId = artistForCredit == null ? null : (int?)artistForCredit.Id;
trackCredit.IsLocked = credit.IsLocked;
trackCredit.Status = SafeParser.ToEnum<Statuses>(credit.Status);
trackCredit.CreditToName = artistForCredit == null ? credit.CreditName : null;
trackCredit.Description = credit.Description;
trackCredit.URLs = credit.URLs;
trackCredit.Tags = credit.Tags;
trackCredit.LastUpdated = now;
}
}
var trackImage = ImageHelper.ImageDataFromUrl(model.NewThumbnailData);
if (trackImage != null)
{
@ -902,7 +952,7 @@ namespace Roadie.Api.Services
};
}
private Task<OperationResult<Track>> TrackByIdAction(Guid id, IEnumerable<string> includes)
private async Task<OperationResult<Track>> TrackByIdAction(Guid id, IEnumerable<string> includes)
{
var timings = new Dictionary<string, long>();
var tsw = new Stopwatch();
@ -911,13 +961,13 @@ namespace Roadie.Api.Services
sw.Start();
tsw.Restart();
var track = GetTrack(id);
var track = await GetTrack(id);
tsw.Stop();
timings.Add("getTrack", tsw.ElapsedMilliseconds);
if (track == null)
{
return Task.FromResult(new OperationResult<Track>(true, string.Format("Track Not Found [{0}]", id)));
return new OperationResult<Track>(true, string.Format("Track Not Found [{0}]", id));
}
tsw.Restart();
var result = track.Adapt<Track>();
@ -925,16 +975,16 @@ namespace Roadie.Api.Services
(track.ReleaseMedia.IsLocked ?? false) ||
(track.ReleaseMedia.Release.IsLocked ?? false) ||
(track.ReleaseMedia.Release.Artist.IsLocked ?? false);
result.Thumbnail = MakeTrackThumbnailImage(Configuration, HttpContext, id);
result.MediumThumbnail = MakeThumbnailImage(Configuration, HttpContext, id, "track", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
result.Thumbnail = ImageHelper.MakeTrackThumbnailImage(Configuration, HttpContext, id);
result.MediumThumbnail = ImageHelper.MakeThumbnailImage(Configuration, HttpContext, id, "track", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
result.ReleaseMediaId = track.ReleaseMedia.RoadieId.ToString();
result.Artist = ArtistList.FromDataArtist(track.ReleaseMedia.Release.Artist,
MakeArtistThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.Artist.RoadieId));
result.ArtistThumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.Artist.RoadieId);
ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.Artist.RoadieId));
result.ArtistThumbnail = ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.Artist.RoadieId);
result.Release = ReleaseList.FromDataRelease(track.ReleaseMedia.Release, track.ReleaseMedia.Release.Artist,
HttpContext.BaseUrl, MakeArtistThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.Artist.RoadieId),
MakeReleaseThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.RoadieId));
result.ReleaseThumbnail = MakeReleaseThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.RoadieId);
HttpContext.BaseUrl, ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.Artist.RoadieId),
ImageHelper.MakeReleaseThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.RoadieId));
result.ReleaseThumbnail = ImageHelper.MakeReleaseThumbnailImage(Configuration, HttpContext, track.ReleaseMedia.Release.RoadieId);
tsw.Stop();
timings.Add("adapt", tsw.ElapsedMilliseconds);
if (track.ArtistId.HasValue)
@ -948,9 +998,9 @@ namespace Roadie.Api.Services
else
{
result.TrackArtist =
ArtistList.FromDataArtist(trackArtist, MakeArtistThumbnailImage(Configuration, HttpContext, trackArtist.RoadieId));
ArtistList.FromDataArtist(trackArtist, ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, trackArtist.RoadieId));
result.TrackArtistToken = result.TrackArtist.Artist;
result.TrackArtistThumbnail = MakeArtistThumbnailImage(Configuration, HttpContext, trackArtist.RoadieId);
result.TrackArtistThumbnail = ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, trackArtist.RoadieId);
}
tsw.Stop();
timings.Add("trackArtist", tsw.ElapsedMilliseconds);
@ -958,6 +1008,32 @@ namespace Roadie.Api.Services
if (includes != null && includes.Any())
{
if (includes.Contains("credits"))
{
tsw.Restart();
result.Credits = (await(from c in DbContext.Credits
join cc in DbContext.CreditCategory on c.CreditCategoryId equals cc.Id
join a in DbContext.Artists on c.ArtistId equals a.Id into agg
from a in agg.DefaultIfEmpty()
where c.TrackId == track.Id
select new { c, cc, a })
.ToListAsync())
.Select(x => new CreditList
{
Id = x.c.RoadieId,
Artist = x.a == null ? null : ArtistList.FromDataArtist(x.a, ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, x.a.RoadieId)),
Category = new DataToken {
Text = x.cc.Name,
Value = x.cc.RoadieId.ToString()
},
CreditName = x.a?.Name ?? x.c.CreditToName,
Description = x.c.Description
}).ToArray();
tsw.Stop();
timings.Add("credits", tsw.ElapsedMilliseconds);
}
if (includes.Contains("stats"))
{
tsw.Restart();
@ -997,7 +1073,7 @@ namespace Roadie.Api.Services
var comment = trackComment.Adapt<Comment>();
comment.DatabaseId = trackComment.Id;
comment.User = UserList.FromDataUser(trackComment.User,
MakeUserThumbnailImage(Configuration, HttpContext, trackComment.User.RoadieId));
ImageHelper.MakeUserThumbnailImage(Configuration, HttpContext, trackComment.User.RoadieId));
comment.DislikedCount = userCommentReactions.Count(x =>
x.CommentId == trackComment.Id && x.ReactionValue == CommentReaction.Dislike);
comment.LikedCount = userCommentReactions.Count(x =>
@ -1014,12 +1090,12 @@ namespace Roadie.Api.Services
sw.Stop();
Logger.LogInformation($"ByIdAction: Track `{ track }`: includes [{includes.ToCSV()}], timings: [{ timings.ToTimings() }]");
return Task.FromResult(new OperationResult<Track>
return new OperationResult<Track>
{
Data = result,
IsSuccess = result != null,
OperationTime = sw.ElapsedMilliseconds
});
};
}
}
}

View file

@ -58,8 +58,10 @@ namespace Roadie.Api.Services
{
if (user.UserId != id && !user.IsAdmin)
{
var r = new OperationResult<User>("Access Denied");
r.IsAccessDeniedResult = true;
var r = new OperationResult<User>("Access Denied")
{
IsAccessDeniedResult = true
};
return r;
}
}
@ -74,7 +76,7 @@ namespace Roadie.Api.Services
sw.Stop();
if (result?.Data != null)
{
result.Data.Avatar = MakeUserThumbnailImage(Configuration, HttpContext, id);
result.Data.Avatar = ImageHelper.MakeUserThumbnailImage(Configuration, HttpContext, id);
if (!isAccountSettingsEdit)
{
result.Data.ApiToken = null;
@ -114,7 +116,7 @@ namespace Roadie.Api.Services
IsEditor = u.UserRoles.Any(x => x.Role.Name == "Editor"),
IsAdmin = u.UserRoles.Any(x => x.Role.Name == "Admin"),
IsPrivate = u.IsPrivate,
Thumbnail = MakeUserThumbnailImage(Configuration, HttpContext, u.RoadieId),
Thumbnail = ImageHelper.MakeUserThumbnailImage(Configuration, HttpContext, u.RoadieId),
CreatedDate = u.CreatedDate,
LastUpdated = u.LastUpdated,
RegisteredDate = u.RegisteredOn,
@ -170,14 +172,34 @@ namespace Roadie.Api.Services
});
}
public async Task<OperationResult<bool>> SetArtistBookmark(Guid artistId, User roadieUser, bool isBookmarked)
public async Task<OperationResult<bool>> DeleteAllBookmarks(User roadieUser)
{
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
if (user == null)
{
return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
}
var artist = GetArtist(artistId);
DbContext.Bookmarks.RemoveRange(DbContext.Bookmarks.Where(x => x.UserId == user.Id));
await DbContext.SaveChangesAsync();
CacheManager.ClearRegion(user.CacheRegion);
return new OperationResult<bool>
{
IsSuccess = true,
Data = true
};
}
public async Task<OperationResult<bool>> SetArtistBookmark(Guid artistId, User roadieUser, bool isBookmarked)
{
var user = await GetUser(roadieUser.UserId);
if (user == null)
{
return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
}
var artist = await GetArtist(artistId);
if (artist == null)
{
return new OperationResult<bool>(true, $"Invalid Artist [{artistId}]");
@ -195,7 +217,7 @@ namespace Roadie.Api.Services
public async Task<OperationResult<bool>> SetArtistDisliked(Guid artistId, User roadieUser, bool isDisliked)
{
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
if (user == null)
{
return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
@ -205,7 +227,7 @@ namespace Roadie.Api.Services
public async Task<OperationResult<bool>> SetArtistFavorite(Guid artistId, User roadieUser, bool isFavorite)
{
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
if (user == null)
{
return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
@ -215,23 +237,22 @@ namespace Roadie.Api.Services
public async Task<OperationResult<short>> SetArtistRating(Guid artistId, User roadieUser, short rating)
{
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
if (user == null)
{
return new OperationResult<short>(true, $"Invalid User [{roadieUser}]");
}
return await base.SetArtistRating(artistId, user, rating);
return await SetArtistRating(artistId, user, rating);
}
public async Task<OperationResult<bool>> SetCollectionBookmark(Guid collectionId, User roadieUser,
bool isBookmarked)
public async Task<OperationResult<bool>> SetCollectionBookmark(Guid collectionId, User roadieUser, bool isBookmarked)
{
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
if (user == null)
{
return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
}
var collection = GetCollection(collectionId);
var collection = await GetCollection(collectionId);
if (collection == null)
{
return new OperationResult<bool>(true, $"Invalid Collection [{collectionId}]");
@ -249,12 +270,12 @@ namespace Roadie.Api.Services
public async Task<OperationResult<bool>> SetLabelBookmark(Guid labelId, User roadieUser, bool isBookmarked)
{
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
if (user == null)
{
return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
}
var label = GetLabel(labelId);
var label = await GetLabel(labelId);
if (label == null)
{
return new OperationResult<bool>(true, $"Invalid Label [{labelId}]");
@ -273,17 +294,17 @@ namespace Roadie.Api.Services
public async Task<OperationResult<bool>> SetPlaylistBookmark(Guid playlistId, User roadieUser,
bool isBookmarked)
{
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
if (user == null)
{
return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
}
var playlist = GetPlaylist(playlistId);
var playlist = await GetPlaylist(playlistId);
if (playlist == null)
{
return new OperationResult<bool>(true, $"Invalid Playlist [{playlistId}]");
}
var result = await SetBookmark(user, BookmarkType.Playlist, playlist.Id, isBookmarked);
await SetBookmark(user, BookmarkType.Playlist, playlist.Id, isBookmarked);
CacheManager.ClearRegion(playlist.CacheRegion);
@ -296,17 +317,17 @@ namespace Roadie.Api.Services
public async Task<OperationResult<bool>> SetReleaseBookmark(Guid releaseid, User roadieUser, bool isBookmarked)
{
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
if (user == null)
{
return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
}
var release = GetRelease(releaseid);
var release = await GetRelease(releaseid);
if (release == null)
{
return new OperationResult<bool>(true, $"Invalid Release [{releaseid}]");
}
var result = await SetBookmark(user, BookmarkType.Release, release.Id, isBookmarked);
await SetBookmark(user, BookmarkType.Release, release.Id, isBookmarked);
CacheManager.ClearRegion(release.CacheRegion);
@ -319,7 +340,7 @@ namespace Roadie.Api.Services
public async Task<OperationResult<bool>> SetReleaseDisliked(Guid releaseId, User roadieUser, bool isDisliked)
{
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
if (user == null)
{
return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
@ -329,7 +350,7 @@ namespace Roadie.Api.Services
public async Task<OperationResult<bool>> SetReleaseFavorite(Guid releaseId, User roadieUser, bool isFavorite)
{
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
if (user == null)
{
return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
@ -339,7 +360,7 @@ namespace Roadie.Api.Services
public async Task<OperationResult<short>> SetReleaseRating(Guid releaseId, User roadieUser, short rating)
{
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
if (user == null)
{
return new OperationResult<short>(true, $"Invalid User [{roadieUser}]");
@ -349,17 +370,17 @@ namespace Roadie.Api.Services
public async Task<OperationResult<bool>> SetTrackBookmark(Guid trackId, User roadieUser, bool isBookmarked)
{
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
if (user == null)
{
return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
}
var track = GetTrack(trackId);
var track = await GetTrack(trackId);
if (track == null)
{
return new OperationResult<bool>(true, $"Invalid Track [{trackId}]");
}
var result = await SetBookmark(user, BookmarkType.Track, track.Id, isBookmarked);
await SetBookmark(user, BookmarkType.Track, track.Id, isBookmarked);
CacheManager.ClearRegion(track.CacheRegion);
@ -372,7 +393,7 @@ namespace Roadie.Api.Services
public async Task<OperationResult<bool>> SetTrackDisliked(Guid trackId, User roadieUser, bool isDisliked)
{
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
if (user == null)
{
return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
@ -382,7 +403,7 @@ namespace Roadie.Api.Services
public async Task<OperationResult<bool>> SetTrackFavorite(Guid trackId, User roadieUser, bool isFavorite)
{
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
if (user == null)
{
return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
@ -394,7 +415,7 @@ namespace Roadie.Api.Services
{
var timings = new Dictionary<string, long>();
var sw = Stopwatch.StartNew();
var user = GetUser(roadieUser.UserId);
var user = await GetUser(roadieUser.UserId);
sw.Stop();
timings.Add("GetUser", sw.ElapsedMilliseconds);
@ -616,7 +637,7 @@ namespace Roadie.Api.Services
var tsw = new Stopwatch();
tsw.Restart();
var user = GetUser(id);
var user = await GetUser(id);
tsw.Stop();
timings.Add("getUser", tsw.ElapsedMilliseconds);
@ -626,7 +647,7 @@ namespace Roadie.Api.Services
}
tsw.Restart();
var model = user.Adapt<User>();
model.MediumThumbnail = MakeThumbnailImage(Configuration, HttpContext, id, "user", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
model.MediumThumbnail = ImageHelper.MakeThumbnailImage(Configuration, HttpContext, id, "user", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
model.IsAdmin = user.UserRoles?.Any(x => x.Role?.NormalizedName == "ADMIN") ?? false;
model.IsEditor = model.IsAdmin ? true : user.UserRoles?.Any(x => x.Role?.NormalizedName == "EDITOR") ?? false;
tsw.Stop();
@ -650,44 +671,44 @@ namespace Roadie.Api.Services
LastPlayedTrack = lastPlayedTrack == null
? null
: models.TrackList.FromDataTrack(
MakeTrackPlayUrl(user, HttpContext.BaseUrl, lastPlayedTrack.Id, lastPlayedTrack.RoadieId),
MakeTrackPlayUrl(user, HttpContext.BaseUrl, lastPlayedTrack.RoadieId),
lastPlayedTrack,
lastPlayedTrack.ReleaseMedia.MediaNumber,
lastPlayedTrack.ReleaseMedia.Release,
lastPlayedTrack.ReleaseMedia.Release.Artist,
lastPlayedTrack.TrackArtist,
HttpContext.BaseUrl,
MakeTrackThumbnailImage(Configuration, HttpContext, lastPlayedTrack.RoadieId),
MakeReleaseThumbnailImage(Configuration, HttpContext, lastPlayedTrack.ReleaseMedia.Release.RoadieId),
MakeArtistThumbnailImage(Configuration, HttpContext, lastPlayedTrack.ReleaseMedia.Release.Artist.RoadieId),
MakeArtistThumbnailImage(Configuration, HttpContext, lastPlayedTrack.TrackArtist == null
ImageHelper.MakeTrackThumbnailImage(Configuration, HttpContext, lastPlayedTrack.RoadieId),
ImageHelper.MakeReleaseThumbnailImage(Configuration, HttpContext, lastPlayedTrack.ReleaseMedia.Release.RoadieId),
ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, lastPlayedTrack.ReleaseMedia.Release.Artist.RoadieId),
ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, lastPlayedTrack.TrackArtist == null
? null
: (Guid?)lastPlayedTrack.TrackArtist.RoadieId)),
MostPlayedArtist = mostPlayedArtist == null
? null
: models.ArtistList.FromDataArtist(mostPlayedArtist,
MakeArtistThumbnailImage(Configuration, HttpContext, mostPlayedArtist.RoadieId)),
ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, mostPlayedArtist.RoadieId)),
MostPlayedRelease = mostPlayedRelease == null
? null
: ReleaseList.FromDataRelease(mostPlayedRelease,
mostPlayedRelease.Artist,
HttpContext.BaseUrl,
MakeArtistThumbnailImage(Configuration, HttpContext, mostPlayedRelease.Artist.RoadieId),
MakeReleaseThumbnailImage(Configuration, HttpContext, mostPlayedRelease.RoadieId)),
ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, mostPlayedRelease.Artist.RoadieId),
ImageHelper.MakeReleaseThumbnailImage(Configuration, HttpContext, mostPlayedRelease.RoadieId)),
MostPlayedTrack = mostPlayedTrack == null
? null
: models.TrackList.FromDataTrack(
MakeTrackPlayUrl(user, HttpContext.BaseUrl, mostPlayedTrack.Id, mostPlayedTrack.RoadieId),
MakeTrackPlayUrl(user, HttpContext.BaseUrl, mostPlayedTrack.RoadieId),
mostPlayedTrack,
mostPlayedTrack.ReleaseMedia.MediaNumber,
mostPlayedTrack.ReleaseMedia.Release,
mostPlayedTrack.ReleaseMedia.Release.Artist,
mostPlayedTrack.TrackArtist,
HttpContext.BaseUrl,
MakeTrackThumbnailImage(Configuration, HttpContext, mostPlayedTrack.RoadieId),
MakeReleaseThumbnailImage(Configuration, HttpContext, mostPlayedTrack.ReleaseMedia.Release.RoadieId),
MakeArtistThumbnailImage(Configuration, HttpContext, mostPlayedTrack.ReleaseMedia.Release.Artist.RoadieId),
MakeArtistThumbnailImage(Configuration, HttpContext, mostPlayedTrack.TrackArtist == null
ImageHelper.MakeTrackThumbnailImage(Configuration, HttpContext, mostPlayedTrack.RoadieId),
ImageHelper.MakeReleaseThumbnailImage(Configuration, HttpContext, mostPlayedTrack.ReleaseMedia.Release.RoadieId),
ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, mostPlayedTrack.ReleaseMedia.Release.Artist.RoadieId),
ImageHelper.MakeArtistThumbnailImage(Configuration, HttpContext, mostPlayedTrack.TrackArtist == null
? null
: (Guid?)mostPlayedTrack.TrackArtist.RoadieId)),
RatedArtists = userArtists.Where(x => x.Rating > 0).Count(),

View file

@ -13,6 +13,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Threading.Tasks;
using models = Roadie.Library.Models.Users;
@ -150,6 +151,6 @@ namespace Roadie.Api.Controllers
result.IsAdmin = User.IsInRole("Admin");
result.IsEditor = User.IsInRole("Editor") || result.IsAdmin;
return result;
}
}
}
}

View file

@ -1,8 +1,7 @@
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
using Roadie.Api.Services;
using Roadie.Library.Caching;
using Roadie.Library.Configuration;
@ -43,12 +42,7 @@ namespace Roadie.Api.Controllers
{
return StatusCode((int)HttpStatusCode.InternalServerError);
}
var model = result.Data.Adapt<Library.Models.Image>();
return File(model.Bytes,
result.ContentType,
$"{model.Caption ?? id.ToString()}.jpg",
result.LastModified,
result.ETag);
return MakeFileResult(result.Data.Bytes, $"{id}.jpg", result.ContentType, result.LastModified, result.ETag);
}
[HttpGet("artist-secondary/{id}/{imageId}/{width:int?}/{height:int?}/{cacheBuster?}")]
@ -65,12 +59,7 @@ namespace Roadie.Api.Controllers
{
return StatusCode((int)HttpStatusCode.InternalServerError);
}
var model = result.Data.Adapt<Library.Models.Image>();
return File(model.Bytes,
result.ContentType,
$"{model.Caption ?? id.ToString()}.jpg",
result.LastModified,
result.ETag);
return MakeFileResult(result.Data.Bytes, $"{id}.jpg", result.ContentType, result.LastModified, result.ETag);
}
[HttpGet("collection/{id}/{width:int?}/{height:int?}/{cacheBuster?}")]
@ -87,34 +76,7 @@ namespace Roadie.Api.Controllers
{
return StatusCode((int)HttpStatusCode.InternalServerError);
}
var model = result.Data.Adapt<Library.Models.Image>();
return File(model.Bytes,
result.ContentType,
$"{model.Caption ?? id.ToString()}.jpg",
result.LastModified,
result.ETag);
}
[HttpGet("{id}/{width:int?}/{height:int?}/{cacheBuster?}")]
[ProducesResponseType(200)]
[ProducesResponseType(404)]
public async Task<IActionResult> Get(Guid id, int? width, int? height)
{
var result = await ImageService.ById(id, width, height);
if (result == null)
{
return NotFound();
}
if (!result.IsSuccess)
{
return StatusCode((int)HttpStatusCode.InternalServerError);
}
var model = result.Data.Adapt<Library.Models.Image>();
return File(model.Bytes,
result.ContentType,
$"{model.Caption ?? id.ToString()}.jpg",
result.LastModified,
result.ETag);
return MakeFileResult(result.Data.Bytes, $"{id}.jpg", result.ContentType, result.LastModified, result.ETag);
}
[HttpGet("label/{id}/{width:int?}/{height:int?}/{cacheBuster?}")]
@ -131,12 +93,7 @@ namespace Roadie.Api.Controllers
{
return StatusCode((int)HttpStatusCode.InternalServerError);
}
var model = result.Data.Adapt<Library.Models.Image>();
return File(model.Bytes,
result.ContentType,
$"{model.Caption ?? id.ToString()}.jpg",
result.LastModified,
result.ETag);
return MakeFileResult(result.Data.Bytes, $"{id}.jpg", result.ContentType, result.LastModified, result.ETag);
}
[HttpGet("genre/{id}/{width:int?}/{height:int?}/{cacheBuster?}")]
@ -153,12 +110,7 @@ namespace Roadie.Api.Controllers
{
return StatusCode((int)HttpStatusCode.InternalServerError);
}
var model = result.Data.Adapt<Library.Models.Image>();
return File(model.Bytes,
result.ContentType,
$"{model.Caption ?? id.ToString()}.jpg",
result.LastModified,
result.ETag);
return MakeFileResult(result.Data.Bytes, $"{id}.jpg", result.ContentType, result.LastModified, result.ETag);
}
[HttpGet("playlist/{id}/{width:int?}/{height:int?}/{cacheBuster?}")]
@ -175,12 +127,7 @@ namespace Roadie.Api.Controllers
{
return StatusCode((int)HttpStatusCode.InternalServerError);
}
var model = result.Data.Adapt<Library.Models.Image>();
return File(model.Bytes,
result.ContentType,
$"{model.Caption ?? id.ToString()}.jpg",
result.LastModified,
result.ETag);
return MakeFileResult(result.Data.Bytes, $"{id}.jpg", result.ContentType, result.LastModified, result.ETag);
}
[HttpGet("release/{id}/{width:int?}/{height:int?}/{cacheBuster?}")]
@ -197,12 +144,7 @@ namespace Roadie.Api.Controllers
{
return StatusCode((int)HttpStatusCode.InternalServerError);
}
var model = result.Data.Adapt<Library.Models.Image>();
return File(model.Bytes,
result.ContentType,
$"{model.Caption ?? id.ToString()}.jpg",
result.LastModified,
result.ETag);
return MakeFileResult(result.Data.Bytes, $"{id}.jpg", result.ContentType, result.LastModified, result.ETag);
}
[HttpGet("release-secondary/{id}/{imageId}/{width:int?}/{height:int?}/{cacheBuster?}")]
@ -219,12 +161,7 @@ namespace Roadie.Api.Controllers
{
return StatusCode((int)HttpStatusCode.InternalServerError);
}
var model = result.Data.Adapt<Library.Models.Image>();
return File(model.Bytes,
result.ContentType,
$"{model.Caption ?? id.ToString()}.jpg",
result.LastModified,
result.ETag);
return MakeFileResult(result.Data.Bytes, $"{id}.jpg", result.ContentType, result.LastModified, result.ETag);
}
[HttpPost("search/artist/{query}/{resultsCount:int?}")]
@ -297,16 +234,13 @@ namespace Roadie.Api.Controllers
{
return StatusCode((int)HttpStatusCode.InternalServerError);
}
var model = result.Data.Adapt<Library.Models.Image>();
return File(model.Bytes,
result.ContentType,
$"{model.Caption ?? id.ToString()}.jpg",
result.LastModified,
result.ETag);
return MakeFileResult(result.Data.Bytes, $"{id}.jpg", result.ContentType, result.LastModified, result.ETag);
}
private IActionResult MakeFileResult(byte[] bytes, string fileName, string contentType, DateTimeOffset? lastModified, EntityTagHeaderValue eTag) => File(bytes, contentType, fileName, lastModified, eTag);
/// <summary>
/// NOTE that user images/avatars are GIF not JPG this is so it looks better in the menus/applications
/// NOTE that user images/avatars are GIF not JPG this is so it looks better in the menus/applications and allows for animated avatars.
/// </summary>
[HttpGet("user/{id}/{width:int?}/{height:int?}/{cacheBuster?}")]
[ProducesResponseType(200)]
@ -322,12 +256,7 @@ namespace Roadie.Api.Controllers
{
return StatusCode((int)HttpStatusCode.InternalServerError);
}
var model = result.Data.Adapt<Library.Models.Image>();
return File(model.Bytes,
result.ContentType,
$"{model.Caption ?? id.ToString()}.gif",
result.LastModified,
result.ETag);
return MakeFileResult(result.Data.Bytes, $"{id}.gif", result.ContentType, result.LastModified, result.ETag);
}
}
}

View file

@ -117,5 +117,16 @@ namespace Roadie.Api.Controllers
if (!result.IsSuccess) return StatusCode((int)HttpStatusCode.InternalServerError);
return Ok(result);
}
[HttpGet("creditCategory")]
[ProducesResponseType(200)]
[ProducesResponseType(404)]
public async Task<IActionResult> CreditCategories(Guid id, string inc = null)
{
var result = await LookupService.Status();
if (!result.IsSuccess) return StatusCode((int)HttpStatusCode.InternalServerError);
return Ok(result);
}
}
}

View file

@ -153,6 +153,16 @@ namespace Roadie.Api.Controllers
return Ok(result);
}
[HttpPost("deleteAllBookmarks")]
[ProducesResponseType(200)]
public async Task<IActionResult> DeleteAllBookmarks()
{
var result = await UserService.DeleteAllBookmarks(await CurrentUserModel());
if (!result.IsSuccess) return StatusCode((int)HttpStatusCode.InternalServerError);
CacheManager.ClearRegion(ControllerCacheRegionUrn);
return Ok(result);
}
[HttpPost("setCollectionBookmark/{collectionId}/{isBookmarked}")]
[ProducesResponseType(200)]
public async Task<IActionResult> SetCollectionBookmark(Guid collectionId, bool isBookmarked)

View file

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

View file

@ -1,5 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<VersionPrefix>1.0.1</VersionPrefix>
<VersionSuffix></VersionSuffix>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<Platforms>AnyCPU;x64</Platforms>

View file

@ -45,6 +45,7 @@ using Serilog;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Text;
#endregion Usings
@ -79,6 +80,12 @@ namespace Roadie.Api
// c.RoutePrefix = string.Empty;
//});
app.Use((context, next) =>
{
context.Response.Headers["Roadie-Api-Version"] = RoadieApiVersion();
return next.Invoke();
});
app.UseSerilogRequestLogging();
app.UseCors("CORSPolicy");
@ -329,6 +336,20 @@ namespace Roadie.Api
adminService.PerformStartUpTasks();
}
private static string _roadieApiVersion = null;
public static string RoadieApiVersion()
{
if (string.IsNullOrEmpty(_roadieApiVersion))
{
_roadieApiVersion = typeof(Startup)
.GetTypeInfo()
.Assembly
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()
.InformationalVersion;
}
return _roadieApiVersion;
}
private class IntegrationKey
{
public string BingImageSearch { get; set; }

View file

@ -0,0 +1,45 @@
CREATE TABLE `creditCategory` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`isLocked` tinyint(1) DEFAULT NULL,
`status` smallint(6) DEFAULT NULL,
`roadieId` varchar(36) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`createdDate` datetime DEFAULT NULL,
`lastUpdated` datetime DEFAULT NULL,
`name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`description` varchar(4000) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`urls` mediumtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`tags` mediumtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`alternateNames` mediumtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `ix_creditCategory_roadieId` (`roadieId`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `credit` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`artistId` int(11) NULL DEFAULT NULL,
`releaseId` int(11) NULL DEFAULT NULL,
`trackId` int(11) NULL DEFAULT NULL,
`creditCategoryId` int(11) NOT NULL,
`isLocked` tinyint(1) DEFAULT NULL,
`status` smallint(6) DEFAULT NULL,
`roadieId` varchar(36) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`createdDate` datetime DEFAULT NULL,
`lastUpdated` datetime DEFAULT NULL,
`creditToName` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`description` varchar(4000) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`urls` mediumtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`tags` mediumtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `ix_credit_roadieId` (`roadieId`),
KEY `idx_creditCreditandRelease` (`releaseId`,`id`),
KEY `idx_creditCreditandTrack` (`trackId`,`id`),
CONSTRAINT `credit_artist_ibfk_1` FOREIGN KEY (`artistId`) REFERENCES `artist` (`id`) ON DELETE CASCADE,
CONSTRAINT `credit_release_ibfk_1` FOREIGN KEY (`releaseId`) REFERENCES `release` (`id`) ON DELETE CASCADE,
CONSTRAINT `credit_track_ibfk_1` FOREIGN KEY (`trackId`) REFERENCES `track` (`id`) ON DELETE CASCADE,
CONSTRAINT `credit_category_ibfk_1` FOREIGN KEY (`creditCategoryId`) REFERENCES `creditCategory` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `creditCategory` VALUES (null,0,1,'d4008de3-2735-4991-968b-b6dfe868990a', UTC_TIMESTAMP(), null, 'Vocals', 'Provided lead or backup vocals',null,null,null);
INSERT INTO `creditCategory` VALUES (null,0,1,'aea463b8-0b90-47d5-8fde-5e68d3c454ed', UTC_TIMESTAMP(), null, 'Instrument', 'Played an instrument',null,null,null);
INSERT INTO `creditCategory` VALUES (null,0,1,'e3178aae-2359-4654-ab29-b45338b5984f', UTC_TIMESTAMP(), null, 'Production', 'Provided some role in production',null,null,null);

View file

@ -62,7 +62,7 @@ CREATE TABLE `artist` (
UNIQUE KEY `ix_artist_name` (`name`),
UNIQUE KEY `ix_artist_sortname` (`sortName`),
KEY `ix_artist_roadieId` (`roadieId`)
) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -81,7 +81,7 @@ CREATE TABLE `artistAssociation` (
KEY `idx_artistAssociation` (`artistId`,`associatedArtistId`),
CONSTRAINT `artistAssociation_ibfk_1` FOREIGN KEY (`artistId`) REFERENCES `artist` (`id`) ON DELETE CASCADE,
CONSTRAINT `artistAssociation_ibfk_2` FOREIGN KEY (`associatedArtistId`) REFERENCES `artist` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -101,7 +101,7 @@ CREATE TABLE `artistGenreTable` (
KEY `ix_artistGenreTable_artistId` (`artistId`),
CONSTRAINT `artistGenreTable_ibfk_1` FOREIGN KEY (`artistId`) REFERENCES `artist` (`id`) ON DELETE CASCADE,
CONSTRAINT `artistGenreTable_ibfk_2` FOREIGN KEY (`genreId`) REFERENCES `genre` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=63 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -120,7 +120,7 @@ CREATE TABLE `artistSimilar` (
KEY `idx_artistSimilar` (`artistId`,`similarArtistId`),
CONSTRAINT `artistSimilar_ibfk_1` FOREIGN KEY (`artistId`) REFERENCES `artist` (`id`) ON DELETE CASCADE,
CONSTRAINT `artistSimilar_ibfk_2` FOREIGN KEY (`similarArtistId`) REFERENCES `artist` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -147,7 +147,7 @@ CREATE TABLE `bookmark` (
KEY `ix_bookmark_roadieId` (`roadieId`),
KEY `ix_bookmark_userId` (`userId`),
CONSTRAINT `bookmark_ibfk_1` FOREIGN KEY (`userId`) REFERENCES `user` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -204,7 +204,7 @@ CREATE TABLE `collection` (
KEY `maintainerId` (`maintainerId`),
KEY `ix_collection_roadieId` (`roadieId`),
CONSTRAINT `collection_ibfk_1` FOREIGN KEY (`maintainerId`) REFERENCES `user` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -223,7 +223,7 @@ CREATE TABLE `collectionMissing` (
`release` varchar(1000) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `ix_collection_collectionId` (`collectionId`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -249,7 +249,7 @@ CREATE TABLE `collectionrelease` (
KEY `ix_collectionrelease_roadieId` (`roadieId`),
CONSTRAINT `collectionrelease_ibfk_1` FOREIGN KEY (`releaseId`) REFERENCES `release` (`id`) ON DELETE CASCADE,
CONSTRAINT `collectionrelease_ibfk_2` FOREIGN KEY (`collectionId`) REFERENCES `collection` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -293,7 +293,7 @@ CREATE TABLE `comment` (
CONSTRAINT `commentrelease_ibfk_1` FOREIGN KEY (`releaseId`) REFERENCES `release` (`id`) ON DELETE CASCADE,
CONSTRAINT `commenttrack_ibfk_1` FOREIGN KEY (`trackId`) REFERENCES `track` (`id`) ON DELETE CASCADE,
CONSTRAINT `commentuser_ibfk_1` FOREIGN KEY (`userId`) REFERENCES `user` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=54 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -319,7 +319,7 @@ CREATE TABLE `commentReaction` (
KEY `commentReactioncomment_ibfk_1` (`commentId`),
CONSTRAINT `commentReactioncomment_ibfk_1` FOREIGN KEY (`commentId`) REFERENCES `comment` (`id`) ON DELETE CASCADE,
CONSTRAINT `commentReactionuser_ibfk_1` FOREIGN KEY (`userId`) REFERENCES `user` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -347,7 +347,7 @@ CREATE TABLE `genre` (
UNIQUE KEY `ix_genre_name` (`name`),
KEY `ix_genre_roadieId` (`roadieId`),
KEY `genre_normalizedName_IDX` (`normalizedName`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -398,7 +398,7 @@ CREATE TABLE `inviteToken` (
KEY `ix_inviteToken_roadieId` (`roadieId`),
KEY `inviteToken_fk_1` (`createdByUserId`),
CONSTRAINT `inviteToken_fk_1` FOREIGN KEY (`createdByUserId`) REFERENCES `user` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -433,7 +433,7 @@ CREATE TABLE `label` (
PRIMARY KEY (`id`),
UNIQUE KEY `ix_label_name` (`name`),
KEY `ix_label_roadieId` (`roadieId`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -466,7 +466,7 @@ CREATE TABLE `playlist` (
KEY `ix_playlist_roadieId` (`roadieId`),
KEY `ix_playlist_userId` (`userId`),
CONSTRAINT `playlist_ibfk_1` FOREIGN KEY (`userId`) REFERENCES `user` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -492,7 +492,7 @@ CREATE TABLE `playlisttrack` (
KEY `ix_playlisttrack_roadieId` (`roadieId`),
CONSTRAINT `playlisttrack_ibfk_1` FOREIGN KEY (`trackId`) REFERENCES `track` (`id`) ON DELETE CASCADE,
CONSTRAINT `playlisttrack_ibfk_2` FOREIGN KEY (`playListId`) REFERENCES `playlist` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=694 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -541,7 +541,7 @@ CREATE TABLE `release` (
KEY `ix_release_roadieId` (`roadieId`),
KEY `ix_release_title` (`title`),
CONSTRAINT `release_ibfk_1` FOREIGN KEY (`artistId`) REFERENCES `artist` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=64 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -560,7 +560,7 @@ CREATE TABLE `releaseGenreTable` (
KEY `idx_releaseGenreTableReleaseAndGenre` (`releaseId`,`genreId`),
CONSTRAINT `releaseGenreTable_ibfk_1` FOREIGN KEY (`releaseId`) REFERENCES `release` (`id`) ON DELETE CASCADE,
CONSTRAINT `releaseGenreTable_ibfk_2` FOREIGN KEY (`genreId`) REFERENCES `genre` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=107 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -588,7 +588,7 @@ CREATE TABLE `releaselabel` (
KEY `ix_releaselabel_roadieId` (`roadieId`),
CONSTRAINT `releaselabel_ibfk_1` FOREIGN KEY (`releaseId`) REFERENCES `release` (`id`) ON DELETE CASCADE,
CONSTRAINT `releaselabel_ibfk_2` FOREIGN KEY (`labelId`) REFERENCES `label` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -613,7 +613,7 @@ CREATE TABLE `releasemedia` (
KEY `ix_releasemedia_roadieId` (`roadieId`),
KEY `releasemedia_releaseId_IDX` (`releaseId`,`releaseMediaNumber`) USING BTREE,
CONSTRAINT `releasemedia_ibfk_1` FOREIGN KEY (`releaseId`) REFERENCES `release` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=62 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -635,7 +635,7 @@ CREATE TABLE `request` (
KEY `ix_request_roadieId` (`roadieId`),
KEY `requestartist_ibfk_1` (`userId`),
CONSTRAINT `requestartist_ibfk_1` FOREIGN KEY (`userId`) REFERENCES `user` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=148 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -661,7 +661,7 @@ CREATE TABLE `scanHistory` (
PRIMARY KEY (`id`),
KEY `ix_scanHistory_roadieId` (`roadieId`),
KEY `rscanHistoryt_ibfk_1` (`userId`)
) ENGINE=InnoDB AUTO_INCREMENT=107 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -729,7 +729,7 @@ CREATE TABLE `track` (
KEY `track_artistId_IDX` (`artistId`) USING BTREE,
KEY `track_releaseMediaId_IDX` (`releaseMediaId`) USING BTREE,
CONSTRAINT `track_ibfk_1` FOREIGN KEY (`releaseMediaId`) REFERENCES `releasemedia` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=623 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -803,7 +803,7 @@ CREATE TABLE `user` (
UNIQUE KEY `email` (`email`),
UNIQUE KEY `ix_user_username` (`username`),
KEY `ix_user_roadieId` (`roadieId`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -894,7 +894,7 @@ CREATE TABLE `userartist` (
KEY `ix_userartist_roadieId` (`roadieId`),
CONSTRAINT `userartist_ibfk_1` FOREIGN KEY (`userId`) REFERENCES `user` (`id`) ON DELETE CASCADE,
CONSTRAINT `userartist_ibfk_2` FOREIGN KEY (`artistId`) REFERENCES `artist` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -922,7 +922,7 @@ CREATE TABLE `userrelease` (
KEY `ix_userrelease_roadieId` (`roadieId`),
CONSTRAINT `userrelease_ibfk_1` FOREIGN KEY (`userId`) REFERENCES `user` (`id`) ON DELETE CASCADE,
CONSTRAINT `userrelease_ibfk_2` FOREIGN KEY (`releaseId`) REFERENCES `release` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -946,7 +946,7 @@ CREATE TABLE `userrole` (
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`),
KEY `ix_userrole_roadieId` (`roadieId`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -965,7 +965,7 @@ CREATE TABLE `usersInRoles` (
KEY `ix_usersInRoles_userId` (`userId`),
CONSTRAINT `usersInRoles_ibfk_1` FOREIGN KEY (`userId`) REFERENCES `user` (`id`) ON DELETE CASCADE,
CONSTRAINT `usersInRoles_ibfk_2` FOREIGN KEY (`userRoleId`) REFERENCES `userrole` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -995,7 +995,7 @@ CREATE TABLE `usertrack` (
KEY `ix_usertrack_roadieId` (`roadieId`),
CONSTRAINT `usertrack_ibfk_1` FOREIGN KEY (`userId`) REFERENCES `user` (`id`) ON DELETE CASCADE,
CONSTRAINT `usertrack_ibfk_2` FOREIGN KEY (`trackId`) REFERENCES `track` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=238 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--