mirror of
https://github.com/sphildreth/roadie
synced 2024-11-25 05:30:24 +00:00
Cleaning up files.
This commit is contained in:
parent
4fa59f442a
commit
1402cfbb72
46 changed files with 3967 additions and 3826 deletions
|
@ -18,7 +18,7 @@
|
|||
"Width": 320
|
||||
},
|
||||
"DontDoMetaDataProvidersSearchArtists": [ "Various Artists", "Sound Tracks" ],
|
||||
"FileExtensionsToDelete": [ ".accurip", ".cue", ".dat", ".db", ".exe", ".htm", ".html", ".ini", ".log", ".jpg", ".jpeg", ".par", ".par2", ".pdf", ".png", ".md5", ".mht", ".mpg", ".m3u", ".nfo", ".nzb", ".pls", ".sfv", ".srr", ".txt", ".url" ],
|
||||
"FileExtensionsToDelete": [ ".accurip", ".bmp", ".cue", ".dat", ".db", ".exe", ".htm", ".html", ".ini", ".log", ".jpg", ".jpeg", ".par", ".par2", ".pdf", ".png", ".md5", ".mht", ".mpg", ".m3u", ".nfo", ".nzb", ".pls", ".sfv", ".srr", ".txt", ".url" ],
|
||||
"RecordNoResultSearches": true,
|
||||
"ArtistNameReplace": {
|
||||
"AC/DC": [ "AC; DC", "AC;DC", "AC/ DC", "AC DC" ],
|
||||
|
@ -101,5 +101,3 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
using Microsoft.AspNetCore.SignalR;
|
||||
using Roadie.Library.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Roadie.Api.Hubs
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using Microsoft.AspNetCore.SignalR;
|
||||
using Roadie.Library.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Roadie.Api.Hubs
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.1.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
using System;
|
||||
|
||||
namespace Roadie.Library
|
||||
{
|
||||
public class AppException
|
||||
[Serializable]
|
||||
public class AppException : Exception
|
||||
{
|
||||
|
||||
public AppException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
28
Roadie.Api.Library/Data/CollectionMissing.cs
Normal file
28
Roadie.Api.Library/Data/CollectionMissing.cs
Normal file
|
@ -0,0 +1,28 @@
|
|||
using Roadie.Library.Enums;
|
||||
using Roadie.Library.Identity;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Roadie.Library.Data
|
||||
{
|
||||
[Table("collectionMissing")]
|
||||
public partial class CollectionMissing
|
||||
{
|
||||
[Column("id")]
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public int Id { get; set; }
|
||||
[Column("collectionId")]
|
||||
public int CollectionId { get; set; }
|
||||
[Column("isArtistFound")]
|
||||
public bool IsArtistFound { get; set; }
|
||||
[Column("position")]
|
||||
public int Position { get; set; }
|
||||
[Column("artist")]
|
||||
[MaxLength(1000)]
|
||||
public string Artist { get; set; }
|
||||
[Column("release")]
|
||||
[MaxLength(1000)]
|
||||
public string Release { get; set; }
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ namespace Roadie.Library.Data
|
|||
DbSet<Bookmark> Bookmarks { get; set; }
|
||||
ChangeTracker ChangeTracker { get; }
|
||||
DbSet<ChatMessage> ChatMessages { get; set; }
|
||||
DbSet<CollectionMissing> CollectionMissings { get; set; }
|
||||
DbSet<CollectionRelease> CollectionReleases { get; set; }
|
||||
DbSet<Collection> Collections { get; set; }
|
||||
DbSet<Comment> Comments { get; set; }
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace Roadie.Library.Data
|
|||
public DbSet<Bookmark> Bookmarks { get; set; }
|
||||
public DbSet<ChatMessage> ChatMessages { get; set; }
|
||||
public DbSet<Comment> Comments { get; set; }
|
||||
public DbSet<CollectionMissing> CollectionMissings { get; set; }
|
||||
public DbSet<CommentReaction> CommentReactions { get; set; }
|
||||
public DbSet<CollectionRelease> CollectionReleases { get; set; }
|
||||
public DbSet<Collection> Collections { get; set; }
|
||||
|
|
|
@ -1,83 +1,18 @@
|
|||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Xml.Serialization;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Roadie.Library
|
||||
{
|
||||
[Serializable]
|
||||
public class AppException : Exception
|
||||
{
|
||||
public AppException() : base()
|
||||
{
|
||||
}
|
||||
|
||||
public AppException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public AppException(string message, params object[] args)
|
||||
: base(String.Format(CultureInfo.CurrentCulture, message, args))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class OperationResult<T>
|
||||
{
|
||||
private List<Exception> _errors;
|
||||
private List<string> _messages;
|
||||
|
||||
[JsonIgnore]
|
||||
[XmlIgnore]
|
||||
public Dictionary<string, object> AdditionalData { get; set; } = new Dictionary<string, object>();
|
||||
|
||||
public Dictionary<string, object> AdditionalClientData { get; set; } = new Dictionary<string, object>();
|
||||
|
||||
/// <summary>
|
||||
/// Client friendly exceptions
|
||||
/// </summary>
|
||||
[JsonProperty("errors")]
|
||||
public IEnumerable<AppException> AppExceptions
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.Errors == null || !this.Errors.Any())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return this.Errors.Select(x => new AppException(x.Message));
|
||||
}
|
||||
}
|
||||
|
||||
public T Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Server side visible exceptions
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public IEnumerable<Exception> Errors { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsNotFoundResult { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsAccessDeniedResult { get; set; }
|
||||
|
||||
public bool IsSuccess { get; set; }
|
||||
|
||||
public IEnumerable<string> Messages
|
||||
{
|
||||
get
|
||||
{
|
||||
return this._messages;
|
||||
}
|
||||
}
|
||||
|
||||
public long OperationTime { get; set; }
|
||||
|
||||
public OperationResult()
|
||||
{
|
||||
}
|
||||
|
@ -86,53 +21,89 @@ namespace Roadie.Library
|
|||
{
|
||||
if (messages != null && messages.Any())
|
||||
{
|
||||
this.AdditionalData = new Dictionary<string, object>();
|
||||
messages.ToList().ForEach(x => this.AddMessage(x));
|
||||
AdditionalData = new Dictionary<string, object>();
|
||||
messages.ToList().ForEach(AddMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public OperationResult(bool isNotFoundResult, IEnumerable<string> messages = null)
|
||||
{
|
||||
this.IsNotFoundResult = isNotFoundResult;
|
||||
IsNotFoundResult = isNotFoundResult;
|
||||
if (messages != null && messages.Any())
|
||||
{
|
||||
this.AdditionalData = new Dictionary<string, object>();
|
||||
messages.ToList().ForEach(x => this.AddMessage(x));
|
||||
AdditionalData = new Dictionary<string, object>();
|
||||
messages.ToList().ForEach(AddMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public OperationResult(bool isNotFoundResult, string message)
|
||||
{
|
||||
this.IsNotFoundResult = isNotFoundResult;
|
||||
this.AddMessage(message);
|
||||
IsNotFoundResult = isNotFoundResult;
|
||||
AddMessage(message);
|
||||
}
|
||||
|
||||
public OperationResult(string message = null)
|
||||
{
|
||||
this.AdditionalData = new Dictionary<string, object>();
|
||||
this.AddMessage(message);
|
||||
AdditionalData = new Dictionary<string, object>();
|
||||
AddMessage(message);
|
||||
}
|
||||
|
||||
public OperationResult(Exception error = null)
|
||||
{
|
||||
this.AddError(error);
|
||||
AddError(error);
|
||||
}
|
||||
|
||||
public OperationResult(string message = null, Exception error = null)
|
||||
{
|
||||
this.AddMessage(message);
|
||||
this.AddError(error);
|
||||
AddMessage(message);
|
||||
AddError(error);
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
[XmlIgnore]
|
||||
public Dictionary<string, object> AdditionalData { get; set; } = new Dictionary<string, object>();
|
||||
|
||||
public Dictionary<string, object> AdditionalClientData { get; set; } = new Dictionary<string, object>();
|
||||
|
||||
/// <summary>
|
||||
/// Client friendly exceptions
|
||||
/// </summary>
|
||||
[JsonProperty("errors")]
|
||||
public IEnumerable<AppException> AppExceptions
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Errors == null || !Errors.Any()) return null;
|
||||
|
||||
return Errors.Select(x => new AppException(x.Message));
|
||||
}
|
||||
}
|
||||
|
||||
public T Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Server side visible exceptions
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public IEnumerable<Exception> Errors { get; set; }
|
||||
|
||||
[JsonIgnore] public bool IsNotFoundResult { get; set; }
|
||||
|
||||
[JsonIgnore] public bool IsAccessDeniedResult { get; set; }
|
||||
|
||||
public bool IsSuccess { get; set; }
|
||||
|
||||
public IEnumerable<string> Messages => _messages;
|
||||
|
||||
public long OperationTime { get; set; }
|
||||
|
||||
public void AddError(Exception exception)
|
||||
{
|
||||
if (exception != null)
|
||||
{
|
||||
if (this._errors == null)
|
||||
{
|
||||
this._errors = new List<Exception>();
|
||||
}
|
||||
this._errors.Add(exception);
|
||||
if (_errors == null) _errors = new List<Exception>();
|
||||
|
||||
_errors.Add(exception);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,11 +111,9 @@ namespace Roadie.Library
|
|||
{
|
||||
if (!string.IsNullOrEmpty(message))
|
||||
{
|
||||
if (this._messages == null)
|
||||
{
|
||||
this._messages = new List<string>();
|
||||
}
|
||||
this._messages.Add(message);
|
||||
if (_messages == null) _messages = new List<string>();
|
||||
|
||||
_messages.Add(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
|
@ -11,9 +11,9 @@
|
|||
<PackageReference Include="AutoCompare.Core" Version="1.0.0" />
|
||||
<PackageReference Include="CsvHelper" Version="12.1.2" />
|
||||
<PackageReference Include="EFCore.BulkExtensions" Version="2.4.7" />
|
||||
<PackageReference Include="FluentFTP" Version="25.0.3" />
|
||||
<PackageReference Include="FluentFTP" Version="25.0.4" />
|
||||
<PackageReference Include="Hashids.net" Version="1.2.2" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.7" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.8" />
|
||||
<PackageReference Include="IdSharp.Common" Version="1.0.1" />
|
||||
<PackageReference Include="IdSharp.Tagging" Version="1.0.0-rc3" />
|
||||
<PackageReference Include="Inflatable.Lastfm" Version="1.1.0.339" />
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -4,8 +4,10 @@ using Roadie.Library.Caching;
|
|||
using Roadie.Library.Configuration;
|
||||
using Roadie.Library.Encoding;
|
||||
using Roadie.Library.Enums;
|
||||
using Roadie.Library.Models;
|
||||
using Roadie.Library.Models.Collections;
|
||||
using Roadie.Library.Models.Pagination;
|
||||
using Roadie.Library.Models.Playlists;
|
||||
using Roadie.Library.Models.Releases;
|
||||
using Roadie.Library.Models.Users;
|
||||
using Roadie.Library.Utility;
|
||||
using System;
|
||||
|
@ -15,7 +17,6 @@ using System.Linq;
|
|||
using System.Linq.Dynamic.Core;
|
||||
using System.Threading.Tasks;
|
||||
using data = Roadie.Library.Data;
|
||||
|
||||
using models = Roadie.Library.Models;
|
||||
|
||||
namespace Roadie.Api.Services
|
||||
|
@ -23,169 +24,163 @@ namespace Roadie.Api.Services
|
|||
public class BookmarkService : ServiceBase, IBookmarkService
|
||||
{
|
||||
public BookmarkService(IRoadieSettings configuration,
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext context,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<BookmarkService> logger)
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext context,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<BookmarkService> logger)
|
||||
: base(configuration, httpEncoder, context, cacheManager, logger, httpContext)
|
||||
{
|
||||
}
|
||||
|
||||
public Task<Library.Models.Pagination.PagedResult<BookmarkList>> List(User roadieUser, PagedRequest request, bool? doRandomize = false, BookmarkType? filterType = null)
|
||||
public Task<Library.Models.Pagination.PagedResult<models.BookmarkList>> List(User roadieUser,
|
||||
PagedRequest request, bool? doRandomize = false, BookmarkType? filterType = null)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
var result = (from b in this.DbContext.Bookmarks
|
||||
join u in this.DbContext.Users on b.UserId equals u.Id
|
||||
where b.UserId == roadieUser.Id
|
||||
where (filterType == null || b.BookmarkType == filterType)
|
||||
select new BookmarkList
|
||||
{
|
||||
Comment = b.Comment,
|
||||
Position = b.Position,
|
||||
User = new DataToken
|
||||
{
|
||||
Text = u.UserName,
|
||||
Value = u.RoadieId.ToString()
|
||||
},
|
||||
DatabaseId = b.Id,
|
||||
Id = b.RoadieId,
|
||||
CreatedDate = b.CreatedDate,
|
||||
LastUpdated = b.LastUpdated,
|
||||
Type = b.BookmarkType,
|
||||
BookmarkTargetId = b.BookmarkTargetId
|
||||
});
|
||||
var result = from b in DbContext.Bookmarks
|
||||
join u in DbContext.Users on b.UserId equals u.Id
|
||||
where b.UserId == roadieUser.Id
|
||||
where filterType == null || b.BookmarkType == filterType
|
||||
select new models.BookmarkList
|
||||
{
|
||||
Comment = b.Comment,
|
||||
Position = b.Position,
|
||||
User = new models.DataToken
|
||||
{
|
||||
Text = u.UserName,
|
||||
Value = u.RoadieId.ToString()
|
||||
},
|
||||
DatabaseId = b.Id,
|
||||
Id = b.RoadieId,
|
||||
CreatedDate = b.CreatedDate,
|
||||
LastUpdated = b.LastUpdated,
|
||||
Type = b.BookmarkType,
|
||||
BookmarkTargetId = b.BookmarkTargetId
|
||||
};
|
||||
|
||||
var sortBy = string.IsNullOrEmpty(request.Sort) ? request.OrderValue(new Dictionary<string, string> { { "CreatedDate", "DESC" } }) : request.OrderValue(null);
|
||||
var sortBy = string.IsNullOrEmpty(request.Sort)
|
||||
? request.OrderValue(new Dictionary<string, string> { { "CreatedDate", "DESC" } })
|
||||
: request.OrderValue();
|
||||
var rowCount = result.Count();
|
||||
BookmarkList[] rows = result.OrderBy(sortBy).Skip(request.SkipValue).Take(request.LimitValue).ToArray();
|
||||
var rows = result.OrderBy(sortBy).Skip(request.SkipValue).Take(request.LimitValue).ToArray();
|
||||
|
||||
var user = this.GetUser(roadieUser.UserId);
|
||||
var user = GetUser(roadieUser.UserId);
|
||||
|
||||
foreach (var row in rows)
|
||||
{
|
||||
switch (row.Type)
|
||||
{
|
||||
case BookmarkType.Artist:
|
||||
var artist = this.DbContext.Artists.FirstOrDefault(x => x.Id == row.BookmarkTargetId);
|
||||
if (artist == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
row.Bookmark = new DataToken
|
||||
var artist = DbContext.Artists.FirstOrDefault(x => x.Id == row.BookmarkTargetId);
|
||||
if (artist == null) continue;
|
||||
row.Bookmark = new models.DataToken
|
||||
{
|
||||
Text = artist.Name,
|
||||
Value = artist.RoadieId.ToString()
|
||||
};
|
||||
row.Artist = models.ArtistList.FromDataArtist(artist, this.MakeArtistThumbnailImage(artist.RoadieId));
|
||||
row.Thumbnail = this.MakeArtistThumbnailImage(artist.RoadieId);
|
||||
row.Artist =
|
||||
models.ArtistList.FromDataArtist(artist, MakeArtistThumbnailImage(artist.RoadieId));
|
||||
row.Thumbnail = MakeArtistThumbnailImage(artist.RoadieId);
|
||||
row.SortName = artist.SortName ?? artist.Name;
|
||||
break;
|
||||
|
||||
case BookmarkType.Release:
|
||||
var release = this.DbContext.Releases.Include(x => x.Artist).FirstOrDefault(x => x.Id == row.BookmarkTargetId);
|
||||
if (release == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
row.Bookmark = new DataToken
|
||||
var release = DbContext.Releases.Include(x => x.Artist)
|
||||
.FirstOrDefault(x => x.Id == row.BookmarkTargetId);
|
||||
if (release == null) continue;
|
||||
row.Bookmark = new models.DataToken
|
||||
{
|
||||
Text = release.Title,
|
||||
Value = release.RoadieId.ToString()
|
||||
};
|
||||
row.Release = models.Releases.ReleaseList.FromDataRelease(release, release.Artist, this.HttpContext.BaseUrl, this.MakeArtistThumbnailImage(release.Artist.RoadieId), this.MakeReleaseThumbnailImage(release.RoadieId));
|
||||
row.Thumbnail = this.MakeReleaseThumbnailImage(release.RoadieId);
|
||||
row.Release = ReleaseList.FromDataRelease(release, release.Artist, HttpContext.BaseUrl,
|
||||
MakeArtistThumbnailImage(release.Artist.RoadieId),
|
||||
MakeReleaseThumbnailImage(release.RoadieId));
|
||||
row.Thumbnail = MakeReleaseThumbnailImage(release.RoadieId);
|
||||
row.SortName = release.Title;
|
||||
break;
|
||||
|
||||
case BookmarkType.Track:
|
||||
var track = this.DbContext.Tracks
|
||||
.Include(x => x.ReleaseMedia)
|
||||
.Include(x => x.ReleaseMedia.Release)
|
||||
.Include(x => x.ReleaseMedia.Release.Artist)
|
||||
.Include(x => x.TrackArtist)
|
||||
.FirstOrDefault(x => x.Id == row.BookmarkTargetId);
|
||||
if (track == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
row.Bookmark = new DataToken
|
||||
var track = DbContext.Tracks
|
||||
.Include(x => x.ReleaseMedia)
|
||||
.Include(x => x.ReleaseMedia.Release)
|
||||
.Include(x => x.ReleaseMedia.Release.Artist)
|
||||
.Include(x => x.TrackArtist)
|
||||
.FirstOrDefault(x => x.Id == row.BookmarkTargetId);
|
||||
if (track == null) continue;
|
||||
row.Bookmark = new models.DataToken
|
||||
{
|
||||
Text = track.Title,
|
||||
Value = track.RoadieId.ToString()
|
||||
};
|
||||
row.Track = TrackList.FromDataTrack(this.MakeTrackPlayUrl(user, track.Id, track.RoadieId),
|
||||
track,
|
||||
track.ReleaseMedia.MediaNumber,
|
||||
track.ReleaseMedia.Release,
|
||||
track.ReleaseMedia.Release.Artist,
|
||||
track.TrackArtist,
|
||||
this.HttpContext.BaseUrl,
|
||||
this.MakeTrackThumbnailImage(track.RoadieId),
|
||||
this.MakeReleaseThumbnailImage(track.ReleaseMedia.Release.RoadieId),
|
||||
this.MakeArtistThumbnailImage(track.ReleaseMedia.Release.Artist.RoadieId),
|
||||
this.MakeArtistThumbnailImage(track.TrackArtist == null ? null : (Guid?)track.TrackArtist.RoadieId));
|
||||
row.Track.TrackPlayUrl = this.MakeTrackPlayUrl(user, track.Id, track.RoadieId);
|
||||
row.Thumbnail = this.MakeTrackThumbnailImage(track.RoadieId);
|
||||
row.Track = models.TrackList.FromDataTrack(MakeTrackPlayUrl(user, track.Id, track.RoadieId),
|
||||
track,
|
||||
track.ReleaseMedia.MediaNumber,
|
||||
track.ReleaseMedia.Release,
|
||||
track.ReleaseMedia.Release.Artist,
|
||||
track.TrackArtist,
|
||||
HttpContext.BaseUrl,
|
||||
MakeTrackThumbnailImage(track.RoadieId),
|
||||
MakeReleaseThumbnailImage(track.ReleaseMedia.Release.RoadieId),
|
||||
MakeArtistThumbnailImage(track.ReleaseMedia.Release.Artist.RoadieId),
|
||||
MakeArtistThumbnailImage(track.TrackArtist == null
|
||||
? null
|
||||
: (Guid?)track.TrackArtist.RoadieId));
|
||||
row.Track.TrackPlayUrl = MakeTrackPlayUrl(user, track.Id, track.RoadieId);
|
||||
row.Thumbnail = MakeTrackThumbnailImage(track.RoadieId);
|
||||
row.SortName = track.Title;
|
||||
break;
|
||||
|
||||
case BookmarkType.Playlist:
|
||||
var playlist = this.DbContext.Playlists
|
||||
.Include(x => x.User)
|
||||
.FirstOrDefault(x => x.Id == row.BookmarkTargetId);
|
||||
if (playlist == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
row.Bookmark = new DataToken
|
||||
var playlist = DbContext.Playlists
|
||||
.Include(x => x.User)
|
||||
.FirstOrDefault(x => x.Id == row.BookmarkTargetId);
|
||||
if (playlist == null) continue;
|
||||
row.Bookmark = new models.DataToken
|
||||
{
|
||||
Text = playlist.Name,
|
||||
Value = playlist.RoadieId.ToString()
|
||||
};
|
||||
row.Playlist = models.Playlists.PlaylistList.FromDataPlaylist(playlist, playlist.User, this.MakePlaylistThumbnailImage(playlist.RoadieId), this.MakeUserThumbnailImage(playlist.User.RoadieId));
|
||||
row.Thumbnail = this.MakePlaylistThumbnailImage(playlist.RoadieId);
|
||||
row.Playlist = PlaylistList.FromDataPlaylist(playlist, playlist.User,
|
||||
MakePlaylistThumbnailImage(playlist.RoadieId),
|
||||
MakeUserThumbnailImage(playlist.User.RoadieId));
|
||||
row.Thumbnail = MakePlaylistThumbnailImage(playlist.RoadieId);
|
||||
row.SortName = playlist.Name;
|
||||
break;
|
||||
|
||||
case BookmarkType.Collection:
|
||||
var collection = this.DbContext.Collections.FirstOrDefault(x => x.Id == row.BookmarkTargetId);
|
||||
if (collection == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
row.Bookmark = new DataToken
|
||||
var collection = DbContext.Collections.FirstOrDefault(x => x.Id == row.BookmarkTargetId);
|
||||
if (collection == null) continue;
|
||||
row.Bookmark = new models.DataToken
|
||||
{
|
||||
Text = collection.Name,
|
||||
Value = collection.RoadieId.ToString()
|
||||
};
|
||||
row.Collection = models.Collections.CollectionList.FromDataCollection(collection, (from crc in this.DbContext.CollectionReleases
|
||||
where crc.CollectionId == collection.Id
|
||||
select crc.Id).Count(), this.MakeCollectionThumbnailImage(collection.RoadieId));
|
||||
row.Thumbnail = this.MakeCollectionThumbnailImage(collection.RoadieId);
|
||||
row.Collection = CollectionList.FromDataCollection(collection,
|
||||
(from crc in DbContext.CollectionReleases
|
||||
where crc.CollectionId == collection.Id
|
||||
select crc.Id).Count(), MakeCollectionThumbnailImage(collection.RoadieId));
|
||||
row.Thumbnail = MakeCollectionThumbnailImage(collection.RoadieId);
|
||||
row.SortName = collection.SortName ?? collection.Name;
|
||||
break;
|
||||
|
||||
case BookmarkType.Label:
|
||||
var label = this.DbContext.Labels.FirstOrDefault(x => x.Id == row.BookmarkTargetId);
|
||||
if (label == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
row.Bookmark = new DataToken
|
||||
var label = DbContext.Labels.FirstOrDefault(x => x.Id == row.BookmarkTargetId);
|
||||
if (label == null) continue;
|
||||
row.Bookmark = new models.DataToken
|
||||
{
|
||||
Text = label.Name,
|
||||
Value = label.RoadieId.ToString()
|
||||
};
|
||||
row.Label = models.LabelList.FromDataLabel(label, this.MakeLabelThumbnailImage(label.RoadieId));
|
||||
row.Thumbnail = this.MakeLabelThumbnailImage(label.RoadieId);
|
||||
row.Label = models.LabelList.FromDataLabel(label, MakeLabelThumbnailImage(label.RoadieId));
|
||||
row.Thumbnail = MakeLabelThumbnailImage(label.RoadieId);
|
||||
row.SortName = label.SortName ?? label.Name;
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
;
|
||||
sw.Stop();
|
||||
return Task.FromResult(new Library.Models.Pagination.PagedResult<BookmarkList>
|
||||
return Task.FromResult(new Library.Models.Pagination.PagedResult<models.BookmarkList>
|
||||
{
|
||||
TotalCount = rowCount,
|
||||
CurrentPage = request.PageValue,
|
||||
|
|
|
@ -8,8 +8,10 @@ using Roadie.Library.Encoding;
|
|||
using Roadie.Library.Enums;
|
||||
using Roadie.Library.Extensions;
|
||||
using Roadie.Library.Imaging;
|
||||
using Roadie.Library.Models;
|
||||
using Roadie.Library.Models.Collections;
|
||||
using Roadie.Library.Models.Pagination;
|
||||
using Roadie.Library.Models.Releases;
|
||||
using Roadie.Library.Models.Statistics;
|
||||
using Roadie.Library.Models.Users;
|
||||
using Roadie.Library.Utility;
|
||||
|
@ -20,28 +22,27 @@ using System.Linq;
|
|||
using System.Linq.Dynamic.Core;
|
||||
using System.Threading.Tasks;
|
||||
using data = Roadie.Library.Data;
|
||||
using Roadie.Library.Models;
|
||||
|
||||
namespace Roadie.Api.Services
|
||||
{
|
||||
public class CollectionService : ServiceBase, ICollectionService
|
||||
{
|
||||
private IBookmarkService BookmarkService { get; } = null;
|
||||
private IBookmarkService BookmarkService { get; }
|
||||
|
||||
public CollectionService(IRoadieSettings configuration,
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext dbContext,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<CollectionService> logger,
|
||||
IBookmarkService bookmarkService)
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext dbContext,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<CollectionService> logger,
|
||||
IBookmarkService bookmarkService)
|
||||
: base(configuration, httpEncoder, dbContext, cacheManager, logger, httpContext)
|
||||
{
|
||||
this.BookmarkService = bookmarkService;
|
||||
BookmarkService = bookmarkService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get blank Collection to add
|
||||
/// Get blank Collection to add
|
||||
/// </summary>
|
||||
/// <param name="roadieUser"></param>
|
||||
/// <returns></returns>
|
||||
|
@ -57,16 +58,16 @@ namespace Roadie.Api.Services
|
|||
};
|
||||
var result = collection.Adapt<Collection>();
|
||||
result.Id = id;
|
||||
result.Thumbnail = this.MakeNewImage("collection");
|
||||
result.MediumThumbnail = this.MakeNewImage("collection");
|
||||
result.Maintainer = new Library.Models.DataToken
|
||||
result.Thumbnail = MakeNewImage("collection");
|
||||
result.MediumThumbnail = MakeNewImage("collection");
|
||||
result.Maintainer = new DataToken
|
||||
{
|
||||
Value = roadieUser.UserId.ToString(),
|
||||
Text = roadieUser.UserName
|
||||
};
|
||||
sw.Stop();
|
||||
|
||||
return new OperationResult<Collection>()
|
||||
return new OperationResult<Collection>
|
||||
{
|
||||
Data = result,
|
||||
IsSuccess = true,
|
||||
|
@ -74,39 +75,42 @@ namespace Roadie.Api.Services
|
|||
};
|
||||
}
|
||||
|
||||
public async Task<OperationResult<Collection>> ById(User roadieUser, Guid id, IEnumerable<string> includes = null)
|
||||
public async Task<OperationResult<Collection>> ById(User roadieUser, Guid id,
|
||||
IEnumerable<string> includes = null)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
sw.Start();
|
||||
|
||||
var cacheKey = string.Format("urn:collection_by_id_operation:{0}:{1}", id, includes == null ? "0" : string.Join("|", includes));
|
||||
var result = await this.CacheManager.GetAsync<OperationResult<Collection>>(cacheKey, async () =>
|
||||
{
|
||||
return await this.CollectionByIdAction(id, includes);
|
||||
}, data.Artist.CacheRegionUrn(id));
|
||||
var cacheKey = string.Format("urn:collection_by_id_operation:{0}:{1}", id,
|
||||
includes == null ? "0" : string.Join("|", includes));
|
||||
var result = await CacheManager.GetAsync(cacheKey,
|
||||
async () => { return await CollectionByIdAction(id, includes); }, data.Artist.CacheRegionUrn(id));
|
||||
sw.Stop();
|
||||
if (result?.Data != null && roadieUser != null)
|
||||
{
|
||||
var userBookmarkResult = await this.BookmarkService.List(roadieUser, new PagedRequest(), false, BookmarkType.Collection);
|
||||
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.Text == result.Data.Id.ToString()) !=
|
||||
null;
|
||||
if (result.Data.Comments.Any())
|
||||
{
|
||||
var commentIds = result.Data.Comments.Select(x => x.DatabaseId).ToArray();
|
||||
var userCommentReactions = (from cr in this.DbContext.CommentReactions
|
||||
var userCommentReactions = (from cr in DbContext.CommentReactions
|
||||
where commentIds.Contains(cr.CommentId)
|
||||
where cr.UserId == roadieUser.Id
|
||||
select cr).ToArray();
|
||||
foreach (var comment in result.Data.Comments)
|
||||
{
|
||||
var userCommentReaction = userCommentReactions.FirstOrDefault(x => x.CommentId == comment.DatabaseId);
|
||||
var userCommentReaction =
|
||||
userCommentReactions.FirstOrDefault(x => x.CommentId == comment.DatabaseId);
|
||||
comment.IsDisliked = userCommentReaction?.ReactionValue == CommentReaction.Dislike;
|
||||
comment.IsLiked = userCommentReaction?.ReactionValue == CommentReaction.Like;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new OperationResult<Collection>(result.Messages)
|
||||
{
|
||||
Data = result?.Data,
|
||||
|
@ -122,28 +126,27 @@ namespace Roadie.Api.Services
|
|||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
var errors = new List<Exception>();
|
||||
var collection = this.DbContext.Collections.FirstOrDefault(x => x.RoadieId == id);
|
||||
if (collection == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Collection Not Found [{ id }]");
|
||||
}
|
||||
var collection = DbContext.Collections.FirstOrDefault(x => x.RoadieId == id);
|
||||
if (collection == null) return new OperationResult<bool>(true, $"Collection Not Found [{id}]");
|
||||
if (!user.IsEditor)
|
||||
{
|
||||
this.Logger.LogWarning($"DeleteCollection: Access Denied: `{ collection }`, By User `{user }`");
|
||||
Logger.LogWarning($"DeleteCollection: Access Denied: `{collection}`, By User `{user}`");
|
||||
return new OperationResult<bool>("Access Denied");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
this.DbContext.Collections.Remove(collection);
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
DbContext.Collections.Remove(collection);
|
||||
await DbContext.SaveChangesAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex);
|
||||
Logger.LogError(ex);
|
||||
errors.Add(ex);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
this.Logger.LogInformation($"DeleteCollection `{ collection }`, By User `{user }`");
|
||||
Logger.LogInformation($"DeleteCollection `{collection}`, By User `{user}`");
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
IsSuccess = !errors.Any(),
|
||||
|
@ -153,7 +156,8 @@ namespace Roadie.Api.Services
|
|||
};
|
||||
}
|
||||
|
||||
public Task<Library.Models.Pagination.PagedResult<CollectionList>> List(User roadieUser, PagedRequest request, bool? doRandomize = false, Guid? releaseId = null, Guid? artistId = null)
|
||||
public Task<Library.Models.Pagination.PagedResult<CollectionList>> List(User roadieUser, PagedRequest request,
|
||||
bool? doRandomize = false, Guid? releaseId = null, Guid? artistId = null)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
@ -167,7 +171,7 @@ namespace Roadie.Api.Services
|
|||
join `artist` a on r.artistId = a.id
|
||||
where a.roadieId = {0}";
|
||||
|
||||
collections = this.DbContext.Collections.FromSql(sql, artistId);
|
||||
collections = DbContext.Collections.FromSql(sql, artistId);
|
||||
}
|
||||
else if (releaseId.HasValue)
|
||||
{
|
||||
|
@ -177,25 +181,27 @@ namespace Roadie.Api.Services
|
|||
join `release` r on r.id = cr.releaseId
|
||||
where r.roadieId = {0}";
|
||||
|
||||
collections = this.DbContext.Collections.FromSql(sql, releaseId);
|
||||
collections = DbContext.Collections.FromSql(sql, releaseId);
|
||||
}
|
||||
else
|
||||
{
|
||||
collections = this.DbContext.Collections;
|
||||
collections = DbContext.Collections;
|
||||
}
|
||||
var result = (from c in collections
|
||||
where (request.FilterValue.Length == 0 || (request.FilterValue.Length > 0 && c.Name.Contains(request.Filter)))
|
||||
where (request.FilterToStatusValue == Statuses.Ok || (c.Status == request.FilterToStatusValue))
|
||||
select CollectionList.FromDataCollection(c, (from crc in this.DbContext.CollectionReleases
|
||||
where crc.CollectionId == c.Id
|
||||
select crc.Id).Count(), this.MakeCollectionThumbnailImage(c.RoadieId)));
|
||||
var sortBy = string.IsNullOrEmpty(request.Sort) ? request.OrderValue(new Dictionary<string, string> { { "Collection.Text", "ASC" } }) : request.OrderValue(null);
|
||||
|
||||
var result = from c in collections
|
||||
where request.FilterValue.Length == 0 ||
|
||||
request.FilterValue.Length > 0 && c.Name.Contains(request.Filter)
|
||||
where request.FilterToStatusValue == Statuses.Ok || c.Status == request.FilterToStatusValue
|
||||
select CollectionList.FromDataCollection(c, (from crc in DbContext.CollectionReleases
|
||||
where crc.CollectionId == c.Id
|
||||
select crc.Id).Count(), MakeCollectionThumbnailImage(c.RoadieId));
|
||||
var sortBy = string.IsNullOrEmpty(request.Sort)
|
||||
? request.OrderValue(new Dictionary<string, string> { { "Collection.Text", "ASC" } })
|
||||
: request.OrderValue();
|
||||
var rowCount = result.Count();
|
||||
var rows = result.OrderBy(sortBy).Skip(request.SkipValue).Take(request.LimitValue).ToArray();
|
||||
if (request.FilterToStatusValue == Statuses.Incomplete)
|
||||
{
|
||||
rows = rows.OrderByDescending(x => x.PercentComplete).ThenBy(x => x.SortName).ToArray();
|
||||
}
|
||||
sw.Stop();
|
||||
return Task.FromResult(new Library.Models.Pagination.PagedResult<CollectionList>
|
||||
{
|
||||
|
@ -208,7 +214,7 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates (or Adds) Collection
|
||||
/// Updates (or Adds) Collection
|
||||
/// </summary>
|
||||
public async Task<OperationResult<bool>> UpdateCollection(User user, Collection model)
|
||||
{
|
||||
|
@ -219,16 +225,15 @@ namespace Roadie.Api.Services
|
|||
sw.Start();
|
||||
var errors = new List<Exception>();
|
||||
|
||||
data.Collection collection = new data.Collection();
|
||||
var collection = new data.Collection();
|
||||
|
||||
if (!isNew)
|
||||
{
|
||||
collection = this.DbContext.Collections.FirstOrDefault(x => x.RoadieId == model.Id);
|
||||
collection = DbContext.Collections.FirstOrDefault(x => x.RoadieId == model.Id);
|
||||
if (collection == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, string.Format("Collection Not Found [{0}]", model.Id));
|
||||
}
|
||||
}
|
||||
|
||||
collection.IsLocked = model.IsLocked;
|
||||
collection.Name = model.Name;
|
||||
collection.SortName = model.SortName;
|
||||
|
@ -251,26 +256,23 @@ namespace Roadie.Api.Services
|
|||
collection.Thumbnail = ImageHelper.ConvertToJpegFormat(collectionImage);
|
||||
|
||||
// Resize to store in database as thumbnail
|
||||
collection.Thumbnail = ImageHelper.ResizeImage(collection.Thumbnail, this.Configuration.MediumImageSize.Width, this.Configuration.MediumImageSize.Height);
|
||||
collection.Thumbnail = ImageHelper.ResizeImage(collection.Thumbnail,
|
||||
Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
|
||||
}
|
||||
|
||||
if (model.Maintainer?.Value != null)
|
||||
{
|
||||
var maintainer = this.DbContext.Users.FirstOrDefault(x => x.RoadieId == SafeParser.ToGuid(model.Maintainer.Value));
|
||||
if (maintainer != null)
|
||||
{
|
||||
collection.MaintainerId = maintainer.Id;
|
||||
}
|
||||
var maintainer =
|
||||
DbContext.Users.FirstOrDefault(x => x.RoadieId == SafeParser.ToGuid(model.Maintainer.Value));
|
||||
if (maintainer != null) collection.MaintainerId = maintainer.Id;
|
||||
}
|
||||
|
||||
collection.LastUpdated = now;
|
||||
|
||||
if (isNew)
|
||||
{
|
||||
await this.DbContext.Collections.AddAsync(collection);
|
||||
}
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
this.CacheManager.ClearRegion(collection.CacheRegion);
|
||||
this.Logger.LogInformation($"UpdateArtist `{ collection }` By User `{ user }`");
|
||||
if (isNew) await DbContext.Collections.AddAsync(collection);
|
||||
await DbContext.SaveChangesAsync();
|
||||
CacheManager.ClearRegion(collection.CacheRegion);
|
||||
Logger.LogInformation($"UpdateArtist `{collection}` By User `{user}`");
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
IsSuccess = !errors.Any(),
|
||||
|
@ -285,16 +287,15 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
sw.Start();
|
||||
|
||||
var collection = this.GetCollection(id);
|
||||
var collection = GetCollection(id);
|
||||
|
||||
if (collection == null)
|
||||
{
|
||||
return Task.FromResult(new OperationResult<Collection>(true, string.Format("Collection Not Found [{0}]", id)));
|
||||
}
|
||||
return Task.FromResult(new OperationResult<Collection>(true,
|
||||
string.Format("Collection Not Found [{0}]", id)));
|
||||
|
||||
var result = collection.Adapt<Collection>();
|
||||
var maintainer = this.DbContext.Users.FirstOrDefault(x => x.Id == collection.MaintainerId);
|
||||
result.Maintainer = new Library.Models.DataToken
|
||||
var maintainer = DbContext.Users.FirstOrDefault(x => x.Id == collection.MaintainerId);
|
||||
result.Maintainer = new DataToken
|
||||
{
|
||||
Text = maintainer.UserName,
|
||||
Value = maintainer.RoadieId.ToString()
|
||||
|
@ -302,9 +303,10 @@ namespace Roadie.Api.Services
|
|||
result.AlternateNames = collection.AlternateNames;
|
||||
result.Tags = collection.Tags;
|
||||
result.URLs = collection.URLs;
|
||||
result.Thumbnail = this.MakeCollectionThumbnailImage(collection.RoadieId);
|
||||
result.MediumThumbnail = base.MakeThumbnailImage(id, "collection", this.Configuration.MediumImageSize.Width, this.Configuration.MediumImageSize.Height);
|
||||
result.CollectionFoundCount = (from crc in this.DbContext.CollectionReleases
|
||||
result.Thumbnail = MakeCollectionThumbnailImage(collection.RoadieId);
|
||||
result.MediumThumbnail = MakeThumbnailImage(id, "collection", Configuration.MediumImageSize.Width,
|
||||
Configuration.MediumImageSize.Height);
|
||||
result.CollectionFoundCount = (from crc in DbContext.CollectionReleases
|
||||
where crc.CollectionId == collection.Id
|
||||
select crc.Id).Count();
|
||||
if (includes != null && includes.Any())
|
||||
|
@ -321,31 +323,30 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
|
||||
if (includes.Contains("releases"))
|
||||
{
|
||||
result.Releases = (from crc in this.DbContext.CollectionReleases
|
||||
join r in this.DbContext.Releases.Include(x => x.Artist) on crc.ReleaseId equals r.Id
|
||||
result.Releases = (from crc in DbContext.CollectionReleases
|
||||
join r in DbContext.Releases.Include(x => x.Artist) on crc.ReleaseId equals r.Id
|
||||
where crc.CollectionId == collection.Id
|
||||
orderby crc.ListNumber
|
||||
select new CollectionRelease
|
||||
{
|
||||
ListNumber = crc.ListNumber,
|
||||
Release = Library.Models.Releases.ReleaseList.FromDataRelease(r, r.Artist, this.HttpContext.BaseUrl, this.MakeArtistThumbnailImage(r.Artist.RoadieId), this.MakeReleaseThumbnailImage(r.RoadieId))
|
||||
Release = ReleaseList.FromDataRelease(r, r.Artist, HttpContext.BaseUrl,
|
||||
MakeArtistThumbnailImage(r.Artist.RoadieId), MakeReleaseThumbnailImage(r.RoadieId))
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
if (includes.Contains("stats"))
|
||||
{
|
||||
var collectionReleases = (from crc in this.DbContext.CollectionReleases
|
||||
join r in this.DbContext.Releases.Include(x => x.Artist) on crc.ReleaseId equals r.Id
|
||||
where crc.CollectionId == collection.Id
|
||||
select r);
|
||||
var collectionReleases = from crc in DbContext.CollectionReleases
|
||||
join r in DbContext.Releases.Include(x => x.Artist) on crc.ReleaseId equals r.Id
|
||||
where crc.CollectionId == collection.Id
|
||||
select r;
|
||||
|
||||
var collectionTracks = (from crc in this.DbContext.CollectionReleases
|
||||
join r in this.DbContext.Releases.Include(x => x.Artist) on crc.ReleaseId equals r.Id
|
||||
join rm in this.DbContext.ReleaseMedias on r.Id equals rm.ReleaseId
|
||||
join t in this.DbContext.Tracks on rm.Id equals t.ReleaseMediaId
|
||||
where crc.CollectionId == collection.Id
|
||||
select t);
|
||||
var collectionTracks = from crc in DbContext.CollectionReleases
|
||||
join r in DbContext.Releases.Include(x => x.Artist) on crc.ReleaseId equals r.Id
|
||||
join rm in DbContext.ReleaseMedias on r.Id equals rm.ReleaseId
|
||||
join t in DbContext.Tracks on rm.Id equals t.ReleaseMediaId
|
||||
where crc.CollectionId == collection.Id
|
||||
select t;
|
||||
|
||||
result.Statistics = new CollectionStatistics
|
||||
{
|
||||
|
@ -359,25 +360,31 @@ namespace Roadie.Api.Services
|
|||
TrackPlayedCount = collectionReleases.Sum(x => x.PlayedCount)
|
||||
};
|
||||
}
|
||||
|
||||
if (includes.Contains("comments"))
|
||||
{
|
||||
var collectionComments = this.DbContext.Comments.Include(x => x.User).Where(x => x.CollectionId == collection.Id).OrderByDescending(x => x.CreatedDate).ToArray();
|
||||
var collectionComments = DbContext.Comments.Include(x => x.User)
|
||||
.Where(x => x.CollectionId == collection.Id).OrderByDescending(x => x.CreatedDate).ToArray();
|
||||
if (collectionComments.Any())
|
||||
{
|
||||
var comments = new List<Comment>();
|
||||
var commentIds = collectionComments.Select(x => x.Id).ToArray();
|
||||
var userCommentReactions = (from cr in this.DbContext.CommentReactions
|
||||
var userCommentReactions = (from cr in DbContext.CommentReactions
|
||||
where commentIds.Contains(cr.CommentId)
|
||||
select cr).ToArray();
|
||||
foreach (var collectionComment in collectionComments)
|
||||
{
|
||||
var comment = collectionComment.Adapt<Comment>();
|
||||
comment.DatabaseId = collectionComment.Id;
|
||||
comment.User = UserList.FromDataUser(collectionComment.User, this.MakeUserThumbnailImage(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);
|
||||
comment.User = UserList.FromDataUser(collectionComment.User,
|
||||
MakeUserThumbnailImage(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);
|
||||
}
|
||||
|
||||
result.Comments = comments;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Threading.Tasks;
|
||||
using data = Roadie.Library.Data;
|
||||
|
||||
|
@ -19,11 +18,11 @@ namespace Roadie.Api.Services
|
|||
public class CommentService : ServiceBase, ICommentService
|
||||
{
|
||||
public CommentService(IRoadieSettings configuration,
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext context,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<CommentService> logger)
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext context,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<CommentService> logger)
|
||||
: base(configuration, httpEncoder, context, cacheManager, logger, httpContext)
|
||||
{
|
||||
}
|
||||
|
@ -33,12 +32,10 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
var result = false;
|
||||
var errors = new List<Exception>();
|
||||
var artist = this.DbContext.Artists
|
||||
.FirstOrDefault(x => x.RoadieId == artistId);
|
||||
var artist = DbContext.Artists
|
||||
.FirstOrDefault(x => x.RoadieId == artistId);
|
||||
if (artist == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, string.Format("Artist Not Found [{0}]", artistId));
|
||||
}
|
||||
|
||||
var newComment = new data.Comment
|
||||
{
|
||||
|
@ -46,9 +43,9 @@ namespace Roadie.Api.Services
|
|||
UserId = user.Id.Value,
|
||||
Cmt = cmt
|
||||
};
|
||||
this.DbContext.Comments.Add(newComment);
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
this.CacheManager.ClearRegion(artist.CacheRegion);
|
||||
DbContext.Comments.Add(newComment);
|
||||
await DbContext.SaveChangesAsync();
|
||||
CacheManager.ClearRegion(artist.CacheRegion);
|
||||
sw.Stop();
|
||||
result = true;
|
||||
return new OperationResult<bool>
|
||||
|
@ -65,12 +62,10 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
var result = false;
|
||||
var errors = new List<Exception>();
|
||||
var collection = this.DbContext.Collections
|
||||
.FirstOrDefault(x => x.RoadieId == collectionId);
|
||||
var collection = DbContext.Collections
|
||||
.FirstOrDefault(x => x.RoadieId == collectionId);
|
||||
if (collection == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, string.Format("Collection Not Found [{0}]", collectionId));
|
||||
}
|
||||
|
||||
var newComment = new data.Comment
|
||||
{
|
||||
|
@ -78,9 +73,9 @@ namespace Roadie.Api.Services
|
|||
UserId = user.Id.Value,
|
||||
Cmt = cmt
|
||||
};
|
||||
this.DbContext.Comments.Add(newComment);
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
this.CacheManager.ClearRegion(collection.CacheRegion);
|
||||
DbContext.Comments.Add(newComment);
|
||||
await DbContext.SaveChangesAsync();
|
||||
CacheManager.ClearRegion(collection.CacheRegion);
|
||||
sw.Stop();
|
||||
result = true;
|
||||
return new OperationResult<bool>
|
||||
|
@ -97,12 +92,9 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
var result = false;
|
||||
var errors = new List<Exception>();
|
||||
var genre = this.DbContext.Genres
|
||||
.FirstOrDefault(x => x.RoadieId == genreId);
|
||||
if (genre == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, string.Format("Genre Not Found [{0}]", genreId));
|
||||
}
|
||||
var genre = DbContext.Genres
|
||||
.FirstOrDefault(x => x.RoadieId == genreId);
|
||||
if (genre == null) return new OperationResult<bool>(true, string.Format("Genre Not Found [{0}]", genreId));
|
||||
|
||||
var newComment = new data.Comment
|
||||
{
|
||||
|
@ -110,9 +102,9 @@ namespace Roadie.Api.Services
|
|||
UserId = user.Id.Value,
|
||||
Cmt = cmt
|
||||
};
|
||||
this.DbContext.Comments.Add(newComment);
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
this.CacheManager.ClearRegion(genre.CacheRegion);
|
||||
DbContext.Comments.Add(newComment);
|
||||
await DbContext.SaveChangesAsync();
|
||||
CacheManager.ClearRegion(genre.CacheRegion);
|
||||
sw.Stop();
|
||||
result = true;
|
||||
return new OperationResult<bool>
|
||||
|
@ -129,12 +121,9 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
var result = false;
|
||||
var errors = new List<Exception>();
|
||||
var label = this.DbContext.Labels
|
||||
.FirstOrDefault(x => x.RoadieId == labelId);
|
||||
if (label == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, string.Format("Label Not Found [{0}]", labelId));
|
||||
}
|
||||
var label = DbContext.Labels
|
||||
.FirstOrDefault(x => x.RoadieId == labelId);
|
||||
if (label == null) return new OperationResult<bool>(true, string.Format("Label Not Found [{0}]", labelId));
|
||||
|
||||
var newComment = new data.Comment
|
||||
{
|
||||
|
@ -142,9 +131,9 @@ namespace Roadie.Api.Services
|
|||
UserId = user.Id.Value,
|
||||
Cmt = cmt
|
||||
};
|
||||
this.DbContext.Comments.Add(newComment);
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
this.CacheManager.ClearRegion(label.CacheRegion);
|
||||
DbContext.Comments.Add(newComment);
|
||||
await DbContext.SaveChangesAsync();
|
||||
CacheManager.ClearRegion(label.CacheRegion);
|
||||
sw.Stop();
|
||||
result = true;
|
||||
return new OperationResult<bool>
|
||||
|
@ -161,12 +150,10 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
var result = false;
|
||||
var errors = new List<Exception>();
|
||||
var playlist = this.DbContext.Playlists
|
||||
.FirstOrDefault(x => x.RoadieId == playlistId);
|
||||
var playlist = DbContext.Playlists
|
||||
.FirstOrDefault(x => x.RoadieId == playlistId);
|
||||
if (playlist == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, string.Format("Playlist Not Found [{0}]", playlistId));
|
||||
}
|
||||
|
||||
var newComment = new data.Comment
|
||||
{
|
||||
|
@ -174,9 +161,9 @@ namespace Roadie.Api.Services
|
|||
UserId = user.Id.Value,
|
||||
Cmt = cmt
|
||||
};
|
||||
this.DbContext.Comments.Add(newComment);
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
this.CacheManager.ClearRegion(playlist.CacheRegion);
|
||||
DbContext.Comments.Add(newComment);
|
||||
await DbContext.SaveChangesAsync();
|
||||
CacheManager.ClearRegion(playlist.CacheRegion);
|
||||
sw.Stop();
|
||||
result = true;
|
||||
return new OperationResult<bool>
|
||||
|
@ -193,12 +180,10 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
var result = false;
|
||||
var errors = new List<Exception>();
|
||||
var release = this.DbContext.Releases
|
||||
.FirstOrDefault(x => x.RoadieId == releaseId);
|
||||
var release = DbContext.Releases
|
||||
.FirstOrDefault(x => x.RoadieId == releaseId);
|
||||
if (release == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, string.Format("Release Not Found [{0}]", releaseId));
|
||||
}
|
||||
|
||||
var newComment = new data.Comment
|
||||
{
|
||||
|
@ -206,9 +191,9 @@ namespace Roadie.Api.Services
|
|||
UserId = user.Id.Value,
|
||||
Cmt = cmt
|
||||
};
|
||||
this.DbContext.Comments.Add(newComment);
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
this.CacheManager.ClearRegion(release.CacheRegion);
|
||||
DbContext.Comments.Add(newComment);
|
||||
await DbContext.SaveChangesAsync();
|
||||
CacheManager.ClearRegion(release.CacheRegion);
|
||||
sw.Stop();
|
||||
result = true;
|
||||
return new OperationResult<bool>
|
||||
|
@ -225,12 +210,9 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
var result = false;
|
||||
var errors = new List<Exception>();
|
||||
var track = this.DbContext.Tracks
|
||||
.FirstOrDefault(x => x.RoadieId == trackId);
|
||||
if (track == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, string.Format("Track Not Found [{0}]", trackId));
|
||||
}
|
||||
var track = DbContext.Tracks
|
||||
.FirstOrDefault(x => x.RoadieId == trackId);
|
||||
if (track == null) return new OperationResult<bool>(true, string.Format("Track Not Found [{0}]", trackId));
|
||||
|
||||
var newComment = new data.Comment
|
||||
{
|
||||
|
@ -238,9 +220,9 @@ namespace Roadie.Api.Services
|
|||
UserId = user.Id.Value,
|
||||
Cmt = cmt
|
||||
};
|
||||
this.DbContext.Comments.Add(newComment);
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
this.CacheManager.ClearRegion(track.CacheRegion);
|
||||
DbContext.Comments.Add(newComment);
|
||||
await DbContext.SaveChangesAsync();
|
||||
CacheManager.ClearRegion(track.CacheRegion);
|
||||
sw.Stop();
|
||||
result = true;
|
||||
return new OperationResult<bool>
|
||||
|
@ -257,14 +239,11 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
var result = false;
|
||||
var errors = new List<Exception>();
|
||||
var comment = this.DbContext.Comments.FirstOrDefault(x => x.RoadieId == id);
|
||||
if (comment == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, string.Format("Comment Not Found [{0}]", id));
|
||||
}
|
||||
this.DbContext.Remove(comment);
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
this.ClearCaches(comment);
|
||||
var comment = DbContext.Comments.FirstOrDefault(x => x.RoadieId == id);
|
||||
if (comment == null) return new OperationResult<bool>(true, string.Format("Comment Not Found [{0}]", id));
|
||||
DbContext.Remove(comment);
|
||||
await DbContext.SaveChangesAsync();
|
||||
ClearCaches(comment);
|
||||
sw.Stop();
|
||||
result = true;
|
||||
return new OperationResult<bool>
|
||||
|
@ -281,12 +260,10 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
var result = false;
|
||||
var errors = new List<Exception>();
|
||||
var comment = this.DbContext.Comments.FirstOrDefault(x => x.RoadieId == id);
|
||||
if (comment == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, string.Format("Comment Not Found [{0}]", id));
|
||||
}
|
||||
var userCommentReaction = this.DbContext.CommentReactions.FirstOrDefault(x => x.CommentId == comment.Id && x.UserId == user.Id);
|
||||
var comment = DbContext.Comments.FirstOrDefault(x => x.RoadieId == id);
|
||||
if (comment == null) return new OperationResult<bool>(true, string.Format("Comment Not Found [{0}]", id));
|
||||
var userCommentReaction =
|
||||
DbContext.CommentReactions.FirstOrDefault(x => x.CommentId == comment.Id && x.UserId == user.Id);
|
||||
if (userCommentReaction == null)
|
||||
{
|
||||
userCommentReaction = new data.CommentReaction
|
||||
|
@ -294,17 +271,20 @@ namespace Roadie.Api.Services
|
|||
CommentId = comment.Id,
|
||||
UserId = user.Id.Value
|
||||
};
|
||||
this.DbContext.CommentReactions.Add(userCommentReaction);
|
||||
DbContext.CommentReactions.Add(userCommentReaction);
|
||||
}
|
||||
|
||||
userCommentReaction.Reaction = reaction == CommentReaction.Unknown ? null : reaction.ToString();
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
this.ClearCaches(comment);
|
||||
var userCommentReactions = (from cr in this.DbContext.CommentReactions
|
||||
await DbContext.SaveChangesAsync();
|
||||
ClearCaches(comment);
|
||||
var userCommentReactions = (from cr in DbContext.CommentReactions
|
||||
where cr.CommentId == comment.Id
|
||||
select cr).ToArray();
|
||||
var additionalData = new Dictionary<string, object>();
|
||||
additionalData.Add("likedCount", userCommentReactions.Where(x => x.ReactionValue == CommentReaction.Like).Count());
|
||||
additionalData.Add("dislikedCount", userCommentReactions.Where(x => x.ReactionValue == CommentReaction.Dislike).Count());
|
||||
additionalData.Add("likedCount",
|
||||
userCommentReactions.Where(x => x.ReactionValue == CommentReaction.Like).Count());
|
||||
additionalData.Add("dislikedCount",
|
||||
userCommentReactions.Where(x => x.ReactionValue == CommentReaction.Dislike).Count());
|
||||
sw.Stop();
|
||||
result = true;
|
||||
return new OperationResult<bool>
|
||||
|
@ -322,59 +302,38 @@ namespace Roadie.Api.Services
|
|||
switch (comment.CommentType)
|
||||
{
|
||||
case CommentType.Artist:
|
||||
var artist = this.DbContext.Artists.FirstOrDefault(x => x.Id == comment.ArtistId);
|
||||
if (artist != null)
|
||||
{
|
||||
this.CacheManager.ClearRegion(artist.CacheRegion);
|
||||
}
|
||||
var artist = DbContext.Artists.FirstOrDefault(x => x.Id == comment.ArtistId);
|
||||
if (artist != null) CacheManager.ClearRegion(artist.CacheRegion);
|
||||
break;
|
||||
|
||||
case CommentType.Collection:
|
||||
var collection = this.DbContext.Collections.FirstOrDefault(x => x.Id == comment.CollectionId);
|
||||
if (collection != null)
|
||||
{
|
||||
this.CacheManager.ClearRegion(collection.CacheRegion);
|
||||
}
|
||||
var collection = DbContext.Collections.FirstOrDefault(x => x.Id == comment.CollectionId);
|
||||
if (collection != null) CacheManager.ClearRegion(collection.CacheRegion);
|
||||
break;
|
||||
|
||||
case CommentType.Genre:
|
||||
var genre = this.DbContext.Genres.FirstOrDefault(x => x.Id == comment.GenreId);
|
||||
if (genre != null)
|
||||
{
|
||||
this.CacheManager.ClearRegion(genre.CacheRegion);
|
||||
}
|
||||
var genre = DbContext.Genres.FirstOrDefault(x => x.Id == comment.GenreId);
|
||||
if (genre != null) CacheManager.ClearRegion(genre.CacheRegion);
|
||||
break;
|
||||
|
||||
case CommentType.Label:
|
||||
var label = this.DbContext.Labels.FirstOrDefault(x => x.Id == comment.LabelId);
|
||||
if (label != null)
|
||||
{
|
||||
this.CacheManager.ClearRegion(label.CacheRegion);
|
||||
}
|
||||
var label = DbContext.Labels.FirstOrDefault(x => x.Id == comment.LabelId);
|
||||
if (label != null) CacheManager.ClearRegion(label.CacheRegion);
|
||||
break;
|
||||
|
||||
case CommentType.Playlist:
|
||||
var playlist = this.DbContext.Playlists.FirstOrDefault(x => x.Id == comment.PlaylistId);
|
||||
if (playlist != null)
|
||||
{
|
||||
this.CacheManager.ClearRegion(playlist.CacheRegion);
|
||||
}
|
||||
var playlist = DbContext.Playlists.FirstOrDefault(x => x.Id == comment.PlaylistId);
|
||||
if (playlist != null) CacheManager.ClearRegion(playlist.CacheRegion);
|
||||
break;
|
||||
|
||||
case CommentType.Release:
|
||||
var release = this.DbContext.Releases.FirstOrDefault(x => x.Id == comment.ReleaseId);
|
||||
if (release != null)
|
||||
{
|
||||
this.CacheManager.ClearRegion(release.CacheRegion);
|
||||
}
|
||||
var release = DbContext.Releases.FirstOrDefault(x => x.Id == comment.ReleaseId);
|
||||
if (release != null) CacheManager.ClearRegion(release.CacheRegion);
|
||||
break;
|
||||
|
||||
case CommentType.Track:
|
||||
var track = this.DbContext.Tracks.FirstOrDefault(x => x.Id == comment.TrackId);
|
||||
if (track != null)
|
||||
{
|
||||
this.CacheManager.ClearRegion(track.CacheRegion);
|
||||
}
|
||||
var track = DbContext.Tracks.FirstOrDefault(x => x.Id == comment.TrackId);
|
||||
if (track != null) CacheManager.ClearRegion(track.CacheRegion);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
using Roadie.Library.Configuration;
|
||||
using System.Net;
|
||||
using System.Net.Mail;
|
||||
using System.Net.Security;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Roadie.Api.Services
|
||||
|
@ -14,28 +12,25 @@ namespace Roadie.Api.Services
|
|||
|
||||
public EmailSenderService(IRoadieSettings configuration)
|
||||
{
|
||||
this.Configuration = configuration;
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
public async Task SendEmailAsync(string email, string subject, string htmlMessage)
|
||||
{
|
||||
using (MailMessage mail = new MailMessage(this.Configuration.SmtpFromAddress, email))
|
||||
using (var mail = new MailMessage(Configuration.SmtpFromAddress, email))
|
||||
{
|
||||
using (SmtpClient client = new SmtpClient())
|
||||
using (var client = new SmtpClient())
|
||||
{
|
||||
client.Port = this.Configuration.SmtpPort;
|
||||
client.EnableSsl = this.Configuration.SmtpUseSSl;
|
||||
client.Port = Configuration.SmtpPort;
|
||||
client.EnableSsl = Configuration.SmtpUseSSl;
|
||||
client.DeliveryMethod = SmtpDeliveryMethod.Network;
|
||||
client.UseDefaultCredentials = false;
|
||||
client.Credentials = new NetworkCredential(this.Configuration.SmtpUsername, this.Configuration.SmtpPassword);
|
||||
client.Host = this.Configuration.SmtpHost;
|
||||
client.Credentials = new NetworkCredential(Configuration.SmtpUsername, Configuration.SmtpPassword);
|
||||
client.Host = Configuration.SmtpHost;
|
||||
mail.Subject = subject;
|
||||
mail.IsBodyHtml = true;
|
||||
mail.Body = htmlMessage;
|
||||
ServicePointManager.ServerCertificateValidationCallback = delegate (object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
||||
{
|
||||
return true;
|
||||
};
|
||||
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
|
||||
await client.SendMailAsync(mail);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,16 +19,17 @@ namespace Roadie.Api.Services
|
|||
public class GenreService : ServiceBase, IGenreService
|
||||
{
|
||||
public GenreService(IRoadieSettings configuration,
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext dbContext,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<GenreService> logger)
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext dbContext,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<GenreService> logger)
|
||||
: base(configuration, httpEncoder, dbContext, cacheManager, logger, httpContext)
|
||||
{
|
||||
}
|
||||
|
||||
public Task<Library.Models.Pagination.PagedResult<GenreList>> List(User roadieUser, PagedRequest request, bool? doRandomize = false)
|
||||
public Task<Library.Models.Pagination.PagedResult<GenreList>> List(User roadieUser, PagedRequest request,
|
||||
bool? doRandomize = false)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
@ -38,30 +39,31 @@ namespace Roadie.Api.Services
|
|||
request.Sort = request.Sort.Replace("createdDate", "createdDateTime");
|
||||
request.Sort = request.Sort.Replace("lastUpdated", "lastUpdatedDateTime");
|
||||
}
|
||||
var result = (from g in this.DbContext.Genres
|
||||
let releaseCount = (from rg in this.DbContext.ReleaseGenres
|
||||
where rg.GenreId == g.Id
|
||||
select rg.Id).Count()
|
||||
let artistCount = (from rg in this.DbContext.ArtistGenres
|
||||
|
||||
var result = from g in DbContext.Genres
|
||||
let releaseCount = (from rg in DbContext.ReleaseGenres
|
||||
where rg.GenreId == g.Id
|
||||
select rg.Id).Count()
|
||||
where (request.FilterValue.Length == 0 || (g.Name.Contains(request.FilterValue)))
|
||||
select new GenreList
|
||||
{
|
||||
DatabaseId = g.Id,
|
||||
Id = g.RoadieId,
|
||||
Genre = new DataToken
|
||||
{
|
||||
Text = g.Name,
|
||||
Value = g.RoadieId.ToString()
|
||||
},
|
||||
ReleaseCount = releaseCount,
|
||||
ArtistCount = artistCount,
|
||||
CreatedDate = g.CreatedDate,
|
||||
LastUpdated = g.LastUpdated,
|
||||
});
|
||||
let artistCount = (from rg in DbContext.ArtistGenres
|
||||
where rg.GenreId == g.Id
|
||||
select rg.Id).Count()
|
||||
where request.FilterValue.Length == 0 || g.Name.Contains(request.FilterValue)
|
||||
select new GenreList
|
||||
{
|
||||
DatabaseId = g.Id,
|
||||
Id = g.RoadieId,
|
||||
Genre = new DataToken
|
||||
{
|
||||
Text = g.Name,
|
||||
Value = g.RoadieId.ToString()
|
||||
},
|
||||
ReleaseCount = releaseCount,
|
||||
ArtistCount = artistCount,
|
||||
CreatedDate = g.CreatedDate,
|
||||
LastUpdated = g.LastUpdated
|
||||
};
|
||||
|
||||
GenreList[] rows = null;
|
||||
GenreList[] rows;
|
||||
var rowCount = result.Count();
|
||||
if (doRandomize ?? false)
|
||||
{
|
||||
|
@ -71,9 +73,12 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
else
|
||||
{
|
||||
var sortBy = string.IsNullOrEmpty(request.Sort) ? request.OrderValue(new Dictionary<string, string> { { "Genre.Text", "ASC" } }) : request.OrderValue(null);
|
||||
var sortBy = string.IsNullOrEmpty(request.Sort)
|
||||
? request.OrderValue(new Dictionary<string, string> { { "Genre.Text", "ASC" } })
|
||||
: request.OrderValue();
|
||||
rows = result.OrderBy(sortBy).Skip(request.SkipValue).Take(request.LimitValue).ToArray();
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
return Task.FromResult(new Library.Models.Pagination.PagedResult<GenreList>
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Roadie.Library.Configuration;
|
||||
using Roadie.Library.Utility;
|
||||
|
||||
|
@ -7,22 +8,18 @@ namespace Roadie.Api.Services
|
|||
public class HttpContext : IHttpContext
|
||||
{
|
||||
public string BaseUrl { get; set; }
|
||||
|
||||
public string ImageBaseUrl { get; set; }
|
||||
|
||||
public HttpContext(IRoadieSettings configuration, IUrlHelper urlHelper)
|
||||
{
|
||||
var scheme = urlHelper.ActionContext.HttpContext.Request.Scheme;
|
||||
if (configuration.UseSSLBehindProxy)
|
||||
{
|
||||
scheme = "https";
|
||||
}
|
||||
if (configuration.UseSSLBehindProxy) scheme = "https";
|
||||
var host = urlHelper.ActionContext.HttpContext.Request.Host;
|
||||
if (!string.IsNullOrEmpty(configuration.BehindProxyHost))
|
||||
{
|
||||
host = new Microsoft.AspNetCore.Http.HostString(configuration.BehindProxyHost);
|
||||
}
|
||||
this.BaseUrl = $"{ scheme }://{ host }";
|
||||
this.ImageBaseUrl = $"{ this.BaseUrl}/images";
|
||||
host = new HostString(configuration.BehindProxyHost);
|
||||
BaseUrl = $"{scheme}://{host}";
|
||||
ImageBaseUrl = $"{BaseUrl}/images";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using Roadie.Library.Encoding;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
|
||||
namespace Roadie.Api.Services
|
||||
|
@ -28,7 +29,7 @@ namespace Roadie.Api.Services
|
|||
|
||||
public string UrlEncodeBase64(string input)
|
||||
{
|
||||
return WebEncoders.Base64UrlEncode(System.Text.Encoding.ASCII.GetBytes(input));
|
||||
return WebEncoders.Base64UrlEncode(Encoding.ASCII.GetBytes(input));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,8 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
Task<OperationResult<bool>> DeleteArtist(ApplicationUser user, Guid artistId);
|
||||
|
||||
Task<OperationResult<bool>> DeleteArtistReleases(ApplicationUser user, Guid artistId, bool doDeleteFiles = false);
|
||||
Task<OperationResult<bool>> DeleteArtistReleases(ApplicationUser user, Guid artistId,
|
||||
bool doDeleteFiles = false);
|
||||
|
||||
Task<OperationResult<bool>> DeleteArtistSecondaryImage(ApplicationUser user, Guid artistId, int index);
|
||||
|
||||
|
@ -27,16 +28,19 @@ namespace Roadie.Api.Services
|
|||
|
||||
Task<OperationResult<Dictionary<string, List<string>>>> MissingCollectionReleases(ApplicationUser user);
|
||||
|
||||
Task<OperationResult<bool>> ScanAllCollections(ApplicationUser user, bool isReadOnly = false, bool doPurgeFirst = false);
|
||||
Task<OperationResult<bool>> ScanAllCollections(ApplicationUser user, bool isReadOnly = false,
|
||||
bool doPurgeFirst = false);
|
||||
|
||||
Task<OperationResult<bool>> ScanArtist(ApplicationUser user, Guid artistId, bool isReadOnly = false);
|
||||
|
||||
Task<OperationResult<bool>> ScanCollection(ApplicationUser user, Guid collectionId, bool isReadOnly = false, bool doPurgeFirst = false, bool doUpdateRanks = true);
|
||||
Task<OperationResult<bool>> ScanCollection(ApplicationUser user, Guid collectionId, bool isReadOnly = false,
|
||||
bool doPurgeFirst = false, bool doUpdateRanks = true);
|
||||
|
||||
Task<OperationResult<bool>> ScanInboundFolder(ApplicationUser user, bool isReadOnly = false);
|
||||
|
||||
Task<OperationResult<bool>> ScanLibraryFolder(ApplicationUser user, bool isReadOnly = false);
|
||||
|
||||
Task<OperationResult<bool>> ScanRelease(ApplicationUser user, Guid releaseId, bool isReadOnly = false, bool wasDoneForInvalidTrackPlay = false);
|
||||
Task<OperationResult<bool>> ScanRelease(ApplicationUser user, Guid releaseId, bool isReadOnly = false,
|
||||
bool wasDoneForInvalidTrackPlay = false);
|
||||
}
|
||||
}
|
|
@ -13,14 +13,15 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
Task<OperationResult<Artist>> ById(User roadieUser, Guid id, IEnumerable<string> includes);
|
||||
|
||||
Task<PagedResult<ArtistList>> List(User roadieUser, PagedRequest request, bool? doRandomize = false, bool? onlyIncludeWithReleases = true);
|
||||
Task<PagedResult<ArtistList>> List(User roadieUser, PagedRequest request, bool? doRandomize = false,
|
||||
bool? onlyIncludeWithReleases = true);
|
||||
|
||||
Task<OperationResult<bool>> MergeArtists(User user, Guid artistToMergeId, Guid artistToMergeIntoId);
|
||||
|
||||
Task<OperationResult<Library.Models.Image>> SetReleaseImageByUrl(User user, Guid id, string imageUrl);
|
||||
Task<OperationResult<Image>> SetReleaseImageByUrl(User user, Guid id, string imageUrl);
|
||||
|
||||
Task<OperationResult<bool>> UpdateArtist(User user, Artist artist);
|
||||
|
||||
Task<OperationResult<Library.Models.Image>> UploadArtistImage(User user, Guid id, IFormFile file);
|
||||
Task<OperationResult<Image>> UploadArtistImage(User user, Guid id, IFormFile file);
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
public interface IBookmarkService
|
||||
{
|
||||
Task<PagedResult<BookmarkList>> List(User roadieUser, PagedRequest request, bool? doRandomize = false, BookmarkType? filterType = null);
|
||||
Task<PagedResult<BookmarkList>> List(User roadieUser, PagedRequest request, bool? doRandomize = false,
|
||||
BookmarkType? filterType = null);
|
||||
}
|
||||
}
|
|
@ -16,7 +16,8 @@ namespace Roadie.Api.Services
|
|||
|
||||
Task<OperationResult<bool>> DeleteCollection(User user, Guid id);
|
||||
|
||||
Task<PagedResult<CollectionList>> List(User roadieUser, PagedRequest request, bool? doRandomize = false, Guid? releaseId = null, Guid? artistId = null);
|
||||
Task<PagedResult<CollectionList>> List(User roadieUser, PagedRequest request, bool? doRandomize = false,
|
||||
Guid? releaseId = null, Guid? artistId = null);
|
||||
|
||||
Task<OperationResult<bool>> UpdateCollection(User roadieUser, Collection collection);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using Microsoft.Net.Http.Headers;
|
||||
using Roadie.Library;
|
||||
using Roadie.Library.Models;
|
||||
using Roadie.Library.Models.Users;
|
||||
using Roadie.Library.SearchEngines.Imaging;
|
||||
using System;
|
||||
|
@ -10,30 +11,36 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
public interface IImageService
|
||||
{
|
||||
Task<FileOperationResult<Library.Models.Image>> ArtistImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<Image>>
|
||||
ArtistImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<FileOperationResult<Library.Models.Image>> ArtistSecondaryImage(Guid id, int imageId, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<Image>> ArtistSecondaryImage(Guid id, int imageId, int? width, int? height,
|
||||
EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<FileOperationResult<Library.Models.Image>> ById(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<Image>> ById(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<FileOperationResult<Library.Models.Image>> CollectionImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<Image>> CollectionImage(Guid id, int? width, int? height,
|
||||
EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<OperationResult<bool>> Delete(User user, Guid id);
|
||||
|
||||
Task<OperationResult<IEnumerable<ImageSearchResult>>> ImageProvidersSearch(string query);
|
||||
|
||||
Task<FileOperationResult<Library.Models.Image>> LabelImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<Image>> LabelImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<FileOperationResult<Library.Models.Image>> PlaylistImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<Image>> PlaylistImage(Guid id, int? width, int? height,
|
||||
EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<FileOperationResult<Library.Models.Image>> ReleaseImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<Image>> ReleaseImage(Guid id, int? width, int? height,
|
||||
EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<FileOperationResult<Library.Models.Image>> ReleaseSecondaryImage(Guid id, int imageId, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<Image>> ReleaseSecondaryImage(Guid id, int imageId, int? width, int? height,
|
||||
EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<OperationResult<IEnumerable<ImageSearchResult>>> Search(string query, int resultsCount = 10);
|
||||
|
||||
Task<FileOperationResult<Library.Models.Image>> TrackImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<Image>> TrackImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<FileOperationResult<Library.Models.Image>> UserImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<Image>> UserImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
}
|
||||
}
|
|
@ -10,8 +10,11 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
public interface IPlayActivityService
|
||||
{
|
||||
Task<PagedResult<PlayActivityList>> List(PagedRequest request, User roadieUser = null,
|
||||
DateTime? newerThan = null);
|
||||
|
||||
Task<OperationResult<bool>> NowPlaying(User roadieUser, ScrobbleInfo scrobble);
|
||||
|
||||
Task<OperationResult<bool>> Scrobble(User roadieUser, ScrobbleInfo scrobble);
|
||||
Task<PagedResult<PlayActivityList>> List(PagedRequest request, User roadieUser = null, DateTime? newerThan = null);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using Microsoft.AspNetCore.Http;
|
||||
using Roadie.Library;
|
||||
using Roadie.Library.Models;
|
||||
using Roadie.Library.Models.Pagination;
|
||||
using Roadie.Library.Models.Releases;
|
||||
using Roadie.Library.Models.Users;
|
||||
|
@ -13,16 +14,18 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
Task<OperationResult<Release>> ById(User roadieUser, Guid id, IEnumerable<string> includes = null);
|
||||
|
||||
Task<PagedResult<ReleaseList>> List(User user, PagedRequest request, bool? doRandomize = false, IEnumerable<string> includes = null);
|
||||
Task<PagedResult<ReleaseList>> List(User user, PagedRequest request, bool? doRandomize = false,
|
||||
IEnumerable<string> includes = null);
|
||||
|
||||
Task<OperationResult<bool>> MergeReleases(User user, Guid releaseToMergeId, Guid releaseToMergeIntoId, bool addAsMedia);
|
||||
Task<OperationResult<bool>> MergeReleases(User user, Guid releaseToMergeId, Guid releaseToMergeIntoId,
|
||||
bool addAsMedia);
|
||||
|
||||
Task<FileOperationResult<byte[]>> ReleaseZipped(User roadieUser, Guid id);
|
||||
|
||||
Task<OperationResult<Library.Models.Image>> SetReleaseImageByUrl(User user, Guid id, string imageUrl);
|
||||
Task<OperationResult<Image>> SetReleaseImageByUrl(User user, Guid id, string imageUrl);
|
||||
|
||||
Task<OperationResult<bool>> UpdateRelease(User user, Release release);
|
||||
|
||||
Task<OperationResult<Library.Models.Image>> UploadReleaseImage(User user, Guid id, IFormFile file);
|
||||
Task<OperationResult<Image>> UploadReleaseImage(User user, Guid id, IFormFile file);
|
||||
}
|
||||
}
|
|
@ -1,73 +1,82 @@
|
|||
using Roadie.Library.Models.ThirdPartyApi.Subsonic;
|
||||
using Roadie.Library.Models;
|
||||
using Roadie.Library.Models.ThirdPartyApi.Subsonic;
|
||||
using System.Threading.Tasks;
|
||||
using User = Roadie.Library.Models.Users.User;
|
||||
|
||||
namespace Roadie.Api.Services
|
||||
{
|
||||
public interface ISubsonicService
|
||||
{
|
||||
Task<SubsonicOperationResult<Response>> AddChatMessage(Request request, Roadie.Library.Models.Users.User roadieUser);
|
||||
Task<SubsonicOperationResult<Response>> AddChatMessage(Request request, User roadieUser);
|
||||
|
||||
Task<SubsonicOperationResult<SubsonicAuthenticateResponse>> Authenticate(Request request);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> CreateBookmark(Request request, Roadie.Library.Models.Users.User roadieUser, int position, string comment);
|
||||
Task<SubsonicOperationResult<Response>> CreateBookmark(Request request, User roadieUser, int position,
|
||||
string comment);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> CreatePlaylist(Request request, Roadie.Library.Models.Users.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, Roadie.Library.Models.Users.User roadieUser);
|
||||
Task<SubsonicOperationResult<Response>> DeleteBookmark(Request request, User roadieUser);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> DeletePlaylist(Request request, Roadie.Library.Models.Users.User roadieUser);
|
||||
Task<SubsonicOperationResult<Response>> DeletePlaylist(Request request, User roadieUser);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetAlbum(Request request, Roadie.Library.Models.Users.User roadieUser);
|
||||
Task<SubsonicOperationResult<Response>> GetAlbum(Request request, User roadieUser);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetAlbumInfo(Request request, Roadie.Library.Models.Users.User roadieUser, AlbumInfoVersion version);
|
||||
Task<SubsonicOperationResult<Response>>
|
||||
GetAlbumInfo(Request request, User roadieUser, AlbumInfoVersion version);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetAlbumList(Request request, Roadie.Library.Models.Users.User roadieUser, AlbumListVersions version);
|
||||
Task<SubsonicOperationResult<Response>> GetAlbumList(Request request, User roadieUser,
|
||||
AlbumListVersions version);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetArtist(Request request, Roadie.Library.Models.Users.User roadieUser);
|
||||
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, Roadie.Library.Models.Users.User roadieUser);
|
||||
Task<SubsonicOperationResult<Response>> GetArtists(Request request, User roadieUser);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetBookmarks(Request request, Roadie.Library.Models.Users.User roadieUser);
|
||||
Task<SubsonicOperationResult<Response>> GetBookmarks(Request request, User roadieUser);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetChatMessages(Request request, Roadie.Library.Models.Users.User roadieUser, long? since);
|
||||
Task<SubsonicOperationResult<Response>> GetChatMessages(Request request, User roadieUser, long? since);
|
||||
|
||||
Task<SubsonicFileOperationResult<Roadie.Library.Models.Image>> GetCoverArt(Request request, int? size);
|
||||
Task<SubsonicFileOperationResult<Image>> GetCoverArt(Request request, int? size);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetGenres(Request request);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetIndexes(Request request, Roadie.Library.Models.Users.User roadieUser, long? ifModifiedSince = null);
|
||||
Task<SubsonicOperationResult<Response>> GetIndexes(Request request, User roadieUser,
|
||||
long? ifModifiedSince = null);
|
||||
|
||||
SubsonicOperationResult<Response> GetLicense(Request request);
|
||||
|
||||
SubsonicOperationResult<Response> GetLyrics(Request request, string artistId, string title);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetMusicDirectory(Request request, Roadie.Library.Models.Users.User roadieUser);
|
||||
Task<SubsonicOperationResult<Response>> GetMusicDirectory(Request request, User roadieUser);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetMusicFolders(Request request);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetNowPlaying(Request request, Roadie.Library.Models.Users.User roadieUser);
|
||||
Task<SubsonicOperationResult<Response>> GetNowPlaying(Request request, User roadieUser);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetPlaylist(Request request, Roadie.Library.Models.Users.User roadieUser);
|
||||
Task<SubsonicOperationResult<Response>> GetPlaylist(Request request, User roadieUser);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetPlaylists(Request request, Roadie.Library.Models.Users.User roadieUser, string filterToUserName);
|
||||
Task<SubsonicOperationResult<Response>> GetPlaylists(Request request, User roadieUser, string filterToUserName);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetPlayQueue(Request request, Roadie.Library.Models.Users.User roadieUser);
|
||||
Task<SubsonicOperationResult<Response>> GetPlayQueue(Request request, User roadieUser);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetPodcasts(Request request);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetRandomSongs(Request request, Roadie.Library.Models.Users.User roadieUser);
|
||||
Task<SubsonicOperationResult<Response>> GetRandomSongs(Request request, User roadieUser);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetSimliarSongs(Request request, Roadie.Library.Models.Users.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, Roadie.Library.Models.Users.User roadieUser);
|
||||
Task<SubsonicOperationResult<Response>> GetSong(Request request, User roadieUser);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetSongsByGenre(Request request, Roadie.Library.Models.Users.User roadieUser);
|
||||
Task<SubsonicOperationResult<Response>> GetSongsByGenre(Request request, User roadieUser);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetStarred(Request request, Roadie.Library.Models.Users.User roadieUser, StarredVersion version);
|
||||
Task<SubsonicOperationResult<Response>> GetStarred(Request request, User roadieUser, StarredVersion version);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetTopSongs(Request request, Roadie.Library.Models.Users.User roadieUser, int? count = 50);
|
||||
Task<SubsonicOperationResult<Response>> GetTopSongs(Request request, User roadieUser, int? count = 50);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> GetUser(Request request, string username);
|
||||
|
||||
|
@ -75,14 +84,18 @@ namespace Roadie.Api.Services
|
|||
|
||||
SubsonicOperationResult<Response> Ping(Request request);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> SavePlayQueue(Request request, Roadie.Library.Models.Users.User roadieUser, string current, long? position);
|
||||
Task<SubsonicOperationResult<Response>> SavePlayQueue(Request request, User roadieUser, string current,
|
||||
long? position);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> Search(Request request, Roadie.Library.Models.Users.User roadieUser, SearchVersion version);
|
||||
Task<SubsonicOperationResult<Response>> Search(Request request, User roadieUser, SearchVersion version);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> SetRating(Request request, Roadie.Library.Models.Users.User roadieUser, short rating);
|
||||
Task<SubsonicOperationResult<Response>> SetRating(Request request, User roadieUser, short rating);
|
||||
|
||||
Task<SubsonicOperationResult<Response>> ToggleStar(Request request, Roadie.Library.Models.Users.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, Roadie.Library.Models.Users.User roadieUser, string playlistId, string name = null, string comment = null, bool? isPublic = null, string[] songIdsToAdd = null, int[] songIndexesToRemove = null);
|
||||
Task<SubsonicOperationResult<Response>> UpdatePlaylist(Request request, User roadieUser, string playlistId,
|
||||
string name = null, string comment = null, bool? isPublic = null, string[] songIdsToAdd = null,
|
||||
int[] songIndexesToRemove = null);
|
||||
}
|
||||
}
|
|
@ -12,11 +12,13 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
Task<OperationResult<Track>> ById(User roadieUser, Guid id, IEnumerable<string> includes);
|
||||
|
||||
Task<Library.Models.Pagination.PagedResult<TrackList>> List(PagedRequest request, User roadieUser, bool? doRandomize = false, Guid? releaseId = null);
|
||||
Task<PagedResult<TrackList>> List(PagedRequest request, User roadieUser, bool? doRandomize = false,
|
||||
Guid? releaseId = null);
|
||||
|
||||
OperationResult<Track> StreamCheckAndInfo(User roadieUser, Guid id);
|
||||
|
||||
Task<OperationResult<TrackStreamInfo>> TrackStreamInfo(Guid trackId, long beginBytes, long endBytes, User roadieUser);
|
||||
Task<OperationResult<TrackStreamInfo>> TrackStreamInfo(Guid trackId, long beginBytes, long endBytes,
|
||||
User roadieUser);
|
||||
|
||||
Task<OperationResult<bool>> UpdateTrack(User user, Track track);
|
||||
}
|
||||
|
|
|
@ -43,8 +43,8 @@ namespace Roadie.Api.Services
|
|||
|
||||
Task<OperationResult<short>> SetTrackRating(Guid trackId, User roadieUser, short rating);
|
||||
|
||||
Task<OperationResult<bool>> UpdateProfile(User userPerformingUpdate, User userBeingUpdatedModel);
|
||||
|
||||
Task<OperationResult<bool>> UpdateIntegrationGrant(Guid userId, string integrationName, string token);
|
||||
|
||||
Task<OperationResult<bool>> UpdateProfile(User userPerformingUpdate, User userBeingUpdatedModel);
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ using Roadie.Library;
|
|||
using Roadie.Library.Caching;
|
||||
using Roadie.Library.Configuration;
|
||||
using Roadie.Library.Encoding;
|
||||
using Roadie.Library.Enums;
|
||||
using Roadie.Library.Identity;
|
||||
using Roadie.Library.Imaging;
|
||||
using Roadie.Library.Models;
|
||||
|
@ -25,105 +26,91 @@ namespace Roadie.Api.Services
|
|||
public class ImageService : ServiceBase, IImageService
|
||||
{
|
||||
private IImageSearchEngine BingSearchEngine { get; }
|
||||
|
||||
private IDefaultNotFoundImages DefaultNotFoundImages { get; }
|
||||
|
||||
private IImageSearchEngine ITunesSearchEngine { get; }
|
||||
|
||||
private string Referrer { get; }
|
||||
|
||||
private string RequestIp { get; }
|
||||
|
||||
public ImageService(IRoadieSettings configuration,
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext context,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<ImageService> logger,
|
||||
IDefaultNotFoundImages defaultNotFoundImages)
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext context,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<ImageService> logger,
|
||||
IDefaultNotFoundImages defaultNotFoundImages)
|
||||
: base(configuration, httpEncoder, context, cacheManager, logger, httpContext)
|
||||
{
|
||||
this.DefaultNotFoundImages = defaultNotFoundImages;
|
||||
this.BingSearchEngine = new BingImageSearchEngine(configuration, logger, this.RequestIp, this.Referrer);
|
||||
this.ITunesSearchEngine = new ITunesSearchEngine(configuration, cacheManager, logger, this.RequestIp, this.Referrer);
|
||||
DefaultNotFoundImages = defaultNotFoundImages;
|
||||
BingSearchEngine = new BingImageSearchEngine(configuration, logger, RequestIp, Referrer);
|
||||
ITunesSearchEngine = new ITunesSearchEngine(configuration, cacheManager, logger, RequestIp, Referrer);
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> ArtistImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<Image>> ArtistImage(Guid id, int? width, int? height,
|
||||
EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await this.GetImageFileOperation(type: "ArtistImage",
|
||||
regionUrn: data.Artist.CacheRegionUrn(id),
|
||||
id: id,
|
||||
width: width,
|
||||
height: height,
|
||||
action: async () =>
|
||||
{
|
||||
return await this.ArtistImageAction(id, etag);
|
||||
},
|
||||
etag: etag);
|
||||
return await GetImageFileOperation("ArtistImage",
|
||||
data.Artist.CacheRegionUrn(id),
|
||||
id,
|
||||
width,
|
||||
height,
|
||||
async () => { return await ArtistImageAction(id, etag); },
|
||||
etag);
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> ArtistSecondaryImage(Guid id, int imageId, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<Image>> ArtistSecondaryImage(Guid id, int imageId, int? width,
|
||||
int? height, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await this.GetImageFileOperation(type: $"ArtistSecondaryThumbnail-{imageId}",
|
||||
regionUrn: data.Release.CacheRegionUrn(id),
|
||||
id: id,
|
||||
width: width,
|
||||
height: height,
|
||||
action: async () =>
|
||||
{
|
||||
return await this.ArtistSecondaryImageAction(id, imageId, etag);
|
||||
},
|
||||
etag: etag);
|
||||
return await GetImageFileOperation($"ArtistSecondaryThumbnail-{imageId}",
|
||||
data.Release.CacheRegionUrn(id),
|
||||
id,
|
||||
width,
|
||||
height,
|
||||
async () => { return await ArtistSecondaryImageAction(id, imageId, etag); },
|
||||
etag);
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> ById(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<Image>> ById(Guid id, int? width, int? height,
|
||||
EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await this.GetImageFileOperation(type: "ImageById",
|
||||
regionUrn: data.Image.CacheRegionUrn(id),
|
||||
id: id,
|
||||
width: width,
|
||||
height: height,
|
||||
action: async () =>
|
||||
{
|
||||
return await this.ImageByIdAction(id, etag);
|
||||
},
|
||||
etag: etag);
|
||||
return await GetImageFileOperation("ImageById",
|
||||
data.Image.CacheRegionUrn(id),
|
||||
id,
|
||||
width,
|
||||
height,
|
||||
async () => { return await ImageByIdAction(id, etag); },
|
||||
etag);
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> CollectionImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<Image>> CollectionImage(Guid id, int? width, int? height,
|
||||
EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await this.GetImageFileOperation(type: "CollectionThumbnail",
|
||||
regionUrn: data.Collection.CacheRegionUrn(id),
|
||||
id: id,
|
||||
width: width,
|
||||
height: height,
|
||||
action: async () =>
|
||||
{
|
||||
return await this.CollectionImageAction(id, etag);
|
||||
},
|
||||
etag: etag);
|
||||
return await GetImageFileOperation("CollectionThumbnail",
|
||||
data.Collection.CacheRegionUrn(id),
|
||||
id,
|
||||
width,
|
||||
height,
|
||||
async () => { return await CollectionImageAction(id, etag); },
|
||||
etag);
|
||||
}
|
||||
|
||||
public async Task<OperationResult<bool>> Delete(User user, Guid id)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
var image = this.DbContext.Images
|
||||
.Include("Release")
|
||||
.Include("Artist")
|
||||
.FirstOrDefault(x => x.RoadieId == id);
|
||||
if (image == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, string.Format("Image Not Found [{0}]", id));
|
||||
}
|
||||
if (image.ArtistId.HasValue)
|
||||
{
|
||||
this.CacheManager.ClearRegion(data.Artist.CacheRegionUrn(image.Artist.RoadieId));
|
||||
}
|
||||
if (image.ReleaseId.HasValue)
|
||||
{
|
||||
this.CacheManager.ClearRegion(data.Release.CacheRegionUrn(image.Release.RoadieId));
|
||||
}
|
||||
this.DbContext.Images.Remove(image);
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
this.CacheManager.ClearRegion(data.Image.CacheRegionUrn(id));
|
||||
this.Logger.LogInformation($"Deleted Image [{ id }], By User [{ user.ToString() }]");
|
||||
var image = DbContext.Images
|
||||
.Include("Release")
|
||||
.Include("Artist")
|
||||
.FirstOrDefault(x => x.RoadieId == id);
|
||||
if (image == null) return new OperationResult<bool>(true, string.Format("Image Not Found [{0}]", id));
|
||||
if (image.ArtistId.HasValue) CacheManager.ClearRegion(data.Artist.CacheRegionUrn(image.Artist.RoadieId));
|
||||
if (image.ReleaseId.HasValue) CacheManager.ClearRegion(data.Release.CacheRegionUrn(image.Release.RoadieId));
|
||||
DbContext.Images.Remove(image);
|
||||
await DbContext.SaveChangesAsync();
|
||||
CacheManager.ClearRegion(data.Image.CacheRegionUrn(id));
|
||||
Logger.LogInformation($"Deleted Image [{id}], By User [{user}]");
|
||||
sw.Stop();
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
|
@ -141,14 +128,15 @@ namespace Roadie.Api.Services
|
|||
IEnumerable<ImageSearchResult> searchResults = null;
|
||||
try
|
||||
{
|
||||
var manager = new ImageSearchManager(this.Configuration, this.CacheManager, this.Logger);
|
||||
var manager = new ImageSearchManager(Configuration, CacheManager, Logger);
|
||||
searchResults = await manager.ImageSearch(query);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex);
|
||||
Logger.LogError(ex);
|
||||
errors.Add(ex);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
return new OperationResult<IEnumerable<ImageSearchResult>>
|
||||
{
|
||||
|
@ -159,60 +147,52 @@ namespace Roadie.Api.Services
|
|||
};
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> LabelImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<Image>> LabelImage(Guid id, int? width, int? height,
|
||||
EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await this.GetImageFileOperation(type: "LabelThumbnail",
|
||||
regionUrn: data.Label.CacheRegionUrn(id),
|
||||
id: id,
|
||||
width: width,
|
||||
height: height,
|
||||
action: async () =>
|
||||
{
|
||||
return await this.LabelImageAction(id, etag);
|
||||
},
|
||||
etag: etag);
|
||||
return await GetImageFileOperation("LabelThumbnail",
|
||||
data.Label.CacheRegionUrn(id),
|
||||
id,
|
||||
width,
|
||||
height,
|
||||
async () => { return await LabelImageAction(id, etag); },
|
||||
etag);
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> PlaylistImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<Image>> PlaylistImage(Guid id, int? width, int? height,
|
||||
EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await this.GetImageFileOperation(type: "PlaylistThumbnail",
|
||||
regionUrn: data.Playlist.CacheRegionUrn(id),
|
||||
id: id,
|
||||
width: width,
|
||||
height: height,
|
||||
action: async () =>
|
||||
{
|
||||
return await this.PlaylistImageAction(id, etag);
|
||||
},
|
||||
etag: etag);
|
||||
return await GetImageFileOperation("PlaylistThumbnail",
|
||||
data.Playlist.CacheRegionUrn(id),
|
||||
id,
|
||||
width,
|
||||
height,
|
||||
async () => { return await PlaylistImageAction(id, etag); },
|
||||
etag);
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> ReleaseImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<Image>> ReleaseImage(Guid id, int? width, int? height,
|
||||
EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await this.GetImageFileOperation(type: "ReleaseThumbnail",
|
||||
regionUrn: data.Release.CacheRegionUrn(id),
|
||||
id: id,
|
||||
width: width,
|
||||
height: height,
|
||||
action: async () =>
|
||||
{
|
||||
return await this.ReleaseImageAction(id, etag);
|
||||
},
|
||||
etag: etag);
|
||||
return await GetImageFileOperation("ReleaseThumbnail",
|
||||
data.Release.CacheRegionUrn(id),
|
||||
id,
|
||||
width,
|
||||
height,
|
||||
async () => { return await ReleaseImageAction(id, etag); },
|
||||
etag);
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> ReleaseSecondaryImage(Guid id, int imageId, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<Image>> ReleaseSecondaryImage(Guid id, int imageId, int? width,
|
||||
int? height, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await this.GetImageFileOperation(type: $"ReleaseSecondaryThumbnail-{imageId}",
|
||||
regionUrn: data.Release.CacheRegionUrn(id),
|
||||
id: id,
|
||||
width: width,
|
||||
height: height,
|
||||
action: async () =>
|
||||
{
|
||||
return await this.ReleaseSecondaryImageAction(id, imageId, etag);
|
||||
},
|
||||
etag: etag);
|
||||
return await GetImageFileOperation($"ReleaseSecondaryThumbnail-{imageId}",
|
||||
data.Release.CacheRegionUrn(id),
|
||||
id,
|
||||
width,
|
||||
height,
|
||||
async () => { return await ReleaseSecondaryImageAction(id, imageId, etag); },
|
||||
etag);
|
||||
}
|
||||
|
||||
public async Task<OperationResult<IEnumerable<ImageSearchResult>>> Search(string query, int resultsCount = 10)
|
||||
|
@ -224,21 +204,13 @@ namespace Roadie.Api.Services
|
|||
if (WebHelper.IsStringUrl(query))
|
||||
{
|
||||
var s = ImageHelper.ImageSearchResultForImageUrl(query);
|
||||
if (s != null)
|
||||
{
|
||||
result.Add(s);
|
||||
}
|
||||
}
|
||||
var bingResults = await this.BingSearchEngine.PerformImageSearch(query, resultsCount);
|
||||
if (bingResults != null)
|
||||
{
|
||||
result.AddRange(bingResults);
|
||||
}
|
||||
var iTunesResults = await this.ITunesSearchEngine.PerformImageSearch(query, resultsCount);
|
||||
if (iTunesResults != null)
|
||||
{
|
||||
result.AddRange(iTunesResults);
|
||||
if (s != null) result.Add(s);
|
||||
}
|
||||
|
||||
var bingResults = await BingSearchEngine.PerformImageSearch(query, resultsCount);
|
||||
if (bingResults != null) result.AddRange(bingResults);
|
||||
var iTunesResults = await ITunesSearchEngine.PerformImageSearch(query, resultsCount);
|
||||
if (iTunesResults != null) result.AddRange(iTunesResults);
|
||||
sw.Stop();
|
||||
return new OperationResult<IEnumerable<ImageSearchResult>>
|
||||
{
|
||||
|
@ -248,66 +220,60 @@ namespace Roadie.Api.Services
|
|||
};
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> TrackImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<Image>> TrackImage(Guid id, int? width, int? height,
|
||||
EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await this.GetImageFileOperation(type: "TrackThumbnail",
|
||||
regionUrn: data.Track.CacheRegionUrn(id),
|
||||
id: id,
|
||||
width: width,
|
||||
height: height,
|
||||
action: async () =>
|
||||
{
|
||||
return await this.TrackImageAction(id, width, height, etag);
|
||||
},
|
||||
etag: etag);
|
||||
return await GetImageFileOperation("TrackThumbnail",
|
||||
data.Track.CacheRegionUrn(id),
|
||||
id,
|
||||
width,
|
||||
height,
|
||||
async () => { return await TrackImageAction(id, width, height, etag); },
|
||||
etag);
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> UserImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<Image>> UserImage(Guid id, int? width, int? height,
|
||||
EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await this.GetImageFileOperation(type: "UserById",
|
||||
regionUrn: ApplicationUser.CacheRegionUrn(id),
|
||||
id: id,
|
||||
width: width,
|
||||
height: height,
|
||||
action: async () =>
|
||||
{
|
||||
return await this.UserImageAction(id, etag);
|
||||
},
|
||||
etag: etag);
|
||||
return await GetImageFileOperation("UserById",
|
||||
ApplicationUser.CacheRegionUrn(id),
|
||||
id,
|
||||
width,
|
||||
height,
|
||||
async () => { return await UserImageAction(id, etag); },
|
||||
etag);
|
||||
}
|
||||
|
||||
private Task<FileOperationResult<Image>> ArtistImageAction(Guid id, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var artist = this.GetArtist(id);
|
||||
var artist = GetArtist(id);
|
||||
if (artist == null)
|
||||
{
|
||||
return Task.FromResult(new FileOperationResult<Image>(true, string.Format("Artist Not Found [{0}]", id)));
|
||||
}
|
||||
return Task.FromResult(new FileOperationResult<Image>(true,
|
||||
string.Format("Artist Not Found [{0}]", id)));
|
||||
byte[] imageBytes = null;
|
||||
string artistFolder = null;
|
||||
try
|
||||
{
|
||||
// See if artist images exists in artist folder
|
||||
artistFolder = artist.ArtistFileFolder(this.Configuration, this.Configuration.LibraryFolder);
|
||||
artistFolder = artist.ArtistFileFolder(Configuration, Configuration.LibraryFolder);
|
||||
if (!Directory.Exists(artistFolder))
|
||||
{
|
||||
this.Logger.LogWarning($"Artist Folder [{ artistFolder }], Not Found For Artist `{ artist.ToString() }`");
|
||||
Logger.LogWarning($"Artist Folder [{artistFolder}], Not Found For Artist `{artist}`");
|
||||
}
|
||||
else
|
||||
{
|
||||
var artistImages = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(artistFolder), Library.Enums.ImageType.Artist);
|
||||
if (artistImages.Any())
|
||||
{
|
||||
imageBytes = File.ReadAllBytes(artistImages.First().FullName);
|
||||
}
|
||||
var artistImages =
|
||||
ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(artistFolder), ImageType.Artist);
|
||||
if (artistImages.Any()) imageBytes = File.ReadAllBytes(artistImages.First().FullName);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex, $"Error Reading Folder [{ artistFolder }] For Artist [{ artist.Id }]");
|
||||
Logger.LogError(ex, $"Error Reading Folder [{artistFolder}] For Artist [{artist.Id}]");
|
||||
}
|
||||
|
||||
imageBytes = imageBytes ?? artist.Thumbnail;
|
||||
var image = new data.Image
|
||||
{
|
||||
|
@ -315,51 +281,50 @@ namespace Roadie.Api.Services
|
|||
CreatedDate = artist.CreatedDate,
|
||||
LastUpdated = artist.LastUpdated
|
||||
};
|
||||
if (imageBytes == null || !imageBytes.Any())
|
||||
{
|
||||
image = this.DefaultNotFoundImages.Artist;
|
||||
}
|
||||
if (imageBytes == null || !imageBytes.Any()) image = DefaultNotFoundImages.Artist;
|
||||
return Task.FromResult(GenerateFileOperationResult(id, image, etag));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError($"Error fetching Artist Thumbnail [{ id }]", ex);
|
||||
Logger.LogError($"Error fetching Artist Thumbnail [{id}]", ex);
|
||||
}
|
||||
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
|
||||
private Task<FileOperationResult<Image>> ArtistSecondaryImageAction(Guid id, int imageId, EntityTagHeaderValue etag = null)
|
||||
private Task<FileOperationResult<Image>> ArtistSecondaryImageAction(Guid id, int imageId,
|
||||
EntityTagHeaderValue etag = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var artist = this.GetArtist(id);
|
||||
var artist = GetArtist(id);
|
||||
if (artist == null)
|
||||
{
|
||||
return Task.FromResult(new FileOperationResult<Image>(true, string.Format("Release Not Found [{0}]", id)));
|
||||
}
|
||||
return Task.FromResult(new FileOperationResult<Image>(true,
|
||||
string.Format("Release Not Found [{0}]", id)));
|
||||
byte[] imageBytes = null;
|
||||
string artistFolder = null;
|
||||
try
|
||||
{
|
||||
// See if cover art file exists in release folder
|
||||
artistFolder = artist.ArtistFileFolder(this.Configuration, this.Configuration.LibraryFolder);
|
||||
artistFolder = artist.ArtistFileFolder(Configuration, Configuration.LibraryFolder);
|
||||
if (!Directory.Exists(artistFolder))
|
||||
{
|
||||
this.Logger.LogWarning($"Artist Folder [{ artistFolder }], Not Found For Artist `{ artist }`");
|
||||
Logger.LogWarning($"Artist Folder [{artistFolder}], Not Found For Artist `{artist}`");
|
||||
}
|
||||
else
|
||||
{
|
||||
var artistSecondaryImages = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(artistFolder), Library.Enums.ImageType.ArtistSecondary).ToArray();
|
||||
var artistSecondaryImages = ImageHelper
|
||||
.FindImageTypeInDirectory(new DirectoryInfo(artistFolder), ImageType.ArtistSecondary)
|
||||
.ToArray();
|
||||
if (artistSecondaryImages.Length >= imageId && artistSecondaryImages[imageId] != null)
|
||||
{
|
||||
imageBytes = File.ReadAllBytes(artistSecondaryImages[imageId].FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex, $"Error Reading Artist Folder [{ artistFolder }] For Artist `{ artist }`");
|
||||
Logger.LogError(ex, $"Error Reading Artist Folder [{artistFolder}] For Artist `{artist}`");
|
||||
}
|
||||
|
||||
var image = new data.Image
|
||||
{
|
||||
Bytes = imageBytes,
|
||||
|
@ -370,8 +335,9 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError($"Error fetching Release Thumbnail [{ id }]", ex);
|
||||
Logger.LogError($"Error fetching Release Thumbnail [{id}]", ex);
|
||||
}
|
||||
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
|
||||
|
@ -379,11 +345,10 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
try
|
||||
{
|
||||
var collection = this.GetCollection(id);
|
||||
var collection = GetCollection(id);
|
||||
if (collection == null)
|
||||
{
|
||||
return Task.FromResult(new FileOperationResult<Image>(true, string.Format("Collection Not Found [{0}]", id)));
|
||||
}
|
||||
return Task.FromResult(new FileOperationResult<Image>(true,
|
||||
string.Format("Collection Not Found [{0}]", id)));
|
||||
var image = new data.Image
|
||||
{
|
||||
Bytes = collection.Thumbnail,
|
||||
|
@ -391,63 +356,57 @@ namespace Roadie.Api.Services
|
|||
LastUpdated = collection.LastUpdated
|
||||
};
|
||||
if (collection.Thumbnail == null || !collection.Thumbnail.Any())
|
||||
{
|
||||
image = this.DefaultNotFoundImages.Collection;
|
||||
}
|
||||
image = DefaultNotFoundImages.Collection;
|
||||
return Task.FromResult(GenerateFileOperationResult(id, image, etag));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError($"Error fetching Collection Thumbnail [{ id }]", ex);
|
||||
Logger.LogError($"Error fetching Collection Thumbnail [{id}]", ex);
|
||||
}
|
||||
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
|
||||
private FileOperationResult<Image> GenerateFileOperationResult(Guid id, data.Image image, EntityTagHeaderValue etag = null, string contentType = "image/jpeg")
|
||||
private FileOperationResult<Image> GenerateFileOperationResult(Guid id, data.Image image,
|
||||
EntityTagHeaderValue etag = null, string contentType = "image/jpeg")
|
||||
{
|
||||
var imageEtag = EtagHelper.GenerateETag(this.HttpEncoder, image.Bytes);
|
||||
if (EtagHelper.CompareETag(this.HttpEncoder, etag, imageEtag))
|
||||
{
|
||||
var imageEtag = EtagHelper.GenerateETag(HttpEncoder, image.Bytes);
|
||||
if (EtagHelper.CompareETag(HttpEncoder, etag, imageEtag))
|
||||
return new FileOperationResult<Image>(OperationMessages.NotModified);
|
||||
}
|
||||
if (!image?.Bytes?.Any() ?? false)
|
||||
{
|
||||
return new FileOperationResult<Image>(string.Format("ImageById Not Set [{0}]", id));
|
||||
}
|
||||
return new FileOperationResult<Image>(image?.Bytes?.Any() ?? false ? OperationMessages.OkMessage : OperationMessages.NoImageDataFound)
|
||||
return new FileOperationResult<Image>(image?.Bytes?.Any() ?? false
|
||||
? OperationMessages.OkMessage
|
||||
: OperationMessages.NoImageDataFound)
|
||||
{
|
||||
IsSuccess = true,
|
||||
Data = image.Adapt<Image>(),
|
||||
ContentType = contentType,
|
||||
LastModified = (image.LastUpdated ?? image.CreatedDate),
|
||||
LastModified = image.LastUpdated ?? image.CreatedDate,
|
||||
ETag = imageEtag
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<FileOperationResult<Image>> GetImageFileOperation(string type, string regionUrn, Guid id, int? width, int? height, Func<Task<FileOperationResult<Image>>> action, EntityTagHeaderValue etag = null)
|
||||
private async Task<FileOperationResult<Image>> GetImageFileOperation(string type, string regionUrn, Guid id,
|
||||
int? width, int? height, Func<Task<FileOperationResult<Image>>> action, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
var result = (await this.CacheManager.GetAsync($"urn:{ type }_by_id_operation:{id}", action, regionUrn)).Adapt<FileOperationResult<Image>>();
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return new FileOperationResult<Image>(result.IsNotFoundResult, result.Messages);
|
||||
}
|
||||
if (result.ETag == etag)
|
||||
{
|
||||
return new FileOperationResult<Image>(OperationMessages.NotModified);
|
||||
}
|
||||
var result = (await CacheManager.GetAsync($"urn:{type}_by_id_operation:{id}", action, regionUrn))
|
||||
.Adapt<FileOperationResult<Image>>();
|
||||
if (!result.IsSuccess) return new FileOperationResult<Image>(result.IsNotFoundResult, result.Messages);
|
||||
if (result.ETag == etag) return new FileOperationResult<Image>(OperationMessages.NotModified);
|
||||
if ((width.HasValue || height.HasValue) && result?.Data?.Bytes != null)
|
||||
{
|
||||
result.Data.Bytes = ImageHelper.ResizeImage(result?.Data?.Bytes, width.Value, height.Value);
|
||||
result.ETag = EtagHelper.GenerateETag(this.HttpEncoder, result.Data.Bytes);
|
||||
result.ETag = EtagHelper.GenerateETag(HttpEncoder, result.Data.Bytes);
|
||||
result.LastModified = DateTime.UtcNow;
|
||||
if (width.Value != this.Configuration.ThumbnailImageSize.Width || height.Value != this.Configuration.ThumbnailImageSize.Height)
|
||||
{
|
||||
this.Logger.LogTrace($"{ type }: Resized [{ id }], Width [{ width.Value }], Height [{ height.Value }]");
|
||||
}
|
||||
if (width.Value != Configuration.ThumbnailImageSize.Width ||
|
||||
height.Value != Configuration.ThumbnailImageSize.Height)
|
||||
Logger.LogTrace($"{type}: Resized [{id}], Width [{width.Value}], Height [{height.Value}]");
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
return new FileOperationResult<Image>(result.Messages)
|
||||
{
|
||||
|
@ -462,8 +421,9 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex, $"GetImageFileOperation Error, Type [{ type }], id [{id}]");
|
||||
Logger.LogError(ex, $"GetImageFileOperation Error, Type [{type}], id [{id}]");
|
||||
}
|
||||
|
||||
return new FileOperationResult<Image>("System Error");
|
||||
}
|
||||
|
||||
|
@ -471,20 +431,20 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
try
|
||||
{
|
||||
var image = this.DbContext.Images
|
||||
.Include("Release")
|
||||
.Include("Artist")
|
||||
.FirstOrDefault(x => x.RoadieId == id);
|
||||
var image = DbContext.Images
|
||||
.Include("Release")
|
||||
.Include("Artist")
|
||||
.FirstOrDefault(x => x.RoadieId == id);
|
||||
if (image == null)
|
||||
{
|
||||
return Task.FromResult(new FileOperationResult<Image>(true, string.Format("ImageById Not Found [{0}]", id)));
|
||||
}
|
||||
return Task.FromResult(new FileOperationResult<Image>(true,
|
||||
string.Format("ImageById Not Found [{0}]", id)));
|
||||
return Task.FromResult(GenerateFileOperationResult(id, image, etag));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError($"Error fetching Image [{ id }]", ex);
|
||||
Logger.LogError($"Error fetching Image [{id}]", ex);
|
||||
}
|
||||
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
|
||||
|
@ -492,27 +452,24 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
try
|
||||
{
|
||||
var label = this.GetLabel(id);
|
||||
var label = GetLabel(id);
|
||||
if (label == null)
|
||||
{
|
||||
return Task.FromResult(new FileOperationResult<Image>(true, string.Format("Label Not Found [{0}]", id)));
|
||||
}
|
||||
return Task.FromResult(new FileOperationResult<Image>(true,
|
||||
string.Format("Label Not Found [{0}]", id)));
|
||||
var image = new data.Image
|
||||
{
|
||||
Bytes = label.Thumbnail,
|
||||
CreatedDate = label.CreatedDate,
|
||||
LastUpdated = label.LastUpdated
|
||||
};
|
||||
if (label.Thumbnail == null || !label.Thumbnail.Any())
|
||||
{
|
||||
image = this.DefaultNotFoundImages.Label;
|
||||
}
|
||||
if (label.Thumbnail == null || !label.Thumbnail.Any()) image = DefaultNotFoundImages.Label;
|
||||
return Task.FromResult(GenerateFileOperationResult(id, image, etag));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError($"Error fetching Label Thumbnail [{ id }]", ex);
|
||||
Logger.LogError($"Error fetching Label Thumbnail [{id}]", ex);
|
||||
}
|
||||
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
|
||||
|
@ -520,27 +477,24 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
try
|
||||
{
|
||||
var playlist = this.GetPlaylist(id);
|
||||
var playlist = GetPlaylist(id);
|
||||
if (playlist == null)
|
||||
{
|
||||
return Task.FromResult(new FileOperationResult<Image>(true, string.Format("Playlist Not Found [{0}]", id)));
|
||||
}
|
||||
return Task.FromResult(new FileOperationResult<Image>(true,
|
||||
string.Format("Playlist Not Found [{0}]", id)));
|
||||
var image = new data.Image
|
||||
{
|
||||
Bytes = playlist.Thumbnail,
|
||||
CreatedDate = playlist.CreatedDate,
|
||||
LastUpdated = playlist.LastUpdated
|
||||
};
|
||||
if (playlist.Thumbnail == null || !playlist.Thumbnail.Any())
|
||||
{
|
||||
image = this.DefaultNotFoundImages.Playlist;
|
||||
}
|
||||
if (playlist.Thumbnail == null || !playlist.Thumbnail.Any()) image = DefaultNotFoundImages.Playlist;
|
||||
return Task.FromResult(GenerateFileOperationResult(id, image, etag));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError($"Error fetching Playlist Thumbnail [{ id }]", ex);
|
||||
Logger.LogError($"Error fetching Playlist Thumbnail [{id}]", ex);
|
||||
}
|
||||
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
|
||||
|
@ -548,43 +502,44 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
try
|
||||
{
|
||||
var release = this.GetRelease(id);
|
||||
var release = GetRelease(id);
|
||||
if (release == null)
|
||||
{
|
||||
return Task.FromResult(new FileOperationResult<Image>(true, string.Format("Release Not Found [{0}]", id)));
|
||||
}
|
||||
return Task.FromResult(new FileOperationResult<Image>(true,
|
||||
string.Format("Release Not Found [{0}]", id)));
|
||||
byte[] imageBytes = null;
|
||||
string artistFolder = null;
|
||||
string releaseFolder = null;
|
||||
try
|
||||
{
|
||||
// See if cover art file exists in release folder
|
||||
artistFolder = release.Artist.ArtistFileFolder(this.Configuration, this.Configuration.LibraryFolder);
|
||||
artistFolder = release.Artist.ArtistFileFolder(Configuration, Configuration.LibraryFolder);
|
||||
if (!Directory.Exists(artistFolder))
|
||||
{
|
||||
this.Logger.LogWarning($"Artist Folder [{ artistFolder }], Not Found For Artist `{ release.Artist.ToString() }`");
|
||||
Logger.LogWarning($"Artist Folder [{artistFolder}], Not Found For Artist `{release.Artist}`");
|
||||
}
|
||||
else
|
||||
{
|
||||
releaseFolder = release.ReleaseFileFolder(artistFolder);
|
||||
if (!Directory.Exists(releaseFolder))
|
||||
{
|
||||
this.Logger.LogWarning($"Release Folder [{ releaseFolder }], Not Found For Release `{ release.ToString() }`");
|
||||
Logger.LogWarning($"Release Folder [{releaseFolder}], Not Found For Release `{release}`");
|
||||
}
|
||||
else
|
||||
{
|
||||
var releaseCoverFiles = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(releaseFolder), Library.Enums.ImageType.Release);
|
||||
var releaseCoverFiles =
|
||||
ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(releaseFolder),
|
||||
ImageType.Release);
|
||||
if (releaseCoverFiles.Any())
|
||||
{
|
||||
imageBytes = File.ReadAllBytes(releaseCoverFiles.First().FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex, $"Error Reading Release Folder [{ releaseFolder }] Artist Folder [{ artistFolder }] For Artist `{ release.Artist.Id }`");
|
||||
Logger.LogError(ex,
|
||||
$"Error Reading Release Folder [{releaseFolder}] Artist Folder [{artistFolder}] For Artist `{release.Artist.Id}`");
|
||||
}
|
||||
|
||||
imageBytes = imageBytes ?? release.Thumbnail;
|
||||
var image = new data.Image
|
||||
{
|
||||
|
@ -592,60 +547,60 @@ namespace Roadie.Api.Services
|
|||
CreatedDate = release.CreatedDate,
|
||||
LastUpdated = release.LastUpdated
|
||||
};
|
||||
if (release.Thumbnail == null || !release.Thumbnail.Any())
|
||||
{
|
||||
image = this.DefaultNotFoundImages.Release;
|
||||
}
|
||||
if (release.Thumbnail == null || !release.Thumbnail.Any()) image = DefaultNotFoundImages.Release;
|
||||
return Task.FromResult(GenerateFileOperationResult(id, image, etag));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError($"Error fetching Release Thumbnail [{ id }]", ex);
|
||||
Logger.LogError($"Error fetching Release Thumbnail [{id}]", ex);
|
||||
}
|
||||
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
|
||||
private Task<FileOperationResult<Image>> ReleaseSecondaryImageAction(Guid id, int imageId, EntityTagHeaderValue etag = null)
|
||||
private Task<FileOperationResult<Image>> ReleaseSecondaryImageAction(Guid id, int imageId,
|
||||
EntityTagHeaderValue etag = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var release = this.GetRelease(id);
|
||||
var release = GetRelease(id);
|
||||
if (release == null)
|
||||
{
|
||||
return Task.FromResult(new FileOperationResult<Image>(true, string.Format("Release Not Found [{0}]", id)));
|
||||
}
|
||||
return Task.FromResult(new FileOperationResult<Image>(true,
|
||||
string.Format("Release Not Found [{0}]", id)));
|
||||
byte[] imageBytes = null;
|
||||
string artistFolder = null;
|
||||
string releaseFolder = null;
|
||||
try
|
||||
{
|
||||
// See if cover art file exists in release folder
|
||||
artistFolder = release.Artist.ArtistFileFolder(this.Configuration, this.Configuration.LibraryFolder);
|
||||
artistFolder = release.Artist.ArtistFileFolder(Configuration, Configuration.LibraryFolder);
|
||||
if (!Directory.Exists(artistFolder))
|
||||
{
|
||||
this.Logger.LogWarning($"Artist Folder [{ artistFolder }], Not Found For Artist `{ release.Artist.ToString() }`");
|
||||
Logger.LogWarning($"Artist Folder [{artistFolder}], Not Found For Artist `{release.Artist}`");
|
||||
}
|
||||
else
|
||||
{
|
||||
releaseFolder = release.ReleaseFileFolder(artistFolder);
|
||||
if (!Directory.Exists(releaseFolder))
|
||||
{
|
||||
this.Logger.LogWarning($"Release Folder [{ releaseFolder }], Not Found For Release `{ release.ToString() }`");
|
||||
Logger.LogWarning($"Release Folder [{releaseFolder}], Not Found For Release `{release}`");
|
||||
}
|
||||
else
|
||||
{
|
||||
var releaseSecondaryImages = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(releaseFolder), Library.Enums.ImageType.ReleaseSecondary).ToArray();
|
||||
var releaseSecondaryImages = ImageHelper
|
||||
.FindImageTypeInDirectory(new DirectoryInfo(releaseFolder), ImageType.ReleaseSecondary)
|
||||
.ToArray();
|
||||
if (releaseSecondaryImages.Length >= imageId && releaseSecondaryImages[imageId] != null)
|
||||
{
|
||||
imageBytes = File.ReadAllBytes(releaseSecondaryImages[imageId].FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex, $"Error Reading Release Folder [{ releaseFolder }] Artist Folder [{ artistFolder }] For Artist `{ release.Artist.Id }`");
|
||||
Logger.LogError(ex,
|
||||
$"Error Reading Release Folder [{releaseFolder}] Artist Folder [{artistFolder}] For Artist `{release.Artist.Id}`");
|
||||
}
|
||||
|
||||
var image = new data.Image
|
||||
{
|
||||
Bytes = imageBytes,
|
||||
|
@ -656,26 +611,25 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError($"Error fetching Release Thumbnail [{ id }]", ex);
|
||||
Logger.LogError($"Error fetching Release Thumbnail [{id}]", ex);
|
||||
}
|
||||
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
|
||||
private async Task<FileOperationResult<Image>> TrackImageAction(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
private async Task<FileOperationResult<Image>> TrackImageAction(Guid id, int? width, int? height,
|
||||
EntityTagHeaderValue etag = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var track = this.GetTrack(id);
|
||||
var track = GetTrack(id);
|
||||
if (track == null)
|
||||
{
|
||||
return new FileOperationResult<Image>(true, string.Format("Track Not Found [{0}]", id));
|
||||
}
|
||||
var imageBytes = track.Thumbnail;
|
||||
var trackThumbnailImages = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(track.PathToTrackThumbnail(this.Configuration, this.Configuration.LibraryFolder)), Library.Enums.ImageType.Track, SearchOption.TopDirectoryOnly);
|
||||
if (trackThumbnailImages.Any())
|
||||
{
|
||||
imageBytes = File.ReadAllBytes(trackThumbnailImages.First().FullName);
|
||||
}
|
||||
var trackThumbnailImages = ImageHelper.FindImageTypeInDirectory(
|
||||
new DirectoryInfo(track.PathToTrackThumbnail(Configuration, Configuration.LibraryFolder)),
|
||||
ImageType.Track, SearchOption.TopDirectoryOnly);
|
||||
if (trackThumbnailImages.Any()) imageBytes = File.ReadAllBytes(trackThumbnailImages.First().FullName);
|
||||
var image = new data.Image
|
||||
{
|
||||
Bytes = track.Thumbnail,
|
||||
|
@ -683,16 +637,15 @@ namespace Roadie.Api.Services
|
|||
LastUpdated = track.LastUpdated
|
||||
};
|
||||
if (track.Thumbnail == null || !track.Thumbnail.Any())
|
||||
{
|
||||
// If no track image is found then return image for release
|
||||
return await this.ReleaseImage(track.ReleaseMedia.Release.RoadieId, width, height, etag);
|
||||
}
|
||||
return await ReleaseImage(track.ReleaseMedia.Release.RoadieId, width, height, etag);
|
||||
return GenerateFileOperationResult(id, image, etag);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError($"Error fetching Track Thumbnail [{ id }]", ex);
|
||||
Logger.LogError($"Error fetching Track Thumbnail [{id}]", ex);
|
||||
}
|
||||
|
||||
return new FileOperationResult<Image>(OperationMessages.ErrorOccured);
|
||||
}
|
||||
|
||||
|
@ -700,27 +653,24 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
try
|
||||
{
|
||||
var user = this.GetUser(id);
|
||||
var user = GetUser(id);
|
||||
if (user == null)
|
||||
{
|
||||
return Task.FromResult(new FileOperationResult<Image>(true, string.Format("User Not Found [{0}]", id)));
|
||||
}
|
||||
return Task.FromResult(new FileOperationResult<Image>(true,
|
||||
string.Format("User Not Found [{0}]", id)));
|
||||
var image = new data.Image
|
||||
{
|
||||
Bytes = user.Avatar,
|
||||
CreatedDate = user.CreatedDate.Value,
|
||||
LastUpdated = user.LastUpdated
|
||||
};
|
||||
if (user.Avatar == null || !user.Avatar.Any())
|
||||
{
|
||||
image = this.DefaultNotFoundImages.User;
|
||||
}
|
||||
if (user.Avatar == null || !user.Avatar.Any()) image = DefaultNotFoundImages.User;
|
||||
return Task.FromResult(GenerateFileOperationResult(id, image, etag, "image/png"));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError($"Error fetching User Thumbnail [{ id }]", ex);
|
||||
Logger.LogError($"Error fetching User Thumbnail [{id}]", ex);
|
||||
}
|
||||
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ using Roadie.Library.Extensions;
|
|||
using Roadie.Library.Imaging;
|
||||
using Roadie.Library.Models;
|
||||
using Roadie.Library.Models.Pagination;
|
||||
using Roadie.Library.Models.Statistics;
|
||||
using Roadie.Library.Models.Users;
|
||||
using Roadie.Library.Utility;
|
||||
using System;
|
||||
|
@ -26,54 +27,56 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
public class LabelService : ServiceBase, ILabelService
|
||||
{
|
||||
private IBookmarkService BookmarkService { get; } = null;
|
||||
private IBookmarkService BookmarkService { get; }
|
||||
|
||||
public LabelService(IRoadieSettings configuration,
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext context,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<LabelService> logger,
|
||||
ICollectionService collectionService,
|
||||
IPlaylistService playlistService,
|
||||
IBookmarkService bookmarkService)
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext context,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<LabelService> logger,
|
||||
ICollectionService collectionService,
|
||||
IPlaylistService playlistService,
|
||||
IBookmarkService bookmarkService)
|
||||
: base(configuration, httpEncoder, context, cacheManager, logger, httpContext)
|
||||
{
|
||||
this.BookmarkService = bookmarkService;
|
||||
BookmarkService = bookmarkService;
|
||||
}
|
||||
|
||||
public async Task<OperationResult<Label>> ById(User roadieUser, Guid id, IEnumerable<string> includes = null)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
sw.Start();
|
||||
var cacheKey = string.Format("urn:label_by_id_operation:{0}:{1}", id, includes == null ? "0" : string.Join("|", includes));
|
||||
var result = await this.CacheManager.GetAsync<OperationResult<Label>>(cacheKey, async () =>
|
||||
{
|
||||
return await this.LabelByIdAction(id, includes);
|
||||
}, data.Artist.CacheRegionUrn(id));
|
||||
var cacheKey = string.Format("urn:label_by_id_operation:{0}:{1}", id,
|
||||
includes == null ? "0" : string.Join("|", includes));
|
||||
var result = await CacheManager.GetAsync(cacheKey,
|
||||
async () => { return await LabelByIdAction(id, includes); }, data.Artist.CacheRegionUrn(id));
|
||||
sw.Stop();
|
||||
if (result?.Data != null && roadieUser != null)
|
||||
{
|
||||
var userBookmarkResult = await this.BookmarkService.List(roadieUser, new PagedRequest(), false, BookmarkType.Label);
|
||||
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.Text == result.Data.Id.ToString()) !=
|
||||
null;
|
||||
if (result.Data.Comments.Any())
|
||||
{
|
||||
var commentIds = result.Data.Comments.Select(x => x.DatabaseId).ToArray();
|
||||
var userCommentReactions = (from cr in this.DbContext.CommentReactions
|
||||
var userCommentReactions = (from cr in DbContext.CommentReactions
|
||||
where commentIds.Contains(cr.CommentId)
|
||||
where cr.UserId == roadieUser.Id
|
||||
select cr).ToArray();
|
||||
foreach (var comment in result.Data.Comments)
|
||||
{
|
||||
var userCommentReaction = userCommentReactions.FirstOrDefault(x => x.CommentId == comment.DatabaseId);
|
||||
var userCommentReaction =
|
||||
userCommentReactions.FirstOrDefault(x => x.CommentId == comment.DatabaseId);
|
||||
comment.IsDisliked = userCommentReaction?.ReactionValue == CommentReaction.Dislike;
|
||||
comment.IsLiked = userCommentReaction?.ReactionValue == CommentReaction.Like;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new OperationResult<Label>(result.Messages)
|
||||
{
|
||||
Data = result?.Data,
|
||||
|
@ -84,7 +87,8 @@ namespace Roadie.Api.Services
|
|||
};
|
||||
}
|
||||
|
||||
public Task<Library.Models.Pagination.PagedResult<LabelList>> List(User roadieUser, PagedRequest request, bool? doRandomize = false)
|
||||
public Task<Library.Models.Pagination.PagedResult<LabelList>> List(User roadieUser, PagedRequest request,
|
||||
bool? doRandomize = false)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
@ -94,30 +98,33 @@ namespace Roadie.Api.Services
|
|||
request.Sort = request.Sort.Replace("createdDate", "createdDateTime");
|
||||
request.Sort = request.Sort.Replace("lastUpdated", "lastUpdatedDateTime");
|
||||
}
|
||||
var normalizedFilterValue = !string.IsNullOrEmpty(request.FilterValue) ? request.FilterValue.ToAlphanumericName() : null;
|
||||
var result = (from l in this.DbContext.Labels
|
||||
where (request.FilterValue.Length == 0 || (request.FilterValue.Length > 0 && (
|
||||
l.Name != null && l.Name.Contains(request.FilterValue) ||
|
||||
l.AlternateNames != null && l.AlternateNames.Contains(request.FilterValue) ||
|
||||
l.AlternateNames != null && l.AlternateNames.Contains(normalizedFilterValue)
|
||||
)))
|
||||
select new LabelList
|
||||
{
|
||||
DatabaseId = l.Id,
|
||||
Id = l.RoadieId,
|
||||
Label = new DataToken
|
||||
{
|
||||
Text = l.Name,
|
||||
Value = l.RoadieId.ToString()
|
||||
},
|
||||
SortName = l.SortName,
|
||||
CreatedDate = l.CreatedDate,
|
||||
LastUpdated = l.LastUpdated,
|
||||
ArtistCount = l.ArtistCount,
|
||||
ReleaseCount = l.ReleaseCount,
|
||||
TrackCount = l.TrackCount,
|
||||
Thumbnail = this.MakeLabelThumbnailImage(l.RoadieId)
|
||||
});
|
||||
|
||||
var normalizedFilterValue = !string.IsNullOrEmpty(request.FilterValue)
|
||||
? request.FilterValue.ToAlphanumericName()
|
||||
: null;
|
||||
var result = from l in DbContext.Labels
|
||||
where request.FilterValue.Length == 0 || request.FilterValue.Length > 0 && (
|
||||
l.Name != null && l.Name.Contains(request.FilterValue) ||
|
||||
l.AlternateNames != null && l.AlternateNames.Contains(request.FilterValue) ||
|
||||
l.AlternateNames != null && l.AlternateNames.Contains(normalizedFilterValue)
|
||||
)
|
||||
select new LabelList
|
||||
{
|
||||
DatabaseId = l.Id,
|
||||
Id = l.RoadieId,
|
||||
Label = new DataToken
|
||||
{
|
||||
Text = l.Name,
|
||||
Value = l.RoadieId.ToString()
|
||||
},
|
||||
SortName = l.SortName,
|
||||
CreatedDate = l.CreatedDate,
|
||||
LastUpdated = l.LastUpdated,
|
||||
ArtistCount = l.ArtistCount,
|
||||
ReleaseCount = l.ReleaseCount,
|
||||
TrackCount = l.TrackCount,
|
||||
Thumbnail = MakeLabelThumbnailImage(l.RoadieId)
|
||||
};
|
||||
LabelList[] rows = null;
|
||||
var rowCount = result.Count();
|
||||
if (doRandomize ?? false)
|
||||
|
@ -125,17 +132,20 @@ namespace Roadie.Api.Services
|
|||
var randomLimit = roadieUser?.RandomReleaseLimit ?? 100;
|
||||
request.Limit = request.LimitValue > randomLimit ? randomLimit : request.LimitValue;
|
||||
var sql = "SELECT l.Id FROM `label` l ORDER BY RAND() LIMIT {0}";
|
||||
rows = (from rdn in this.DbContext.Labels.FromSql(sql, randomLimit)
|
||||
rows = (from rdn in DbContext.Labels.FromSql(sql, randomLimit)
|
||||
join rs in result on rdn.Id equals rs.DatabaseId
|
||||
select rs)
|
||||
.Take(request.LimitValue)
|
||||
.ToArray();
|
||||
.Take(request.LimitValue)
|
||||
.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
var sortBy = string.IsNullOrEmpty(request.Sort) ? request.OrderValue(new Dictionary<string, string> { { "SortName", "ASC" }, { "Label.Text", "ASC" } }) : request.OrderValue(null);
|
||||
var sortBy = string.IsNullOrEmpty(request.Sort)
|
||||
? request.OrderValue(new Dictionary<string, string> { { "SortName", "ASC" }, { "Label.Text", "ASC" } })
|
||||
: request.OrderValue();
|
||||
rows = result.OrderBy(sortBy).Skip(request.SkipValue).Take(request.LimitValue).ToArray();
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
return Task.FromResult(new Library.Models.Pagination.PagedResult<LabelList>
|
||||
{
|
||||
|
@ -149,7 +159,7 @@ namespace Roadie.Api.Services
|
|||
|
||||
public async Task<OperationResult<Image>> SetLabelImageByUrl(User user, Guid id, string imageUrl)
|
||||
{
|
||||
return await this.SaveImageBytes(user, id, WebHelper.BytesForImageUrl(imageUrl));
|
||||
return await SaveImageBytes(user, id, WebHelper.BytesForImageUrl(imageUrl));
|
||||
}
|
||||
|
||||
public async Task<OperationResult<bool>> UpdateLabel(User user, Label model)
|
||||
|
@ -157,11 +167,8 @@ namespace Roadie.Api.Services
|
|||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
var errors = new List<Exception>();
|
||||
var label = this.DbContext.Labels.FirstOrDefault(x => x.RoadieId == model.Id);
|
||||
if (label == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, string.Format("Label Not Found [{0}]", model.Id));
|
||||
}
|
||||
var label = DbContext.Labels.FirstOrDefault(x => x.RoadieId == model.Id);
|
||||
if (label == null) return new OperationResult<bool>(true, string.Format("Label Not Found [{0}]", model.Id));
|
||||
try
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
|
@ -185,19 +192,22 @@ namespace Roadie.Api.Services
|
|||
label.Thumbnail = ImageHelper.ConvertToJpegFormat(labelImage);
|
||||
|
||||
// Resize to store in database as thumbnail
|
||||
label.Thumbnail = ImageHelper.ResizeImage(label.Thumbnail, this.Configuration.MediumImageSize.Width, this.Configuration.MediumImageSize.Height);
|
||||
label.Thumbnail = ImageHelper.ResizeImage(label.Thumbnail, Configuration.MediumImageSize.Width,
|
||||
Configuration.MediumImageSize.Height);
|
||||
}
|
||||
label.LastUpdated = now;
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
|
||||
this.CacheManager.ClearRegion(label.CacheRegion);
|
||||
this.Logger.LogInformation($"UpdateLabel `{ label }` By User `{ user }`");
|
||||
label.LastUpdated = now;
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
CacheManager.ClearRegion(label.CacheRegion);
|
||||
Logger.LogInformation($"UpdateLabel `{label}` By User `{user}`");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex);
|
||||
Logger.LogError(ex);
|
||||
errors.Add(ex);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
|
||||
return new OperationResult<bool>
|
||||
|
@ -217,7 +227,8 @@ namespace Roadie.Api.Services
|
|||
file.CopyTo(ms);
|
||||
bytes = ms.ToArray();
|
||||
}
|
||||
return await this.SaveImageBytes(user, id, bytes);
|
||||
|
||||
return await SaveImageBytes(user, id, bytes);
|
||||
}
|
||||
|
||||
private Task<OperationResult<Label>> LabelByIdAction(Guid id, IEnumerable<string> includes = null)
|
||||
|
@ -225,38 +236,37 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
sw.Start();
|
||||
|
||||
var label = this.GetLabel(id);
|
||||
var label = GetLabel(id);
|
||||
|
||||
if (label == null)
|
||||
{
|
||||
return Task.FromResult(new OperationResult<Label>(true, string.Format("Label Not Found [{0}]", id)));
|
||||
}
|
||||
|
||||
var result = label.Adapt<Label>();
|
||||
result.AlternateNames = label.AlternateNames;
|
||||
result.Tags = label.Tags;
|
||||
result.URLs = label.URLs;
|
||||
result.Thumbnail = this.MakeLabelThumbnailImage(label.RoadieId);
|
||||
result.MediumThumbnail = base.MakeThumbnailImage(id, "label", this.Configuration.MediumImageSize.Width, this.Configuration.MediumImageSize.Height);
|
||||
result.Thumbnail = MakeLabelThumbnailImage(label.RoadieId);
|
||||
result.MediumThumbnail = MakeThumbnailImage(id, "label", Configuration.MediumImageSize.Width,
|
||||
Configuration.MediumImageSize.Height);
|
||||
if (includes != null && includes.Any())
|
||||
{
|
||||
if (includes.Contains("stats"))
|
||||
{
|
||||
var labelTracks = (from l in this.DbContext.Labels
|
||||
join rl in this.DbContext.ReleaseLabels on l.Id equals rl.LabelId into rld
|
||||
from rl in rld.DefaultIfEmpty()
|
||||
join r in this.DbContext.Releases on rl.ReleaseId equals r.Id
|
||||
join rm in this.DbContext.ReleaseMedias on r.Id equals rm.ReleaseId
|
||||
join t in this.DbContext.Tracks on rm.Id equals t.ReleaseMediaId
|
||||
where (l.Id == label.Id)
|
||||
select new
|
||||
{
|
||||
t.Duration,
|
||||
t.FileSize
|
||||
});
|
||||
var labelTracks = from l in DbContext.Labels
|
||||
join rl in DbContext.ReleaseLabels on l.Id equals rl.LabelId into rld
|
||||
from rl in rld.DefaultIfEmpty()
|
||||
join r in DbContext.Releases on rl.ReleaseId equals r.Id
|
||||
join rm in DbContext.ReleaseMedias on r.Id equals rm.ReleaseId
|
||||
join t in DbContext.Tracks on rm.Id equals t.ReleaseMediaId
|
||||
where l.Id == label.Id
|
||||
select new
|
||||
{
|
||||
t.Duration,
|
||||
t.FileSize
|
||||
};
|
||||
result.Duration = labelTracks.Sum(x => x.Duration);
|
||||
|
||||
result.Statistics = new Library.Models.Statistics.ReleaseGroupingStatistics
|
||||
result.Statistics = new ReleaseGroupingStatistics
|
||||
{
|
||||
TrackCount = label.TrackCount,
|
||||
ArtistCount = label.ArtistCount,
|
||||
|
@ -265,25 +275,31 @@ namespace Roadie.Api.Services
|
|||
FileSize = labelTracks.Sum(x => (long?)x.FileSize).ToFileSize()
|
||||
};
|
||||
}
|
||||
|
||||
if (includes.Contains("comments"))
|
||||
{
|
||||
var labelComments = this.DbContext.Comments.Include(x => x.User).Where(x => x.LabelId == label.Id).OrderByDescending(x => x.CreatedDate).ToArray();
|
||||
var labelComments = DbContext.Comments.Include(x => x.User).Where(x => x.LabelId == label.Id)
|
||||
.OrderByDescending(x => x.CreatedDate).ToArray();
|
||||
if (labelComments.Any())
|
||||
{
|
||||
var comments = new List<Comment>();
|
||||
var commentIds = labelComments.Select(x => x.Id).ToArray();
|
||||
var userCommentReactions = (from cr in this.DbContext.CommentReactions
|
||||
var userCommentReactions = (from cr in DbContext.CommentReactions
|
||||
where commentIds.Contains(cr.CommentId)
|
||||
select cr).ToArray();
|
||||
foreach (var labelComment in labelComments)
|
||||
{
|
||||
var comment = labelComment.Adapt<Comment>();
|
||||
comment.DatabaseId = labelComment.Id;
|
||||
comment.User = UserList.FromDataUser(labelComment.User, this.MakeUserThumbnailImage(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);
|
||||
comment.User = UserList.FromDataUser(labelComment.User,
|
||||
MakeUserThumbnailImage(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);
|
||||
}
|
||||
|
||||
result.Comments = comments;
|
||||
}
|
||||
}
|
||||
|
@ -298,16 +314,13 @@ namespace Roadie.Api.Services
|
|||
});
|
||||
}
|
||||
|
||||
private async Task<OperationResult<Library.Models.Image>> SaveImageBytes(User user, Guid id, byte[] imageBytes)
|
||||
private async Task<OperationResult<Image>> SaveImageBytes(User user, Guid id, byte[] imageBytes)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
var errors = new List<Exception>();
|
||||
var label = this.DbContext.Labels.FirstOrDefault(x => x.RoadieId == id);
|
||||
if (label == null)
|
||||
{
|
||||
return new OperationResult<Library.Models.Image>(true, string.Format("Label Not Found [{0}]", id));
|
||||
}
|
||||
var label = DbContext.Labels.FirstOrDefault(x => x.RoadieId == id);
|
||||
if (label == null) return new OperationResult<Image>(true, string.Format("Label Not Found [{0}]", id));
|
||||
try
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
|
@ -318,24 +331,28 @@ namespace Roadie.Api.Services
|
|||
label.Thumbnail = ImageHelper.ConvertToJpegFormat(label.Thumbnail);
|
||||
|
||||
// Resize to store in database as thumbnail
|
||||
label.Thumbnail = ImageHelper.ResizeImage(label.Thumbnail, this.Configuration.MediumImageSize.Width, this.Configuration.MediumImageSize.Height);
|
||||
label.Thumbnail = ImageHelper.ResizeImage(label.Thumbnail, Configuration.MediumImageSize.Width,
|
||||
Configuration.MediumImageSize.Height);
|
||||
}
|
||||
|
||||
label.LastUpdated = now;
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
this.CacheManager.ClearRegion(label.CacheRegion);
|
||||
this.Logger.LogInformation($"UploadLabelImage `{ label }` By User `{ user }`");
|
||||
await DbContext.SaveChangesAsync();
|
||||
CacheManager.ClearRegion(label.CacheRegion);
|
||||
Logger.LogInformation($"UploadLabelImage `{label}` By User `{user}`");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex);
|
||||
Logger.LogError(ex);
|
||||
errors.Add(ex);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
|
||||
return new OperationResult<Library.Models.Image>
|
||||
return new OperationResult<Image>
|
||||
{
|
||||
IsSuccess = !errors.Any(),
|
||||
Data = base.MakeThumbnailImage(id, "label", this.Configuration.MediumImageSize.Width, this.Configuration.MediumImageSize.Height, true),
|
||||
Data = MakeThumbnailImage(id, "label", Configuration.MediumImageSize.Width,
|
||||
Configuration.MediumImageSize.Height, true),
|
||||
OperationTime = sw.ElapsedMilliseconds,
|
||||
Errors = errors
|
||||
};
|
||||
|
|
|
@ -3,6 +3,7 @@ using Roadie.Library;
|
|||
using Roadie.Library.Caching;
|
||||
using Roadie.Library.Configuration;
|
||||
using Roadie.Library.Encoding;
|
||||
using Roadie.Library.Enums;
|
||||
using Roadie.Library.Models;
|
||||
using Roadie.Library.Utility;
|
||||
using System;
|
||||
|
@ -15,16 +16,16 @@ using data = Roadie.Library.Data;
|
|||
namespace Roadie.Api.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns lookups (or dictionaries) of various allowable values for a given Type
|
||||
/// Returns lookups (or dictionaries) of various allowable values for a given Type
|
||||
/// </summary>
|
||||
public class LookupService : ServiceBase, ILookupService
|
||||
{
|
||||
public LookupService(IRoadieSettings configuration,
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext dbContext,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<PlaylistService> logger)
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext dbContext,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<PlaylistService> logger)
|
||||
: base(configuration, httpEncoder, dbContext, cacheManager, logger, httpContext)
|
||||
{
|
||||
}
|
||||
|
@ -34,7 +35,7 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
return Task.FromResult(new OperationResult<IEnumerable<DataToken>>
|
||||
{
|
||||
Data = this.EnumToDataTokens(typeof(Roadie.Library.Enums.ArtistType)),
|
||||
Data = EnumToDataTokens(typeof(ArtistType)),
|
||||
IsSuccess = true,
|
||||
OperationTime = sw.ElapsedMilliseconds
|
||||
});
|
||||
|
@ -45,7 +46,7 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
return Task.FromResult(new OperationResult<IEnumerable<DataToken>>
|
||||
{
|
||||
Data = this.EnumToDataTokens(typeof(Roadie.Library.Enums.BandStatus)),
|
||||
Data = EnumToDataTokens(typeof(BandStatus)),
|
||||
IsSuccess = true,
|
||||
OperationTime = sw.ElapsedMilliseconds
|
||||
});
|
||||
|
@ -56,7 +57,7 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
return Task.FromResult(new OperationResult<IEnumerable<DataToken>>
|
||||
{
|
||||
Data = this.EnumToDataTokens(typeof(Roadie.Library.Enums.BookmarkType)),
|
||||
Data = EnumToDataTokens(typeof(BookmarkType)),
|
||||
IsSuccess = true,
|
||||
OperationTime = sw.ElapsedMilliseconds
|
||||
});
|
||||
|
@ -67,7 +68,7 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
return Task.FromResult(new OperationResult<IEnumerable<DataToken>>
|
||||
{
|
||||
Data = this.EnumToDataTokens(typeof(Roadie.Library.Enums.CollectionType)),
|
||||
Data = EnumToDataTokens(typeof(CollectionType)),
|
||||
IsSuccess = true,
|
||||
OperationTime = sw.ElapsedMilliseconds
|
||||
});
|
||||
|
@ -78,7 +79,7 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
return Task.FromResult(new OperationResult<IEnumerable<DataToken>>
|
||||
{
|
||||
Data = this.EnumToDataTokens(typeof(Roadie.Library.Enums.LibraryStatus)),
|
||||
Data = EnumToDataTokens(typeof(LibraryStatus)),
|
||||
IsSuccess = true,
|
||||
OperationTime = sw.ElapsedMilliseconds
|
||||
});
|
||||
|
@ -89,7 +90,7 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
return Task.FromResult(new OperationResult<IEnumerable<DataToken>>
|
||||
{
|
||||
Data = this.EnumToDataTokens(typeof(Roadie.Library.Enums.QueMessageType)),
|
||||
Data = EnumToDataTokens(typeof(QueMessageType)),
|
||||
IsSuccess = true,
|
||||
OperationTime = sw.ElapsedMilliseconds
|
||||
});
|
||||
|
@ -100,7 +101,7 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
return Task.FromResult(new OperationResult<IEnumerable<DataToken>>
|
||||
{
|
||||
Data = this.EnumToDataTokens(typeof(Roadie.Library.Enums.ReleaseType)),
|
||||
Data = EnumToDataTokens(typeof(ReleaseType)),
|
||||
IsSuccess = true,
|
||||
OperationTime = sw.ElapsedMilliseconds
|
||||
});
|
||||
|
@ -111,7 +112,7 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
return Task.FromResult(new OperationResult<IEnumerable<DataToken>>
|
||||
{
|
||||
Data = this.EnumToDataTokens(typeof(Roadie.Library.Enums.RequestStatus)),
|
||||
Data = EnumToDataTokens(typeof(RequestStatus)),
|
||||
IsSuccess = true,
|
||||
OperationTime = sw.ElapsedMilliseconds
|
||||
});
|
||||
|
@ -122,7 +123,7 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
return Task.FromResult(new OperationResult<IEnumerable<DataToken>>
|
||||
{
|
||||
Data = this.EnumToDataTokens(typeof(Roadie.Library.Enums.Statuses)),
|
||||
Data = EnumToDataTokens(typeof(Statuses)),
|
||||
IsSuccess = true,
|
||||
OperationTime = sw.ElapsedMilliseconds
|
||||
});
|
||||
|
@ -132,13 +133,11 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
var result = new List<DataToken>();
|
||||
foreach (var ls in Enum.GetValues(ee))
|
||||
{
|
||||
result.Add(new DataToken
|
||||
{
|
||||
Text = ls.ToString(),
|
||||
Value = ((short)ls).ToString()
|
||||
});
|
||||
}
|
||||
return result.OrderBy(x => x.Text);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,89 +23,99 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
public class PlayActivityService : ServiceBase, IPlayActivityService
|
||||
{
|
||||
protected IScrobbleHandler ScrobblerHandler { get; }
|
||||
protected IHubContext<PlayActivityHub> PlayActivityHub { get; }
|
||||
|
||||
protected IScrobbleHandler ScrobblerHandler { get; }
|
||||
|
||||
public PlayActivityService(IRoadieSettings configuration,
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext dbContext,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<PlayActivityService> logger,
|
||||
IScrobbleHandler scrobbleHandler,
|
||||
IHubContext<PlayActivityHub> playActivityHub)
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext dbContext,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<PlayActivityService> logger,
|
||||
IScrobbleHandler scrobbleHandler,
|
||||
IHubContext<PlayActivityHub> playActivityHub)
|
||||
: base(configuration, httpEncoder, dbContext, cacheManager, logger, httpContext)
|
||||
{
|
||||
this.PlayActivityHub = playActivityHub;
|
||||
this.ScrobblerHandler = scrobbleHandler;
|
||||
PlayActivityHub = playActivityHub;
|
||||
ScrobblerHandler = scrobbleHandler;
|
||||
}
|
||||
|
||||
public Task<Library.Models.Pagination.PagedResult<PlayActivityList>> List(PagedRequest request, User roadieUser = null, DateTime? newerThan = null)
|
||||
public Task<Library.Models.Pagination.PagedResult<PlayActivityList>> List(PagedRequest request,
|
||||
User roadieUser = null, DateTime? newerThan = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
var result = (from t in this.DbContext.Tracks
|
||||
join rm in this.DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id
|
||||
join r in this.DbContext.Releases on rm.ReleaseId equals r.Id
|
||||
join trackArtist in this.DbContext.Artists on t.ArtistId equals trackArtist.Id into tas
|
||||
from trackArtist in tas.DefaultIfEmpty()
|
||||
join usertrack in this.DbContext.UserTracks on t.Id equals usertrack.TrackId
|
||||
join u in this.DbContext.Users on usertrack.UserId equals u.Id
|
||||
join releaseArtist in this.DbContext.Artists on r.ArtistId equals releaseArtist.Id
|
||||
where (newerThan == null || usertrack.LastPlayed >= newerThan)
|
||||
where ((roadieUser == null && !(u.IsPrivate ?? false)) || (roadieUser != null && (usertrack != null && usertrack.User.Id == roadieUser.Id)))
|
||||
where (!request.FilterRatedOnly || (roadieUser == null && t.Rating > 0 || roadieUser != null && usertrack.Rating >0))
|
||||
where (request.FilterValue.Length == 0 || (request.FilterValue.Length > 0 && (
|
||||
t.Title != null && t.Title.ToLower().Contains(request.Filter.ToLower()) ||
|
||||
t.AlternateNames != null && t.AlternateNames.ToLower().Contains(request.Filter.ToLower())
|
||||
)))
|
||||
select new PlayActivityList
|
||||
{
|
||||
Release = new DataToken
|
||||
{
|
||||
Text = r.Title,
|
||||
Value = r.RoadieId.ToString()
|
||||
},
|
||||
Track = TrackList.FromDataTrack(null,
|
||||
t,
|
||||
rm.MediaNumber,
|
||||
r,
|
||||
releaseArtist,
|
||||
trackArtist,
|
||||
this.HttpContext.BaseUrl,
|
||||
this.MakeTrackThumbnailImage(t.RoadieId),
|
||||
this.MakeReleaseThumbnailImage(r.RoadieId),
|
||||
this.MakeArtistThumbnailImage(releaseArtist.RoadieId),
|
||||
this.MakeArtistThumbnailImage(trackArtist == null ? null : (Guid?)trackArtist.RoadieId)),
|
||||
User = new DataToken
|
||||
{
|
||||
Text = u.UserName,
|
||||
Value = u.RoadieId.ToString()
|
||||
},
|
||||
Artist = new DataToken
|
||||
{
|
||||
Text = releaseArtist.Name,
|
||||
Value = releaseArtist.RoadieId.ToString()
|
||||
},
|
||||
TrackArtist = trackArtist == null ? null : new DataToken
|
||||
{
|
||||
Text = trackArtist.Name,
|
||||
Value = trackArtist.RoadieId.ToString()
|
||||
},
|
||||
PlayedDateDateTime = usertrack.LastPlayed,
|
||||
ReleasePlayUrl = $"{ this.HttpContext.BaseUrl }/play/release/{ r.RoadieId}",
|
||||
Rating = t.Rating,
|
||||
UserRating = usertrack.Rating,
|
||||
TrackPlayUrl = $"{ this.HttpContext.BaseUrl }/play/track/{ t.RoadieId}.mp3",
|
||||
ArtistThumbnail = this.MakeArtistThumbnailImage(trackArtist != null ? trackArtist.RoadieId : releaseArtist.RoadieId),
|
||||
ReleaseThumbnail = this.MakeReleaseThumbnailImage(r.RoadieId),
|
||||
UserThumbnail = this.MakeUserThumbnailImage(u.RoadieId)
|
||||
});
|
||||
var result = from t in DbContext.Tracks
|
||||
join rm in DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id
|
||||
join r in DbContext.Releases on rm.ReleaseId equals r.Id
|
||||
join trackArtist in DbContext.Artists on t.ArtistId equals trackArtist.Id into tas
|
||||
from trackArtist in tas.DefaultIfEmpty()
|
||||
join usertrack in DbContext.UserTracks on t.Id equals usertrack.TrackId
|
||||
join u in DbContext.Users on usertrack.UserId equals u.Id
|
||||
join releaseArtist in DbContext.Artists on r.ArtistId equals releaseArtist.Id
|
||||
where newerThan == null || usertrack.LastPlayed >= newerThan
|
||||
where roadieUser == null && !(u.IsPrivate ?? false) || roadieUser != null && usertrack != null &&
|
||||
usertrack.User.Id == roadieUser.Id
|
||||
where !request.FilterRatedOnly || roadieUser == null && t.Rating > 0 ||
|
||||
roadieUser != null && usertrack.Rating > 0
|
||||
where request.FilterValue.Length == 0 || request.FilterValue.Length > 0 && (
|
||||
t.Title != null && t.Title.ToLower().Contains(request.Filter.ToLower()) ||
|
||||
t.AlternateNames != null && t.AlternateNames.ToLower().Contains(request.Filter.ToLower())
|
||||
)
|
||||
select new PlayActivityList
|
||||
{
|
||||
Release = new DataToken
|
||||
{
|
||||
Text = r.Title,
|
||||
Value = r.RoadieId.ToString()
|
||||
},
|
||||
Track = TrackList.FromDataTrack(null,
|
||||
t,
|
||||
rm.MediaNumber,
|
||||
r,
|
||||
releaseArtist,
|
||||
trackArtist,
|
||||
HttpContext.BaseUrl,
|
||||
MakeTrackThumbnailImage(t.RoadieId),
|
||||
MakeReleaseThumbnailImage(r.RoadieId),
|
||||
MakeArtistThumbnailImage(releaseArtist.RoadieId),
|
||||
MakeArtistThumbnailImage(trackArtist == null ? null : (Guid?)trackArtist.RoadieId)),
|
||||
User = new DataToken
|
||||
{
|
||||
Text = u.UserName,
|
||||
Value = u.RoadieId.ToString()
|
||||
},
|
||||
Artist = new DataToken
|
||||
{
|
||||
Text = releaseArtist.Name,
|
||||
Value = releaseArtist.RoadieId.ToString()
|
||||
},
|
||||
TrackArtist = trackArtist == null
|
||||
? null
|
||||
: new DataToken
|
||||
{
|
||||
Text = trackArtist.Name,
|
||||
Value = trackArtist.RoadieId.ToString()
|
||||
},
|
||||
PlayedDateDateTime = usertrack.LastPlayed,
|
||||
ReleasePlayUrl = $"{HttpContext.BaseUrl}/play/release/{r.RoadieId}",
|
||||
Rating = t.Rating,
|
||||
UserRating = usertrack.Rating,
|
||||
TrackPlayUrl = $"{HttpContext.BaseUrl}/play/track/{t.RoadieId}.mp3",
|
||||
ArtistThumbnail =
|
||||
MakeArtistThumbnailImage(
|
||||
trackArtist != null ? trackArtist.RoadieId : releaseArtist.RoadieId),
|
||||
ReleaseThumbnail = MakeReleaseThumbnailImage(r.RoadieId),
|
||||
UserThumbnail = MakeUserThumbnailImage(u.RoadieId)
|
||||
};
|
||||
|
||||
var sortBy = string.IsNullOrEmpty(request.Sort) ? request.OrderValue(new Dictionary<string, string> { { "PlayedDateDateTime", "DESC" } }) : request.OrderValue(null);
|
||||
var sortBy = string.IsNullOrEmpty(request.Sort)
|
||||
? request.OrderValue(new Dictionary<string, string> { { "PlayedDateDateTime", "DESC" } })
|
||||
: request.OrderValue();
|
||||
var rowCount = result.Count();
|
||||
var rows = result.OrderBy(sortBy).Skip(request.SkipValue).Take(request.LimitValue).ToArray();
|
||||
sw.Stop();
|
||||
|
@ -120,48 +130,44 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex);
|
||||
Logger.LogError(ex);
|
||||
}
|
||||
|
||||
return Task.FromResult(new Library.Models.Pagination.PagedResult<PlayActivityList>());
|
||||
}
|
||||
|
||||
public async Task<OperationResult<bool>> NowPlaying(User roadieUser, ScrobbleInfo scrobble)
|
||||
{
|
||||
var scrobbleResult = await this.ScrobblerHandler.NowPlaying(roadieUser, scrobble);
|
||||
if (!scrobbleResult.IsSuccess)
|
||||
{
|
||||
return scrobbleResult;
|
||||
}
|
||||
var scrobbleResult = await ScrobblerHandler.NowPlaying(roadieUser, scrobble);
|
||||
if (!scrobbleResult.IsSuccess) return scrobbleResult;
|
||||
await PublishPlayActivity(roadieUser, scrobble, true);
|
||||
return scrobbleResult;
|
||||
}
|
||||
|
||||
public async Task<OperationResult<bool>> Scrobble(User roadieUser, ScrobbleInfo scrobble)
|
||||
{
|
||||
var scrobbleResult = await this.ScrobblerHandler.Scrobble(roadieUser, scrobble);
|
||||
if(!scrobbleResult.IsSuccess)
|
||||
{
|
||||
return scrobbleResult;
|
||||
}
|
||||
var scrobbleResult = await ScrobblerHandler.Scrobble(roadieUser, scrobble);
|
||||
if (!scrobbleResult.IsSuccess) return scrobbleResult;
|
||||
await PublishPlayActivity(roadieUser, scrobble, false);
|
||||
return scrobbleResult;
|
||||
}
|
||||
|
||||
private async Task PublishPlayActivity(User roadieUser, ScrobbleInfo scrobble, bool isNowPlaying)
|
||||
{
|
||||
// Only broadcast if the user is not public and played duration is more than half of duration
|
||||
if (!roadieUser.IsPrivate &&
|
||||
scrobble.ElapsedTimeOfTrackPlayed.TotalSeconds > (scrobble.TrackDuration.TotalSeconds / 2))
|
||||
{
|
||||
// Only broadcast if the user is not public and played duration is more than half of duration
|
||||
if (!roadieUser.IsPrivate &&
|
||||
scrobble.ElapsedTimeOfTrackPlayed.TotalSeconds > scrobble.TrackDuration.TotalSeconds / 2)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
var track = this.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 == scrobble.TrackId);
|
||||
var user = this.DbContext.Users.FirstOrDefault(x => x.RoadieId == roadieUser.UserId);
|
||||
var userTrack = this.DbContext.UserTracks.FirstOrDefault(x => x.UserId == roadieUser.Id && x.TrackId == track.Id);
|
||||
var track = 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 == scrobble.TrackId);
|
||||
var user = DbContext.Users.FirstOrDefault(x => x.RoadieId == roadieUser.UserId);
|
||||
var userTrack =
|
||||
DbContext.UserTracks.FirstOrDefault(x => x.UserId == roadieUser.Id && x.TrackId == track.Id);
|
||||
var pl = new PlayActivityList
|
||||
{
|
||||
Artist = new DataToken
|
||||
|
@ -169,49 +175,55 @@ namespace Roadie.Api.Services
|
|||
Text = track.ReleaseMedia.Release.Artist.Name,
|
||||
Value = track.ReleaseMedia.Release.Artist.RoadieId.ToString()
|
||||
},
|
||||
TrackArtist = track.TrackArtist == null ? null : new DataToken
|
||||
{
|
||||
Text = track.TrackArtist.Name,
|
||||
Value = track.TrackArtist.RoadieId.ToString()
|
||||
},
|
||||
TrackArtist = track.TrackArtist == null
|
||||
? null
|
||||
: new DataToken
|
||||
{
|
||||
Text = track.TrackArtist.Name,
|
||||
Value = track.TrackArtist.RoadieId.ToString()
|
||||
},
|
||||
Release = new DataToken
|
||||
{
|
||||
Text = track.ReleaseMedia.Release.Title,
|
||||
Value = track.ReleaseMedia.Release.RoadieId.ToString()
|
||||
},
|
||||
Track = TrackList.FromDataTrack(null,
|
||||
track,
|
||||
track.ReleaseMedia.MediaNumber,
|
||||
track.ReleaseMedia.Release,
|
||||
track.ReleaseMedia.Release.Artist,
|
||||
track.TrackArtist,
|
||||
this.HttpContext.BaseUrl,
|
||||
this.MakeTrackThumbnailImage(track.RoadieId),
|
||||
this.MakeReleaseThumbnailImage(track.ReleaseMedia.Release.RoadieId),
|
||||
this.MakeArtistThumbnailImage(track.ReleaseMedia.Release.Artist.RoadieId),
|
||||
this.MakeArtistThumbnailImage(track.TrackArtist == null ? null : (Guid?)track.TrackArtist.RoadieId)),
|
||||
track,
|
||||
track.ReleaseMedia.MediaNumber,
|
||||
track.ReleaseMedia.Release,
|
||||
track.ReleaseMedia.Release.Artist,
|
||||
track.TrackArtist,
|
||||
HttpContext.BaseUrl,
|
||||
MakeTrackThumbnailImage(track.RoadieId),
|
||||
MakeReleaseThumbnailImage(track.ReleaseMedia.Release.RoadieId),
|
||||
MakeArtistThumbnailImage(track.ReleaseMedia.Release.Artist.RoadieId),
|
||||
MakeArtistThumbnailImage(track.TrackArtist == null
|
||||
? null
|
||||
: (Guid?)track.TrackArtist.RoadieId)),
|
||||
User = new DataToken
|
||||
{
|
||||
Text = roadieUser.UserName,
|
||||
Value = roadieUser.UserId.ToString()
|
||||
},
|
||||
ArtistThumbnail = this.MakeArtistThumbnailImage(track.TrackArtist != null ? track.TrackArtist.RoadieId : track.ReleaseMedia.Release.Artist.RoadieId),
|
||||
ArtistThumbnail = MakeArtistThumbnailImage(track.TrackArtist != null
|
||||
? track.TrackArtist.RoadieId
|
||||
: track.ReleaseMedia.Release.Artist.RoadieId),
|
||||
PlayedDateDateTime = scrobble.TimePlayed,
|
||||
IsNowPlaying = isNowPlaying,
|
||||
Rating = track.Rating,
|
||||
ReleasePlayUrl = $"{ this.HttpContext.BaseUrl }/play/release/{ track.ReleaseMedia.Release.RoadieId}",
|
||||
ReleaseThumbnail = this.MakeReleaseThumbnailImage(track.ReleaseMedia.Release.RoadieId),
|
||||
TrackPlayUrl = $"{ this.HttpContext.BaseUrl }/play/track/{ track.RoadieId}.mp3",
|
||||
ReleasePlayUrl = $"{HttpContext.BaseUrl}/play/release/{track.ReleaseMedia.Release.RoadieId}",
|
||||
ReleaseThumbnail = MakeReleaseThumbnailImage(track.ReleaseMedia.Release.RoadieId),
|
||||
TrackPlayUrl = $"{HttpContext.BaseUrl}/play/track/{track.RoadieId}.mp3",
|
||||
UserRating = userTrack?.Rating,
|
||||
UserThumbnail = this.MakeUserThumbnailImage(roadieUser.UserId)
|
||||
UserThumbnail = MakeUserThumbnailImage(roadieUser.UserId)
|
||||
};
|
||||
try
|
||||
{
|
||||
await this.PlayActivityHub.Clients.All.SendAsync("SendActivity", pl);
|
||||
await PlayActivityHub.Clients.All.SendAsync("SendActivity", pl);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex);
|
||||
Logger.LogError(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ using Roadie.Library.Imaging;
|
|||
using Roadie.Library.Models;
|
||||
using Roadie.Library.Models.Pagination;
|
||||
using Roadie.Library.Models.Playlists;
|
||||
using Roadie.Library.Models.Statistics;
|
||||
using Roadie.Library.Models.Users;
|
||||
using Roadie.Library.Utility;
|
||||
using System;
|
||||
|
@ -25,18 +26,18 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
public class PlaylistService : ServiceBase, IPlaylistService
|
||||
{
|
||||
private IBookmarkService BookmarkService { get; } = null;
|
||||
private IBookmarkService BookmarkService { get; }
|
||||
|
||||
public PlaylistService(IRoadieSettings configuration,
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext dbContext,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<PlaylistService> logger,
|
||||
IBookmarkService bookmarkService)
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext dbContext,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<PlaylistService> logger,
|
||||
IBookmarkService bookmarkService)
|
||||
: base(configuration, httpEncoder, dbContext, cacheManager, logger, httpContext)
|
||||
{
|
||||
this.BookmarkService = bookmarkService;
|
||||
BookmarkService = bookmarkService;
|
||||
}
|
||||
|
||||
public async Task<OperationResult<PlaylistList>> AddNewPlaylist(User user, Playlist model)
|
||||
|
@ -48,14 +49,15 @@ namespace Roadie.Api.Services
|
|||
Name = model.Name,
|
||||
UserId = user.Id
|
||||
};
|
||||
this.DbContext.Playlists.Add(playlist);
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
var r = await this.AddTracksToPlaylist(playlist, model.Tracks.OrderBy(x => x.ListNumber).Select(x => x.Track.Id));
|
||||
DbContext.Playlists.Add(playlist);
|
||||
await DbContext.SaveChangesAsync();
|
||||
var r = await AddTracksToPlaylist(playlist,
|
||||
model.Tracks.OrderBy(x => x.ListNumber).Select(x => x.Track.Id));
|
||||
var request = new PagedRequest
|
||||
{
|
||||
FilterToPlaylistId = playlist.RoadieId
|
||||
};
|
||||
var result = await this.List(request, user);
|
||||
var result = await List(request, user);
|
||||
return new OperationResult<PlaylistList>
|
||||
{
|
||||
Data = result.Rows.First(),
|
||||
|
@ -71,30 +73,28 @@ namespace Roadie.Api.Services
|
|||
var result = false;
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
var existingTracksForPlaylist = (from plt in this.DbContext.PlaylistTracks
|
||||
join t in this.DbContext.Tracks on plt.TrackId equals t.Id
|
||||
where plt.PlayListId == playlist.Id
|
||||
select t);
|
||||
var newTracksForPlaylist = (from t in this.DbContext.Tracks
|
||||
var existingTracksForPlaylist = from plt in DbContext.PlaylistTracks
|
||||
join t in DbContext.Tracks on plt.TrackId equals t.Id
|
||||
where plt.PlayListId == playlist.Id
|
||||
select t;
|
||||
var newTracksForPlaylist = (from t in DbContext.Tracks
|
||||
where (from x in trackIds select x).Contains(t.RoadieId)
|
||||
where !(from x in existingTracksForPlaylist select x.RoadieId).Contains(t.RoadieId)
|
||||
select t).ToArray();
|
||||
foreach (var newTrackForPlaylist in newTracksForPlaylist)
|
||||
{
|
||||
this.DbContext.PlaylistTracks.Add(new data.PlaylistTrack
|
||||
DbContext.PlaylistTracks.Add(new data.PlaylistTrack
|
||||
{
|
||||
TrackId = newTrackForPlaylist.Id,
|
||||
PlayListId = playlist.Id
|
||||
});
|
||||
}
|
||||
playlist.LastUpdated = now;
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
await DbContext.SaveChangesAsync();
|
||||
result = true;
|
||||
|
||||
var r = await this.ReorderPlaylist(playlist);
|
||||
var r = await ReorderPlaylist(playlist);
|
||||
result = result && r.IsSuccess;
|
||||
|
||||
await base.UpdatePlaylistCounts(playlist.Id, now);
|
||||
await UpdatePlaylistCounts(playlist.Id, now);
|
||||
|
||||
sw.Stop();
|
||||
|
||||
|
@ -110,46 +110,45 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
sw.Start();
|
||||
var cacheKey = string.Format("urn:playlist_by_id_operation:{0}:{1}", id, includes == null ? "0" : string.Join("|", includes));
|
||||
var result = await this.CacheManager.GetAsync<OperationResult<Playlist>>(cacheKey, async () =>
|
||||
{
|
||||
return await this.PlaylistByIdAction(id, includes);
|
||||
}, data.Artist.CacheRegionUrn(id));
|
||||
var cacheKey = string.Format("urn:playlist_by_id_operation:{0}:{1}", id,
|
||||
includes == null ? "0" : string.Join("|", includes));
|
||||
var result = await CacheManager.GetAsync(cacheKey,
|
||||
async () => { return await PlaylistByIdAction(id, includes); }, data.Artist.CacheRegionUrn(id));
|
||||
sw.Stop();
|
||||
if (result?.Data != null && roadieUser != null)
|
||||
{
|
||||
if (result?.Data?.Tracks != null)
|
||||
{
|
||||
var user = this.GetUser(roadieUser.UserId);
|
||||
var user = GetUser(roadieUser.UserId);
|
||||
foreach (var track in result.Data.Tracks)
|
||||
{
|
||||
track.Track.TrackPlayUrl = this.MakeTrackPlayUrl(user, track.Track.DatabaseId, track.Track.Id);
|
||||
}
|
||||
track.Track.TrackPlayUrl = MakeTrackPlayUrl(user, track.Track.DatabaseId, track.Track.Id);
|
||||
}
|
||||
|
||||
result.Data.UserCanEdit = result.Data.Maintainer.Id == roadieUser.UserId || roadieUser.IsAdmin;
|
||||
var userBookmarkResult = await this.BookmarkService.List(roadieUser, new PagedRequest(), false, BookmarkType.Playlist);
|
||||
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.Text == result.Data.Id.ToString()) !=
|
||||
null;
|
||||
|
||||
if (result.Data.Comments.Any())
|
||||
{
|
||||
var commentIds = result.Data.Comments.Select(x => x.DatabaseId).ToArray();
|
||||
var userCommentReactions = (from cr in this.DbContext.CommentReactions
|
||||
var userCommentReactions = (from cr in DbContext.CommentReactions
|
||||
where commentIds.Contains(cr.CommentId)
|
||||
where cr.UserId == roadieUser.Id
|
||||
select cr).ToArray();
|
||||
foreach (var comment in result.Data.Comments)
|
||||
{
|
||||
var userCommentReaction = userCommentReactions.FirstOrDefault(x => x.CommentId == comment.DatabaseId);
|
||||
var userCommentReaction =
|
||||
userCommentReactions.FirstOrDefault(x => x.CommentId == comment.DatabaseId);
|
||||
comment.IsDisliked = userCommentReaction?.ReactionValue == CommentReaction.Dislike;
|
||||
comment.IsLiked = userCommentReaction?.ReactionValue == CommentReaction.Like;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return new OperationResult<Playlist>(result.Messages)
|
||||
{
|
||||
Data = result?.Data,
|
||||
|
@ -164,23 +163,21 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
var playlist = this.DbContext.Playlists.FirstOrDefault(x => x.RoadieId == id);
|
||||
if (playlist == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, string.Format("Playlist Not Found [{0}]", id));
|
||||
}
|
||||
var playlist = DbContext.Playlists.FirstOrDefault(x => x.RoadieId == id);
|
||||
if (playlist == null) return new OperationResult<bool>(true, string.Format("Playlist Not Found [{0}]", id));
|
||||
if (!user.IsAdmin && user.Id != playlist.UserId)
|
||||
{
|
||||
this.Logger.LogWarning("User `{0}` attempted to delete Playlist `{1}`", user, playlist);
|
||||
Logger.LogWarning("User `{0}` attempted to delete Playlist `{1}`", user, playlist);
|
||||
return new OperationResult<bool>("Access Denied")
|
||||
{
|
||||
IsAccessDeniedResult = true
|
||||
};
|
||||
}
|
||||
this.DbContext.Playlists.Remove(playlist);
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
this.Logger.LogInformation("User `{0}` deleted Playlist `{1}]`", user, playlist);
|
||||
this.CacheManager.ClearRegion(playlist.CacheRegion);
|
||||
|
||||
DbContext.Playlists.Remove(playlist);
|
||||
await DbContext.SaveChangesAsync();
|
||||
Logger.LogInformation("User `{0}` deleted Playlist `{1}]`", user, playlist);
|
||||
CacheManager.ClearRegion(playlist.CacheRegion);
|
||||
sw.Stop();
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
|
@ -190,46 +187,48 @@ namespace Roadie.Api.Services
|
|||
};
|
||||
}
|
||||
|
||||
public Task<Library.Models.Pagination.PagedResult<PlaylistList>> List(PagedRequest request, User roadieUser = null)
|
||||
public Task<Library.Models.Pagination.PagedResult<PlaylistList>> List(PagedRequest request,
|
||||
User roadieUser = null)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
int[] playlistWithArtistTrackIds = new int[0];
|
||||
var playlistWithArtistTrackIds = new int[0];
|
||||
if (request.FilterToArtistId.HasValue)
|
||||
{
|
||||
playlistWithArtistTrackIds = (from pl in this.DbContext.Playlists
|
||||
join pltr in this.DbContext.PlaylistTracks on pl.Id equals pltr.PlayListId
|
||||
join t in this.DbContext.Tracks on pltr.TrackId equals t.Id
|
||||
join rm in this.DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id
|
||||
join r in this.DbContext.Releases on rm.ReleaseId equals r.Id
|
||||
join a in this.DbContext.Artists on r.ArtistId equals a.Id
|
||||
playlistWithArtistTrackIds = (from pl in DbContext.Playlists
|
||||
join pltr in DbContext.PlaylistTracks on pl.Id equals pltr.PlayListId
|
||||
join t in DbContext.Tracks on pltr.TrackId equals t.Id
|
||||
join rm in DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id
|
||||
join r in DbContext.Releases on rm.ReleaseId equals r.Id
|
||||
join a in DbContext.Artists on r.ArtistId equals a.Id
|
||||
where a.RoadieId == request.FilterToArtistId
|
||||
select pl.Id
|
||||
).ToArray();
|
||||
}
|
||||
int[] playlistReleaseTrackIds = new int[0];
|
||||
).ToArray();
|
||||
var playlistReleaseTrackIds = new int[0];
|
||||
if (request.FilterToReleaseId.HasValue)
|
||||
{
|
||||
playlistReleaseTrackIds = (from pl in this.DbContext.Playlists
|
||||
join pltr in this.DbContext.PlaylistTracks on pl.Id equals pltr.PlayListId
|
||||
join t in this.DbContext.Tracks on pltr.TrackId equals t.Id
|
||||
join rm in this.DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id
|
||||
join r in this.DbContext.Releases on rm.ReleaseId equals r.Id
|
||||
playlistReleaseTrackIds = (from pl in DbContext.Playlists
|
||||
join pltr in DbContext.PlaylistTracks on pl.Id equals pltr.PlayListId
|
||||
join t in DbContext.Tracks on pltr.TrackId equals t.Id
|
||||
join rm in DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id
|
||||
join r in DbContext.Releases on rm.ReleaseId equals r.Id
|
||||
where r.RoadieId == request.FilterToReleaseId
|
||||
select pl.Id
|
||||
).ToArray();
|
||||
}
|
||||
).ToArray();
|
||||
|
||||
var result = (from pl in this.DbContext.Playlists
|
||||
join u in this.DbContext.Users on pl.UserId equals u.Id
|
||||
where (request.FilterToPlaylistId == null || pl.RoadieId == request.FilterToPlaylistId)
|
||||
where (request.FilterToArtistId == null || playlistWithArtistTrackIds.Contains(pl.Id))
|
||||
where (request.FilterToReleaseId == null || playlistReleaseTrackIds.Contains(pl.Id))
|
||||
where ((roadieUser == null && pl.IsPublic) || (roadieUser != null && u.RoadieId == roadieUser.UserId || pl.IsPublic))
|
||||
where (request.FilterValue.Length == 0 || (request.FilterValue.Length > 0 && (pl.Name != null && pl.Name.Contains(request.FilterValue))))
|
||||
select PlaylistList.FromDataPlaylist(pl, u, this.MakePlaylistThumbnailImage(pl.RoadieId), this.MakeUserThumbnailImage(u.RoadieId)));
|
||||
var sortBy = string.IsNullOrEmpty(request.Sort) ? request.OrderValue(new Dictionary<string, string> { { "Playlist.Text", "ASC" } }) : request.OrderValue(null);
|
||||
var result = from pl in DbContext.Playlists
|
||||
join u in DbContext.Users on pl.UserId equals u.Id
|
||||
where request.FilterToPlaylistId == null || pl.RoadieId == request.FilterToPlaylistId
|
||||
where request.FilterToArtistId == null || playlistWithArtistTrackIds.Contains(pl.Id)
|
||||
where request.FilterToReleaseId == null || playlistReleaseTrackIds.Contains(pl.Id)
|
||||
where roadieUser == null && pl.IsPublic || roadieUser != null && u.RoadieId == roadieUser.UserId ||
|
||||
pl.IsPublic
|
||||
where request.FilterValue.Length == 0 || request.FilterValue.Length > 0 && pl.Name != null &&
|
||||
pl.Name.Contains(request.FilterValue)
|
||||
select PlaylistList.FromDataPlaylist(pl, u, MakePlaylistThumbnailImage(pl.RoadieId),
|
||||
MakeUserThumbnailImage(u.RoadieId));
|
||||
var sortBy = string.IsNullOrEmpty(request.Sort)
|
||||
? request.OrderValue(new Dictionary<string, string> { { "Playlist.Text", "ASC" } })
|
||||
: request.OrderValue();
|
||||
var rowCount = result.Count();
|
||||
var rows = result.OrderBy(sortBy).Skip(request.SkipValue).Take(request.LimitValue).ToArray();
|
||||
sw.Stop();
|
||||
|
@ -254,13 +253,15 @@ namespace Roadie.Api.Services
|
|||
if (playlist != null)
|
||||
{
|
||||
var looper = 0;
|
||||
foreach (var playlistTrack in this.DbContext.PlaylistTracks.Where(x => x.PlayListId == playlist.Id).OrderBy(x => x.CreatedDate))
|
||||
foreach (var playlistTrack in DbContext.PlaylistTracks.Where(x => x.PlayListId == playlist.Id)
|
||||
.OrderBy(x => x.CreatedDate))
|
||||
{
|
||||
looper++;
|
||||
playlistTrack.ListNumber = looper;
|
||||
playlistTrack.LastUpdated = now;
|
||||
}
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
|
||||
await DbContext.SaveChangesAsync();
|
||||
result = true;
|
||||
}
|
||||
|
||||
|
@ -276,11 +277,9 @@ namespace Roadie.Api.Services
|
|||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
var errors = new List<Exception>();
|
||||
var playlist = this.DbContext.Playlists.FirstOrDefault(x => x.RoadieId == model.Id);
|
||||
var playlist = DbContext.Playlists.FirstOrDefault(x => x.RoadieId == model.Id);
|
||||
if (playlist == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, string.Format("Label Not Found [{0}]", model.Id));
|
||||
}
|
||||
try
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
|
@ -300,19 +299,22 @@ namespace Roadie.Api.Services
|
|||
playlist.Thumbnail = ImageHelper.ConvertToJpegFormat(playlistImage);
|
||||
|
||||
// Resize to store in database as thumbnail
|
||||
playlist.Thumbnail = ImageHelper.ResizeImage(playlist.Thumbnail, this.Configuration.MediumImageSize.Width, this.Configuration.MediumImageSize.Height);
|
||||
playlist.Thumbnail = ImageHelper.ResizeImage(playlist.Thumbnail,
|
||||
Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
|
||||
}
|
||||
playlist.LastUpdated = now;
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
|
||||
this.CacheManager.ClearRegion(playlist.CacheRegion);
|
||||
this.Logger.LogInformation($"UpdatePlaylist `{ playlist }` By User `{ user }`");
|
||||
playlist.LastUpdated = now;
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
CacheManager.ClearRegion(playlist.CacheRegion);
|
||||
Logger.LogInformation($"UpdatePlaylist `{playlist}` By User `{user}`");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex);
|
||||
Logger.LogError(ex);
|
||||
errors.Add(ex);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
|
||||
return new OperationResult<bool>
|
||||
|
@ -329,18 +331,16 @@ namespace Roadie.Api.Services
|
|||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
var errors = new List<Exception>();
|
||||
var playlist = this.DbContext.Playlists.Include(x => x.Tracks).FirstOrDefault(x => x.RoadieId == request.Id);
|
||||
var playlist = DbContext.Playlists.Include(x => x.Tracks).FirstOrDefault(x => x.RoadieId == request.Id);
|
||||
if (playlist == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, string.Format("Label Not Found [{0}]", request.Id));
|
||||
}
|
||||
try
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
playlist.Tracks.Clear();
|
||||
|
||||
var tracks = (from t in this.DbContext.Tracks
|
||||
var tracks = (from t in DbContext.Tracks
|
||||
join plt in request.Tracks on t.RoadieId equals plt.Track.Id
|
||||
select t).ToArray();
|
||||
foreach (var newPlaylistTrack in request.Tracks.OrderBy(x => x.ListNumber))
|
||||
|
@ -354,18 +354,20 @@ namespace Roadie.Api.Services
|
|||
TrackId = track.Id
|
||||
});
|
||||
}
|
||||
|
||||
playlist.LastUpdated = now;
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
// await base.UpdatePlaylistCounts(playlist.Id, now);
|
||||
|
||||
this.Logger.LogInformation($"UpdatePlaylistTracks `{ playlist }` By User `{ user }`");
|
||||
Logger.LogInformation($"UpdatePlaylistTracks `{playlist}` By User `{user}`");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex);
|
||||
Logger.LogError(ex);
|
||||
errors.Add(ex);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
|
||||
return new OperationResult<bool>
|
||||
|
@ -382,82 +384,84 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
sw.Start();
|
||||
|
||||
var playlist = this.GetPlaylist(id);
|
||||
var playlist = GetPlaylist(id);
|
||||
|
||||
if (playlist == null)
|
||||
{
|
||||
return Task.FromResult(new OperationResult<Playlist>(true, string.Format("Playlist Not Found [{0}]", id)));
|
||||
}
|
||||
return Task.FromResult(new OperationResult<Playlist>(true,
|
||||
string.Format("Playlist Not Found [{0}]", id)));
|
||||
|
||||
var result = playlist.Adapt<Playlist>();
|
||||
result.AlternateNames = playlist.AlternateNames;
|
||||
result.Tags = playlist.Tags;
|
||||
result.URLs = playlist.URLs;
|
||||
var maintainer = this.DbContext.Users.Include(x => x.UserRoles).Include("UserRoles.Role").FirstOrDefault(x => x.Id == playlist.UserId);
|
||||
result.Maintainer = UserList.FromDataUser(maintainer, this.MakeUserThumbnailImage(maintainer.RoadieId));
|
||||
result.Thumbnail = this.MakePlaylistThumbnailImage(playlist.RoadieId);
|
||||
result.MediumThumbnail = base.MakeThumbnailImage(id, "playlist", this.Configuration.MediumImageSize.Width, this.Configuration.MediumImageSize.Height);
|
||||
var maintainer = DbContext.Users.Include(x => x.UserRoles).Include("UserRoles.Role")
|
||||
.FirstOrDefault(x => x.Id == playlist.UserId);
|
||||
result.Maintainer = UserList.FromDataUser(maintainer, MakeUserThumbnailImage(maintainer.RoadieId));
|
||||
result.Thumbnail = MakePlaylistThumbnailImage(playlist.RoadieId);
|
||||
result.MediumThumbnail = MakeThumbnailImage(id, "playlist", Configuration.MediumImageSize.Width,
|
||||
Configuration.MediumImageSize.Height);
|
||||
if (includes != null && includes.Any())
|
||||
{
|
||||
var playlistTracks = (from pl in this.DbContext.Playlists
|
||||
join pltr in this.DbContext.PlaylistTracks on pl.Id equals pltr.PlayListId
|
||||
join t in this.DbContext.Tracks on pltr.TrackId equals t.Id
|
||||
var playlistTracks = (from pl in DbContext.Playlists
|
||||
join pltr in DbContext.PlaylistTracks on pl.Id equals pltr.PlayListId
|
||||
join t in DbContext.Tracks on pltr.TrackId equals t.Id
|
||||
where pl.Id == playlist.Id
|
||||
select new { t, pltr }).ToArray();
|
||||
|
||||
if (includes.Contains("stats"))
|
||||
{
|
||||
result.Statistics = new Library.Models.Statistics.ReleaseGroupingStatistics
|
||||
result.Statistics = new ReleaseGroupingStatistics
|
||||
{
|
||||
ReleaseCount = result.ReleaseCount,
|
||||
TrackCount = result.TrackCount,
|
||||
TrackSize = result.DurationTime,
|
||||
FileSize = playlistTracks.Sum(x => (long?)x.t.FileSize).ToFileSize()
|
||||
};
|
||||
}
|
||||
if (includes.Contains("tracks"))
|
||||
{
|
||||
result.Tracks = (from plt in playlistTracks
|
||||
join rm in this.DbContext.ReleaseMedias on plt.t.ReleaseMediaId equals rm.Id
|
||||
join r in this.DbContext.Releases on rm.ReleaseId equals r.Id
|
||||
join releaseArtist in this.DbContext.Artists on r.ArtistId equals releaseArtist.Id
|
||||
join trackArtist in this.DbContext.Artists on plt.t.ArtistId equals trackArtist.Id into tas
|
||||
join rm in DbContext.ReleaseMedias on plt.t.ReleaseMediaId equals rm.Id
|
||||
join r in DbContext.Releases on rm.ReleaseId equals r.Id
|
||||
join releaseArtist in DbContext.Artists on r.ArtistId equals releaseArtist.Id
|
||||
join trackArtist in DbContext.Artists on plt.t.ArtistId equals trackArtist.Id into tas
|
||||
from trackArtist in tas.DefaultIfEmpty()
|
||||
select new PlaylistTrack
|
||||
{
|
||||
ListNumber = plt.pltr.ListNumber,
|
||||
Track = TrackList.FromDataTrack(null,
|
||||
plt.t,
|
||||
rm.MediaNumber,
|
||||
r,
|
||||
releaseArtist,
|
||||
trackArtist,
|
||||
this.HttpContext.BaseUrl,
|
||||
this.MakeTrackThumbnailImage(plt.t.RoadieId),
|
||||
this.MakeReleaseThumbnailImage(r.RoadieId),
|
||||
this.MakeArtistThumbnailImage(releaseArtist.RoadieId),
|
||||
this.MakeArtistThumbnailImage(trackArtist == null ? null : (Guid?)trackArtist.RoadieId))
|
||||
plt.t,
|
||||
rm.MediaNumber,
|
||||
r,
|
||||
releaseArtist,
|
||||
trackArtist,
|
||||
HttpContext.BaseUrl,
|
||||
MakeTrackThumbnailImage(plt.t.RoadieId),
|
||||
MakeReleaseThumbnailImage(r.RoadieId),
|
||||
MakeArtistThumbnailImage(releaseArtist.RoadieId),
|
||||
MakeArtistThumbnailImage(trackArtist == null ? null : (Guid?)trackArtist.RoadieId))
|
||||
}).ToArray();
|
||||
}
|
||||
if (includes.Contains("comments"))
|
||||
{
|
||||
var playlistComments = this.DbContext.Comments.Include(x => x.User).Where(x => x.PlaylistId == playlist.Id).OrderByDescending(x => x.CreatedDate).ToArray();
|
||||
var playlistComments = DbContext.Comments.Include(x => x.User)
|
||||
.Where(x => x.PlaylistId == playlist.Id).OrderByDescending(x => x.CreatedDate).ToArray();
|
||||
if (playlistComments.Any())
|
||||
{
|
||||
var comments = new List<Comment>();
|
||||
var commentIds = playlistComments.Select(x => x.Id).ToArray();
|
||||
var userCommentReactions = (from cr in this.DbContext.CommentReactions
|
||||
var userCommentReactions = (from cr in DbContext.CommentReactions
|
||||
where commentIds.Contains(cr.CommentId)
|
||||
select cr).ToArray();
|
||||
foreach (var playlistComment in playlistComments)
|
||||
{
|
||||
var comment = playlistComment.Adapt<Comment>();
|
||||
comment.DatabaseId = playlistComment.Id;
|
||||
comment.User = UserList.FromDataUser(playlistComment.User, this.MakeUserThumbnailImage(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);
|
||||
comment.User = UserList.FromDataUser(playlistComment.User,
|
||||
MakeUserThumbnailImage(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);
|
||||
}
|
||||
|
||||
result.Comments = comments;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -9,7 +9,7 @@
|
|||
<PackageReference Include="Hashids.net" Version="1.2.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="2.2.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.4.0" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.5.0" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.17" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -18,11 +18,11 @@ namespace Roadie.Api.Services
|
|||
public class StatisticsService : ServiceBase, IStatisticsService
|
||||
{
|
||||
public StatisticsService(IRoadieSettings configuration,
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext context,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<StatisticsService> logger)
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext context,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<StatisticsService> logger)
|
||||
: base(configuration, httpEncoder, context, cacheManager, logger, httpContext)
|
||||
{
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ namespace Roadie.Api.Services
|
|||
sw.Start();
|
||||
try
|
||||
{
|
||||
using (var conn = new MySqlConnection(this.Configuration.ConnectionString))
|
||||
using (var conn = new MySqlConnection(Configuration.ConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
var sql = @"SELECT rm.releaseMediaCount AS releaseMediaCount, COUNT(r.roadieId) AS releaseCount,
|
||||
|
@ -75,9 +75,7 @@ namespace Roadie.Api.Services
|
|||
using (var rdr = await cmd.ExecuteReaderAsync())
|
||||
{
|
||||
if (rdr.HasRows)
|
||||
{
|
||||
while (rdr.Read())
|
||||
{
|
||||
result = new LibraryStats
|
||||
{
|
||||
UserCount = SafeParser.ToNumber<int?>(rdr["UserCount"]),
|
||||
|
@ -92,13 +90,11 @@ namespace Roadie.Api.Services
|
|||
TotalTrackDuration = SafeParser.ToNumber<long?>(rdr["TotalTrackDuration"]),
|
||||
TotalTrackSize = SafeParser.ToNumber<long?>(rdr["TotalTrackSize"])
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex);
|
||||
Logger.LogError(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -106,17 +102,16 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
}
|
||||
}
|
||||
var lastScan = this.DbContext.ScanHistories.OrderByDescending(x => x.CreatedDate).FirstOrDefault();
|
||||
if (lastScan != null)
|
||||
{
|
||||
result.LastScan = lastScan.CreatedDate;
|
||||
}
|
||||
|
||||
var lastScan = DbContext.ScanHistories.OrderByDescending(x => x.CreatedDate).FirstOrDefault();
|
||||
if (lastScan != null) result.LastScan = lastScan.CreatedDate;
|
||||
sw.Stop();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex);
|
||||
Logger.LogError(ex);
|
||||
}
|
||||
|
||||
return new OperationResult<LibraryStats>
|
||||
{
|
||||
IsSuccess = result != null,
|
||||
|
@ -132,7 +127,7 @@ namespace Roadie.Api.Services
|
|||
|
||||
var result = new List<DateAndCount>();
|
||||
|
||||
using (var conn = new MySqlConnection(this.Configuration.ConnectionString))
|
||||
using (var conn = new MySqlConnection(Configuration.ConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
var sql = @"SELECT DATE_FORMAT(createdDate, '%Y-%m-%d') as date, count(1) as count
|
||||
|
@ -146,21 +141,17 @@ namespace Roadie.Api.Services
|
|||
using (var rdr = cmd.ExecuteReader())
|
||||
{
|
||||
if (rdr.HasRows)
|
||||
{
|
||||
while (rdr.Read())
|
||||
{
|
||||
result.Add(new DateAndCount
|
||||
{
|
||||
Date = SafeParser.ToString(rdr["date"]),
|
||||
Count = SafeParser.ToNumber<int?>(rdr["count"])
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex);
|
||||
Logger.LogError(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,10 +1,12 @@
|
|||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Roadie.Library.Identity;
|
||||
using System;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Roadie.Api.Services
|
||||
|
@ -15,7 +17,7 @@ namespace Roadie.Api.Services
|
|||
|
||||
public TokenService(IConfiguration configuration)
|
||||
{
|
||||
this._configuration = configuration;
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public async Task<string> GenerateToken(ApplicationUser user, UserManager<ApplicationUser> userManager)
|
||||
|
@ -27,7 +29,7 @@ namespace Roadie.Api.Services
|
|||
|
||||
var tokenHandler = new JwtSecurityTokenHandler();
|
||||
|
||||
var claims = new Claim[]
|
||||
var claims = new[]
|
||||
{
|
||||
new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()),
|
||||
new Claim("roadie_id", user.RoadieId.ToString()),
|
||||
|
@ -38,17 +40,19 @@ namespace Roadie.Api.Services
|
|||
}.Union(userRoles);
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(this._configuration.GetValue<String>("Tokens:PrivateKey")));
|
||||
var signingCredentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(securityKey, Microsoft.IdentityModel.Tokens.SecurityAlgorithms.HmacSha256Signature);
|
||||
var securityKey =
|
||||
new SymmetricSecurityKey(
|
||||
Encoding.Default.GetBytes(_configuration.GetValue<string>("Tokens:PrivateKey")));
|
||||
var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
|
||||
|
||||
var jwt = new JwtSecurityToken(
|
||||
signingCredentials: signingCredentials,
|
||||
claims: claims,
|
||||
notBefore: utcNow,
|
||||
expires: utcNow.AddSeconds(this._configuration.GetValue<int>("Tokens:Lifetime")),
|
||||
audience: this._configuration.GetValue<String>("Tokens:Audience"),
|
||||
issuer: this._configuration.GetValue<String>("Tokens:Issuer")
|
||||
);
|
||||
expires: utcNow.AddSeconds(_configuration.GetValue<int>("Tokens:Lifetime")),
|
||||
audience: _configuration.GetValue<string>("Tokens:Audience"),
|
||||
issuer: _configuration.GetValue<string>("Tokens:Issuer")
|
||||
);
|
||||
|
||||
return new JwtSecurityTokenHandler().WriteToken(jwt);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -7,11 +7,12 @@ using Roadie.Library;
|
|||
using Roadie.Library.Caching;
|
||||
using Roadie.Library.Configuration;
|
||||
using Roadie.Library.Encoding;
|
||||
using Roadie.Library.Enums;
|
||||
using Roadie.Library.Identity;
|
||||
using Roadie.Library.Imaging;
|
||||
using Roadie.Library.MetaData.LastFm;
|
||||
using Roadie.Library.Models;
|
||||
using Roadie.Library.Models.Pagination;
|
||||
using Roadie.Library.Models.Releases;
|
||||
using Roadie.Library.Models.Statistics;
|
||||
using Roadie.Library.Models.Users;
|
||||
using Roadie.Library.Utility;
|
||||
|
@ -33,17 +34,18 @@ namespace Roadie.Api.Services
|
|||
private UserManager<ApplicationUser> UserManager { get; }
|
||||
|
||||
public UserService(IRoadieSettings configuration,
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext context,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<ArtistService> logger,
|
||||
UserManager<ApplicationUser> userManager
|
||||
)
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext context,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<ArtistService> logger,
|
||||
UserManager<ApplicationUser> userManager
|
||||
)
|
||||
: base(configuration, httpEncoder, context, cacheManager, logger, httpContext)
|
||||
{
|
||||
this.UserManager = userManager;
|
||||
this.LastFmHelper = new LastFmHelper(this.Configuration, this.CacheManager, this.Logger, context, httpEncoder); ;
|
||||
UserManager = userManager;
|
||||
LastFmHelper = new LastFmHelper(Configuration, CacheManager, Logger, context, httpEncoder);
|
||||
;
|
||||
}
|
||||
|
||||
public async Task<OperationResult<User>> ById(User user, Guid id, IEnumerable<string> includes)
|
||||
|
@ -54,21 +56,18 @@ namespace Roadie.Api.Services
|
|||
var sw = Stopwatch.StartNew();
|
||||
sw.Start();
|
||||
var cacheKey = string.Format("urn:user_by_id_operation:{0}", id);
|
||||
var result = await this.CacheManager.GetAsync<OperationResult<User>>(cacheKey, async () =>
|
||||
var result = await CacheManager.GetAsync(cacheKey, async () =>
|
||||
{
|
||||
tsw.Restart();
|
||||
var rr = await this.UserByIdAction(id, includes);
|
||||
var rr = await UserByIdAction(id, includes);
|
||||
tsw.Stop();
|
||||
timings.Add("UserByIdAction", tsw.ElapsedMilliseconds);
|
||||
return rr;
|
||||
}, ApplicationUser.CacheRegionUrn(id));
|
||||
sw.Stop();
|
||||
if (result?.Data != null)
|
||||
{
|
||||
result.Data.Avatar = this.MakeUserThumbnailImage(id);
|
||||
}
|
||||
if (result?.Data != null) result.Data.Avatar = MakeUserThumbnailImage(id);
|
||||
timings.Add("operation", sw.ElapsedMilliseconds);
|
||||
this.Logger.LogDebug("ById Timings: id [{0}]", id);
|
||||
Logger.LogDebug("ById Timings: id [{0}]", id);
|
||||
return new OperationResult<User>(result.Messages)
|
||||
{
|
||||
Data = result?.Data,
|
||||
|
@ -84,43 +83,48 @@ namespace Roadie.Api.Services
|
|||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
var result = (from u in this.DbContext.Users
|
||||
let lastActivity = (from ut in this.DbContext.UserTracks
|
||||
where ut.UserId == u.Id
|
||||
select ut.LastPlayed).Max()
|
||||
where (request.FilterValue.Length == 0 || (request.FilterValue.Length > 0 && (u.UserName.Contains(request.FilterValue))))
|
||||
select new UserList
|
||||
{
|
||||
DatabaseId = u.Id,
|
||||
Id = u.RoadieId,
|
||||
User = new DataToken
|
||||
{
|
||||
Text = u.UserName,
|
||||
Value = u.RoadieId.ToString()
|
||||
},
|
||||
IsEditor = u.UserRoles.Any(x => x.Role.Name == "Editor"),
|
||||
IsPrivate = u.IsPrivate,
|
||||
Thumbnail = this.MakeUserThumbnailImage(u.RoadieId),
|
||||
CreatedDate = u.CreatedDate,
|
||||
LastUpdated = u.LastUpdated,
|
||||
RegisteredDate = u.RegisteredOn,
|
||||
LastLoginDate = u.LastLogin,
|
||||
LastApiAccessDate = u.LastApiAccess,
|
||||
LastActivity = lastActivity
|
||||
});
|
||||
var result = from u in DbContext.Users
|
||||
let lastActivity = (from ut in DbContext.UserTracks
|
||||
where ut.UserId == u.Id
|
||||
select ut.LastPlayed).Max()
|
||||
where request.FilterValue.Length == 0 ||
|
||||
request.FilterValue.Length > 0 && u.UserName.Contains(request.FilterValue)
|
||||
select new UserList
|
||||
{
|
||||
DatabaseId = u.Id,
|
||||
Id = u.RoadieId,
|
||||
User = new models.DataToken
|
||||
{
|
||||
Text = u.UserName,
|
||||
Value = u.RoadieId.ToString()
|
||||
},
|
||||
IsEditor = u.UserRoles.Any(x => x.Role.Name == "Editor"),
|
||||
IsPrivate = u.IsPrivate,
|
||||
Thumbnail = MakeUserThumbnailImage(u.RoadieId),
|
||||
CreatedDate = u.CreatedDate,
|
||||
LastUpdated = u.LastUpdated,
|
||||
RegisteredDate = u.RegisteredOn,
|
||||
LastLoginDate = u.LastLogin,
|
||||
LastApiAccessDate = u.LastApiAccess,
|
||||
LastActivity = lastActivity
|
||||
};
|
||||
|
||||
UserList[] rows = null;
|
||||
var rowCount = result.Count();
|
||||
var sortBy = string.IsNullOrEmpty(request.Sort) ? request.OrderValue(new Dictionary<string, string> { { "User.Text", "ASC" } }) : request.OrderValue(null);
|
||||
var sortBy = string.IsNullOrEmpty(request.Sort)
|
||||
? request.OrderValue(new Dictionary<string, string> { { "User.Text", "ASC" } })
|
||||
: request.OrderValue();
|
||||
rows = result.OrderBy(sortBy).Skip(request.SkipValue).Take(request.LimitValue).ToArray();
|
||||
|
||||
if (rows.Any())
|
||||
{
|
||||
foreach (var row in rows)
|
||||
{
|
||||
var userArtists = this.DbContext.UserArtists.Include(x => x.Artist).Where(x => x.UserId == row.DatabaseId).ToArray();
|
||||
var userReleases = this.DbContext.UserReleases.Include(x => x.Release).Where(x => x.UserId == row.DatabaseId).ToArray();
|
||||
var userTracks = this.DbContext.UserTracks.Include(x => x.Track).Where(x => x.UserId == row.DatabaseId).ToArray();
|
||||
var userArtists = DbContext.UserArtists.Include(x => x.Artist)
|
||||
.Where(x => x.UserId == row.DatabaseId).ToArray();
|
||||
var userReleases = DbContext.UserReleases.Include(x => x.Release)
|
||||
.Where(x => x.UserId == row.DatabaseId).ToArray();
|
||||
var userTracks = DbContext.UserTracks.Include(x => x.Track).Where(x => x.UserId == row.DatabaseId)
|
||||
.ToArray();
|
||||
|
||||
row.Statistics = new UserStatistics
|
||||
{
|
||||
|
@ -136,7 +140,7 @@ namespace Roadie.Api.Services
|
|||
DislikedTracks = userTracks.Where(x => x.IsDisliked ?? false).Count()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
return Task.FromResult(new Library.Models.Pagination.PagedResult<UserList>
|
||||
{
|
||||
|
@ -150,19 +154,13 @@ namespace Roadie.Api.Services
|
|||
|
||||
public async Task<OperationResult<bool>> SetArtistBookmark(Guid artistId, User roadieUser, bool isBookmarked)
|
||||
{
|
||||
var user = this.GetUser(roadieUser.UserId);
|
||||
if (user == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid User [{ roadieUser }]");
|
||||
}
|
||||
var artist = this.GetArtist(artistId);
|
||||
if (artist == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid Artist [{ artistId }]");
|
||||
}
|
||||
var result = await this.SetBookmark(user, Library.Enums.BookmarkType.Artist, artist.Id, isBookmarked);
|
||||
var user = GetUser(roadieUser.UserId);
|
||||
if (user == null) return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
|
||||
var artist = GetArtist(artistId);
|
||||
if (artist == null) return new OperationResult<bool>(true, $"Invalid Artist [{artistId}]");
|
||||
var result = await SetBookmark(user, BookmarkType.Artist, artist.Id, isBookmarked);
|
||||
|
||||
this.CacheManager.ClearRegion(artist.CacheRegion);
|
||||
CacheManager.ClearRegion(artist.CacheRegion);
|
||||
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
|
@ -173,49 +171,35 @@ namespace Roadie.Api.Services
|
|||
|
||||
public async Task<OperationResult<bool>> SetArtistDisliked(Guid artistId, User roadieUser, bool isDisliked)
|
||||
{
|
||||
var user = this.GetUser(roadieUser.UserId);
|
||||
if (user == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid User [{ roadieUser }]");
|
||||
}
|
||||
return await base.ToggleArtistDisliked(artistId, user, isDisliked);
|
||||
var user = GetUser(roadieUser.UserId);
|
||||
if (user == null) return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
|
||||
return await ToggleArtistDisliked(artistId, user, isDisliked);
|
||||
}
|
||||
|
||||
public async Task<OperationResult<bool>> SetArtistFavorite(Guid artistId, User roadieUser, bool isFavorite)
|
||||
{
|
||||
var user = this.GetUser(roadieUser.UserId);
|
||||
if (user == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid User [{ roadieUser }]");
|
||||
}
|
||||
return await base.ToggleArtistFavorite(artistId, user, isFavorite);
|
||||
var user = GetUser(roadieUser.UserId);
|
||||
if (user == null) return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
|
||||
return await ToggleArtistFavorite(artistId, user, isFavorite);
|
||||
}
|
||||
|
||||
public async Task<OperationResult<short>> SetArtistRating(Guid artistId, User roadieUser, short rating)
|
||||
{
|
||||
var user = this.GetUser(roadieUser.UserId);
|
||||
if (user == null)
|
||||
{
|
||||
return new OperationResult<short>(true, $"Invalid User [{ roadieUser }]");
|
||||
}
|
||||
var user = GetUser(roadieUser.UserId);
|
||||
if (user == null) return new OperationResult<short>(true, $"Invalid User [{roadieUser}]");
|
||||
return await base.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 = this.GetUser(roadieUser.UserId);
|
||||
if (user == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid User [{ roadieUser }]");
|
||||
}
|
||||
var collection = this.GetCollection(collectionId);
|
||||
if (collection == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid Collection [{ collectionId }]");
|
||||
}
|
||||
var result = await this.SetBookmark(user, Library.Enums.BookmarkType.Collection, collection.Id, isBookmarked);
|
||||
var user = GetUser(roadieUser.UserId);
|
||||
if (user == null) return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
|
||||
var collection = GetCollection(collectionId);
|
||||
if (collection == null) return new OperationResult<bool>(true, $"Invalid Collection [{collectionId}]");
|
||||
var result = await SetBookmark(user, BookmarkType.Collection, collection.Id, isBookmarked);
|
||||
|
||||
this.CacheManager.ClearRegion(collection.CacheRegion);
|
||||
CacheManager.ClearRegion(collection.CacheRegion);
|
||||
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
|
@ -226,19 +210,13 @@ namespace Roadie.Api.Services
|
|||
|
||||
public async Task<OperationResult<bool>> SetLabelBookmark(Guid labelId, User roadieUser, bool isBookmarked)
|
||||
{
|
||||
var user = this.GetUser(roadieUser.UserId);
|
||||
if (user == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid User [{ roadieUser }]");
|
||||
}
|
||||
var label = this.GetLabel(labelId);
|
||||
if (label == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid Label [{ labelId }]");
|
||||
}
|
||||
var result = await this.SetBookmark(user, Library.Enums.BookmarkType.Label, label.Id, isBookmarked);
|
||||
var user = GetUser(roadieUser.UserId);
|
||||
if (user == null) return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
|
||||
var label = GetLabel(labelId);
|
||||
if (label == null) return new OperationResult<bool>(true, $"Invalid Label [{labelId}]");
|
||||
var result = await SetBookmark(user, BookmarkType.Label, label.Id, isBookmarked);
|
||||
|
||||
this.CacheManager.ClearRegion(label.CacheRegion);
|
||||
CacheManager.ClearRegion(label.CacheRegion);
|
||||
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
|
@ -247,21 +225,16 @@ namespace Roadie.Api.Services
|
|||
};
|
||||
}
|
||||
|
||||
public async Task<OperationResult<bool>> SetPlaylistBookmark(Guid playlistId, User roadieUser, bool isBookmarked)
|
||||
public async Task<OperationResult<bool>> SetPlaylistBookmark(Guid playlistId, User roadieUser,
|
||||
bool isBookmarked)
|
||||
{
|
||||
var user = this.GetUser(roadieUser.UserId);
|
||||
if (user == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid User [{ roadieUser }]");
|
||||
}
|
||||
var playlist = this.GetPlaylist(playlistId);
|
||||
if (playlist == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid Playlist [{ playlistId }]");
|
||||
}
|
||||
var result = await this.SetBookmark(user, Library.Enums.BookmarkType.Playlist, playlist.Id, isBookmarked);
|
||||
var user = GetUser(roadieUser.UserId);
|
||||
if (user == null) return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
|
||||
var playlist = GetPlaylist(playlistId);
|
||||
if (playlist == null) return new OperationResult<bool>(true, $"Invalid Playlist [{playlistId}]");
|
||||
var result = await SetBookmark(user, BookmarkType.Playlist, playlist.Id, isBookmarked);
|
||||
|
||||
this.CacheManager.ClearRegion(playlist.CacheRegion);
|
||||
CacheManager.ClearRegion(playlist.CacheRegion);
|
||||
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
|
@ -272,19 +245,13 @@ namespace Roadie.Api.Services
|
|||
|
||||
public async Task<OperationResult<bool>> SetReleaseBookmark(Guid releaseid, User roadieUser, bool isBookmarked)
|
||||
{
|
||||
var user = this.GetUser(roadieUser.UserId);
|
||||
if (user == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid User [{ roadieUser }]");
|
||||
}
|
||||
var release = this.GetRelease(releaseid);
|
||||
if (release == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid Release [{ releaseid }]");
|
||||
}
|
||||
var result = await this.SetBookmark(user, Library.Enums.BookmarkType.Release, release.Id, isBookmarked);
|
||||
var user = GetUser(roadieUser.UserId);
|
||||
if (user == null) return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
|
||||
var release = GetRelease(releaseid);
|
||||
if (release == null) return new OperationResult<bool>(true, $"Invalid Release [{releaseid}]");
|
||||
var result = await SetBookmark(user, BookmarkType.Release, release.Id, isBookmarked);
|
||||
|
||||
this.CacheManager.ClearRegion(release.CacheRegion);
|
||||
CacheManager.ClearRegion(release.CacheRegion);
|
||||
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
|
@ -295,49 +262,34 @@ namespace Roadie.Api.Services
|
|||
|
||||
public async Task<OperationResult<bool>> SetReleaseDisliked(Guid releaseId, User roadieUser, bool isDisliked)
|
||||
{
|
||||
var user = this.GetUser(roadieUser.UserId);
|
||||
if (user == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid User [{ roadieUser }]");
|
||||
}
|
||||
return await base.ToggleReleaseDisliked(releaseId, user, isDisliked);
|
||||
var user = GetUser(roadieUser.UserId);
|
||||
if (user == null) return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
|
||||
return await ToggleReleaseDisliked(releaseId, user, isDisliked);
|
||||
}
|
||||
|
||||
public async Task<OperationResult<bool>> SetReleaseFavorite(Guid releaseId, User roadieUser, bool isFavorite)
|
||||
{
|
||||
var user = this.GetUser(roadieUser.UserId);
|
||||
if (user == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid User [{ roadieUser }]");
|
||||
}
|
||||
return await base.ToggleReleaseFavorite(releaseId, user, isFavorite);
|
||||
var user = GetUser(roadieUser.UserId);
|
||||
if (user == null) return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
|
||||
return await ToggleReleaseFavorite(releaseId, user, isFavorite);
|
||||
}
|
||||
|
||||
public async Task<OperationResult<short>> SetReleaseRating(Guid releaseId, User roadieUser, short rating)
|
||||
{
|
||||
var user = this.GetUser(roadieUser.UserId);
|
||||
if (user == null)
|
||||
{
|
||||
return new OperationResult<short>(true, $"Invalid User [{ roadieUser }]");
|
||||
}
|
||||
var user = GetUser(roadieUser.UserId);
|
||||
if (user == null) return new OperationResult<short>(true, $"Invalid User [{roadieUser}]");
|
||||
return await base.SetReleaseRating(releaseId, user, rating);
|
||||
}
|
||||
|
||||
public async Task<OperationResult<bool>> SetTrackBookmark(Guid trackId, User roadieUser, bool isBookmarked)
|
||||
{
|
||||
var user = this.GetUser(roadieUser.UserId);
|
||||
if (user == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid User [{ roadieUser }]");
|
||||
}
|
||||
var track = this.GetTrack(trackId);
|
||||
if (track == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid Track [{ trackId }]");
|
||||
}
|
||||
var result = await this.SetBookmark(user, Library.Enums.BookmarkType.Track, track.Id, isBookmarked);
|
||||
var user = GetUser(roadieUser.UserId);
|
||||
if (user == null) return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
|
||||
var track = GetTrack(trackId);
|
||||
if (track == null) return new OperationResult<bool>(true, $"Invalid Track [{trackId}]");
|
||||
var result = await SetBookmark(user, BookmarkType.Track, track.Id, isBookmarked);
|
||||
|
||||
this.CacheManager.ClearRegion(track.CacheRegion);
|
||||
CacheManager.ClearRegion(track.CacheRegion);
|
||||
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
|
@ -348,137 +300,88 @@ namespace Roadie.Api.Services
|
|||
|
||||
public async Task<OperationResult<bool>> SetTrackDisliked(Guid trackId, User roadieUser, bool isDisliked)
|
||||
{
|
||||
var user = this.GetUser(roadieUser.UserId);
|
||||
if (user == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid User [{ roadieUser }]");
|
||||
}
|
||||
return await base.ToggleTrackDisliked(trackId, user, isDisliked);
|
||||
var user = GetUser(roadieUser.UserId);
|
||||
if (user == null) return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
|
||||
return await ToggleTrackDisliked(trackId, user, isDisliked);
|
||||
}
|
||||
|
||||
public async Task<OperationResult<bool>> SetTrackFavorite(Guid trackId, User roadieUser, bool isFavorite)
|
||||
{
|
||||
var user = this.GetUser(roadieUser.UserId);
|
||||
if (user == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid User [{ roadieUser }]");
|
||||
}
|
||||
return await base.ToggleTrackFavorite(trackId, user, isFavorite);
|
||||
var user = GetUser(roadieUser.UserId);
|
||||
if (user == null) return new OperationResult<bool>(true, $"Invalid User [{roadieUser}]");
|
||||
return await ToggleTrackFavorite(trackId, user, isFavorite);
|
||||
}
|
||||
|
||||
public async Task<OperationResult<short>> SetTrackRating(Guid trackId, User roadieUser, short rating)
|
||||
{
|
||||
var timings = new Dictionary<string, long>();
|
||||
var sw = Stopwatch.StartNew();
|
||||
var user = this.GetUser(roadieUser.UserId);
|
||||
var user = GetUser(roadieUser.UserId);
|
||||
sw.Stop();
|
||||
timings.Add("GetUser", sw.ElapsedMilliseconds);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
return new OperationResult<short>(true, $"Invalid User [{ roadieUser }]");
|
||||
}
|
||||
if (user == null) return new OperationResult<short>(true, $"Invalid User [{roadieUser}]");
|
||||
sw.Start();
|
||||
var result = await base.SetTrackRating(trackId, user, rating);
|
||||
sw.Stop();
|
||||
timings.Add("SetTrackRating", sw.ElapsedMilliseconds);
|
||||
|
||||
result.AdditionalData.Add("Timing", sw.ElapsedMilliseconds);
|
||||
this.Logger.LogInformation($"User `{ roadieUser }` set rating [{ rating }] on TrackId [{ trackId }]. Result [{ JsonConvert.SerializeObject(result) }]");
|
||||
Logger.LogInformation(
|
||||
$"User `{roadieUser}` set rating [{rating}] on TrackId [{trackId}]. Result [{JsonConvert.SerializeObject(result)}]");
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<OperationResult<bool>> UpdateLastFMSessionKey(ApplicationUser user, string token)
|
||||
public async Task<OperationResult<bool>> UpdateIntegrationGrant(Guid userId, string integrationName,
|
||||
string token)
|
||||
{
|
||||
var lastFmSessionKeyResult = await this.LastFmHelper.GetSessionKeyForUserToken(token);
|
||||
if(!lastFmSessionKeyResult.IsSuccess)
|
||||
{
|
||||
return new OperationResult<bool>(false, $"Unable to Get LastFM Session Key For Token [{ token }]");
|
||||
}
|
||||
// Check concurrency stamp
|
||||
if (user.ConcurrencyStamp != user.ConcurrencyStamp)
|
||||
{
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
Errors = new List<Exception> { new Exception("User data is stale.") }
|
||||
};
|
||||
}
|
||||
user.LastFMSessionKey = lastFmSessionKeyResult.Data;
|
||||
user.LastUpdated = DateTime.UtcNow;
|
||||
user.ConcurrencyStamp = Guid.NewGuid().ToString();
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
|
||||
this.CacheManager.ClearRegion(ApplicationUser.CacheRegionUrn(user.RoadieId));
|
||||
|
||||
this.Logger.LogInformation($"User `{ user }` Updated LastFm SessionKey");
|
||||
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
IsSuccess = true,
|
||||
Data = true
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<OperationResult<bool>> UpdateIntegrationGrant(Guid userId, string integrationName, string token)
|
||||
{
|
||||
var user = this.DbContext.Users.FirstOrDefault(x => x.RoadieId == userId);
|
||||
if (user == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"User Not Found [{ userId }]");
|
||||
}
|
||||
if (integrationName == "lastfm")
|
||||
{
|
||||
return await this.UpdateLastFMSessionKey(user, token);
|
||||
}
|
||||
var user = DbContext.Users.FirstOrDefault(x => x.RoadieId == userId);
|
||||
if (user == null) return new OperationResult<bool>(true, $"User Not Found [{userId}]");
|
||||
if (integrationName == "lastfm") return await UpdateLastFMSessionKey(user, token);
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<OperationResult<bool>> UpdateProfile(User userPerformingUpdate, User userBeingUpdatedModel)
|
||||
{
|
||||
var user = this.DbContext.Users.FirstOrDefault(x => x.RoadieId == userBeingUpdatedModel.UserId);
|
||||
var user = DbContext.Users.FirstOrDefault(x => x.RoadieId == userBeingUpdatedModel.UserId);
|
||||
if (user == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, string.Format("User Not Found [{0}]", userBeingUpdatedModel.UserId));
|
||||
}
|
||||
return new OperationResult<bool>(true,
|
||||
string.Format("User Not Found [{0}]", userBeingUpdatedModel.UserId));
|
||||
if (user.Id != userPerformingUpdate.Id && !userPerformingUpdate.IsAdmin)
|
||||
{
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
Errors = new List<Exception> { new Exception("Access Denied") }
|
||||
};
|
||||
}
|
||||
// Check concurrency stamp
|
||||
if (user.ConcurrencyStamp != userBeingUpdatedModel.ConcurrencyStamp)
|
||||
{
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
Errors = new List<Exception> { new Exception("User data is stale.") }
|
||||
};
|
||||
}
|
||||
// Check that username (if changed) doesn't already exist
|
||||
if (user.UserName != userBeingUpdatedModel.UserName)
|
||||
{
|
||||
var userByUsername = this.DbContext.Users.FirstOrDefault(x => x.NormalizedUserName == userBeingUpdatedModel.UserName.ToUpper());
|
||||
var userByUsername = DbContext.Users.FirstOrDefault(x =>
|
||||
x.NormalizedUserName == userBeingUpdatedModel.UserName.ToUpper());
|
||||
if (userByUsername != null)
|
||||
{
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
Errors = new List<Exception> { new Exception("Username already in use") }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Check that email (if changed) doesn't already exist
|
||||
if (user.Email != userBeingUpdatedModel.Email)
|
||||
{
|
||||
var userByEmail = this.DbContext.Users.FirstOrDefault(x => x.NormalizedEmail == userBeingUpdatedModel.Email.ToUpper());
|
||||
var userByEmail =
|
||||
DbContext.Users.FirstOrDefault(x => x.NormalizedEmail == userBeingUpdatedModel.Email.ToUpper());
|
||||
if (userByEmail != null)
|
||||
{
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
Errors = new List<Exception> { new Exception("Email already in use") }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
user.UserName = userBeingUpdatedModel.UserName;
|
||||
user.NormalizedUserName = userBeingUpdatedModel.UserName.ToUpper();
|
||||
user.Email = userBeingUpdatedModel.Email;
|
||||
|
@ -504,35 +407,36 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
var imageData = ImageHelper.ImageDataFromUrl(userBeingUpdatedModel.AvatarData);
|
||||
if (imageData != null)
|
||||
{
|
||||
user.Avatar = ImageHelper.ResizeImage(imageData, this.Configuration.ThumbnailImageSize.Width, this.Configuration.ThumbnailImageSize.Height);
|
||||
}
|
||||
user.Avatar = ImageHelper.ResizeImage(imageData, Configuration.ThumbnailImageSize.Width,
|
||||
Configuration.ThumbnailImageSize.Height);
|
||||
}
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
|
||||
if (!string.IsNullOrEmpty(userBeingUpdatedModel.Password) && !string.IsNullOrEmpty(userBeingUpdatedModel.PasswordConfirmation))
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
if (!string.IsNullOrEmpty(userBeingUpdatedModel.Password) &&
|
||||
!string.IsNullOrEmpty(userBeingUpdatedModel.PasswordConfirmation))
|
||||
{
|
||||
if (userBeingUpdatedModel.Password != userBeingUpdatedModel.PasswordConfirmation)
|
||||
{
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
Errors = new List<Exception> { new Exception("Password does not match confirmation") }
|
||||
};
|
||||
}
|
||||
string resetToken = await UserManager.GeneratePasswordResetTokenAsync(user);
|
||||
var identityResult = await UserManager.ResetPasswordAsync(user, resetToken, userBeingUpdatedModel.Password);
|
||||
var resetToken = await UserManager.GeneratePasswordResetTokenAsync(user);
|
||||
var identityResult =
|
||||
await UserManager.ResetPasswordAsync(user, resetToken, userBeingUpdatedModel.Password);
|
||||
if (!identityResult.Succeeded)
|
||||
{
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
Errors = identityResult.Errors != null ? identityResult.Errors.Select(x => new Exception($"Code [{ x.Code }], Description [{ x.Description }]")) : new List<Exception> { new Exception("Unable to reset password") }
|
||||
Errors = identityResult.Errors != null
|
||||
? identityResult.Errors.Select(x =>
|
||||
new Exception($"Code [{x.Code}], Description [{x.Description}]"))
|
||||
: new List<Exception> { new Exception("Unable to reset password") }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
this.CacheManager.ClearRegion(ApplicationUser.CacheRegionUrn(user.RoadieId));
|
||||
CacheManager.ClearRegion(ApplicationUser.CacheRegionUrn(user.RoadieId));
|
||||
|
||||
this.Logger.LogInformation($"User `{ userPerformingUpdate }` modifed user `{ userBeingUpdatedModel }`");
|
||||
Logger.LogInformation($"User `{userPerformingUpdate}` modifed user `{userBeingUpdatedModel}`");
|
||||
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
|
@ -541,18 +445,19 @@ namespace Roadie.Api.Services
|
|||
};
|
||||
}
|
||||
|
||||
private async Task<OperationResult<bool>> SetBookmark(ApplicationUser user, Library.Enums.BookmarkType bookmarktype, int bookmarkTargetId, bool isBookmarked)
|
||||
private async Task<OperationResult<bool>> SetBookmark(ApplicationUser user, BookmarkType bookmarktype,
|
||||
int bookmarkTargetId, bool isBookmarked)
|
||||
{
|
||||
var bookmark = this.DbContext.Bookmarks.FirstOrDefault(x => x.BookmarkTargetId == bookmarkTargetId &&
|
||||
x.BookmarkType == bookmarktype &&
|
||||
x.UserId == user.Id);
|
||||
var bookmark = DbContext.Bookmarks.FirstOrDefault(x => x.BookmarkTargetId == bookmarkTargetId &&
|
||||
x.BookmarkType == bookmarktype &&
|
||||
x.UserId == user.Id);
|
||||
if (!isBookmarked)
|
||||
{
|
||||
// Remove bookmark
|
||||
if (bookmark != null)
|
||||
{
|
||||
this.DbContext.Bookmarks.Remove(bookmark);
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
DbContext.Bookmarks.Remove(bookmark);
|
||||
await DbContext.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -560,19 +465,46 @@ namespace Roadie.Api.Services
|
|||
// Add bookmark
|
||||
if (bookmark == null)
|
||||
{
|
||||
this.DbContext.Bookmarks.Add(new data.Bookmark
|
||||
DbContext.Bookmarks.Add(new data.Bookmark
|
||||
{
|
||||
UserId = user.Id,
|
||||
BookmarkTargetId = bookmarkTargetId,
|
||||
BookmarkType = bookmarktype,
|
||||
CreatedDate = DateTime.UtcNow,
|
||||
Status = Library.Enums.Statuses.Ok
|
||||
Status = Statuses.Ok
|
||||
});
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
await DbContext.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
this.CacheManager.ClearRegion(user.CacheRegion);
|
||||
CacheManager.ClearRegion(user.CacheRegion);
|
||||
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
IsSuccess = true,
|
||||
Data = true
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<OperationResult<bool>> UpdateLastFMSessionKey(ApplicationUser user, string token)
|
||||
{
|
||||
var lastFmSessionKeyResult = await LastFmHelper.GetSessionKeyForUserToken(token);
|
||||
if (!lastFmSessionKeyResult.IsSuccess)
|
||||
return new OperationResult<bool>(false, $"Unable to Get LastFM Session Key For Token [{token}]");
|
||||
// Check concurrency stamp
|
||||
if (user.ConcurrencyStamp != user.ConcurrencyStamp)
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
Errors = new List<Exception> { new Exception("User data is stale.") }
|
||||
};
|
||||
user.LastFMSessionKey = lastFmSessionKeyResult.Data;
|
||||
user.LastUpdated = DateTime.UtcNow;
|
||||
user.ConcurrencyStamp = Guid.NewGuid().ToString();
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
CacheManager.ClearRegion(ApplicationUser.CacheRegionUrn(user.RoadieId));
|
||||
|
||||
Logger.LogInformation($"User `{user}` Updated LastFm SessionKey");
|
||||
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
|
@ -583,83 +515,98 @@ namespace Roadie.Api.Services
|
|||
|
||||
private Task<OperationResult<User>> UserByIdAction(Guid id, IEnumerable<string> includes)
|
||||
{
|
||||
var user = this.GetUser(id);
|
||||
var user = GetUser(id);
|
||||
if (user == null)
|
||||
{
|
||||
return Task.FromResult(new OperationResult<User>(true, string.Format("User Not Found [{0}]", id)));
|
||||
}
|
||||
var model = user.Adapt<User>();
|
||||
if (includes != null && includes.Any())
|
||||
{
|
||||
if (includes.Contains("stats"))
|
||||
{
|
||||
var userArtists = this.DbContext.UserArtists.Include(x => x.Artist).Where(x => x.UserId == user.Id).ToArray() ?? new data.UserArtist[0];
|
||||
var userReleases = this.DbContext.UserReleases.Include(x => x.Release).Where(x => x.UserId == user.Id).ToArray() ?? new data.UserRelease[0];
|
||||
var userTracks = this.DbContext.UserTracks.Include(x => x.Track).Where(x => x.UserId == user.Id).ToArray() ?? new data.UserTrack[0];
|
||||
var userArtists =
|
||||
DbContext.UserArtists.Include(x => x.Artist).Where(x => x.UserId == user.Id).ToArray() ??
|
||||
new data.UserArtist[0];
|
||||
var userReleases =
|
||||
DbContext.UserReleases.Include(x => x.Release).Where(x => x.UserId == user.Id).ToArray() ??
|
||||
new data.UserRelease[0];
|
||||
var userTracks =
|
||||
DbContext.UserTracks.Include(x => x.Track).Where(x => x.UserId == user.Id).ToArray() ??
|
||||
new data.UserTrack[0];
|
||||
|
||||
var mostPlayedArtist = (from a in this.DbContext.Artists
|
||||
join r in this.DbContext.Releases on a.Id equals r.ArtistId
|
||||
join rm in this.DbContext.ReleaseMedias on r.Id equals rm.ReleaseId
|
||||
join t in this.DbContext.Tracks on rm.Id equals t.ReleaseMediaId
|
||||
join ut in this.DbContext.UserTracks on t.Id equals ut.TrackId
|
||||
var mostPlayedArtist = (from a in DbContext.Artists
|
||||
join r in DbContext.Releases on a.Id equals r.ArtistId
|
||||
join rm in DbContext.ReleaseMedias on r.Id equals rm.ReleaseId
|
||||
join t in DbContext.Tracks on rm.Id equals t.ReleaseMediaId
|
||||
join ut in DbContext.UserTracks on t.Id equals ut.TrackId
|
||||
where ut.UserId == user.Id
|
||||
select new { a, ut.PlayedCount })
|
||||
.GroupBy(a => a.a)
|
||||
.Select(x => new
|
||||
{
|
||||
Artist = x.Key,
|
||||
Played = x.Sum(t => t.PlayedCount)
|
||||
})
|
||||
.OrderByDescending(x => x.Played)
|
||||
.FirstOrDefault();
|
||||
.GroupBy(a => a.a)
|
||||
.Select(x => new
|
||||
{
|
||||
Artist = x.Key,
|
||||
Played = x.Sum(t => t.PlayedCount)
|
||||
})
|
||||
.OrderByDescending(x => x.Played)
|
||||
.FirstOrDefault();
|
||||
|
||||
var mostPlayedReleaseId = (from r in this.DbContext.Releases
|
||||
join rm in this.DbContext.ReleaseMedias on r.Id equals rm.ReleaseId
|
||||
join t in this.DbContext.Tracks on rm.Id equals t.ReleaseMediaId
|
||||
join ut in this.DbContext.UserTracks on t.Id equals ut.TrackId
|
||||
var mostPlayedReleaseId = (from r in DbContext.Releases
|
||||
join rm in DbContext.ReleaseMedias on r.Id equals rm.ReleaseId
|
||||
join t in DbContext.Tracks on rm.Id equals t.ReleaseMediaId
|
||||
join ut in DbContext.UserTracks on t.Id equals ut.TrackId
|
||||
where ut.UserId == user.Id
|
||||
select new { r, ut.PlayedCount })
|
||||
.GroupBy(r => r.r)
|
||||
.Select(x => new
|
||||
{
|
||||
Release = x.Key,
|
||||
Played = x.Sum(t => t.PlayedCount)
|
||||
})
|
||||
.OrderByDescending(x => x.Played)
|
||||
.Select(x => x.Release.RoadieId)
|
||||
.FirstOrDefault();
|
||||
.GroupBy(r => r.r)
|
||||
.Select(x => new
|
||||
{
|
||||
Release = x.Key,
|
||||
Played = x.Sum(t => t.PlayedCount)
|
||||
})
|
||||
.OrderByDescending(x => x.Played)
|
||||
.Select(x => x.Release.RoadieId)
|
||||
.FirstOrDefault();
|
||||
|
||||
var mostPlayedRelease = this.GetRelease(mostPlayedReleaseId);
|
||||
var mostPlayedRelease = GetRelease(mostPlayedReleaseId);
|
||||
|
||||
var mostPlayedTrackUserTrack = userTracks
|
||||
.OrderByDescending(x => x.PlayedCount)
|
||||
.FirstOrDefault();
|
||||
var mostPlayedTrack = mostPlayedTrackUserTrack == null ? null : this.DbContext.Tracks
|
||||
.Include(x => x.TrackArtist)
|
||||
.Include(x => x.ReleaseMedia)
|
||||
.Include("ReleaseMedia.Release")
|
||||
.Include("ReleaseMedia.Release.Artist")
|
||||
.FirstOrDefault(x => x.Id == mostPlayedTrackUserTrack.TrackId);
|
||||
.OrderByDescending(x => x.PlayedCount)
|
||||
.FirstOrDefault();
|
||||
var mostPlayedTrack = mostPlayedTrackUserTrack == null
|
||||
? null
|
||||
: DbContext.Tracks
|
||||
.Include(x => x.TrackArtist)
|
||||
.Include(x => x.ReleaseMedia)
|
||||
.Include("ReleaseMedia.Release")
|
||||
.Include("ReleaseMedia.Release.Artist")
|
||||
.FirstOrDefault(x => x.Id == mostPlayedTrackUserTrack.TrackId);
|
||||
|
||||
model.Statistics = new UserStatistics
|
||||
{
|
||||
MostPlayedArtist = mostPlayedArtist == null ? null : models.ArtistList.FromDataArtist(mostPlayedArtist.Artist, this.MakeArtistThumbnailImage(mostPlayedArtist.Artist.RoadieId)),
|
||||
MostPlayedRelease = mostPlayedRelease == null ? null : models.Releases.ReleaseList.FromDataRelease(mostPlayedRelease,
|
||||
mostPlayedRelease.Artist,
|
||||
this.HttpContext.BaseUrl,
|
||||
this.MakeArtistThumbnailImage(mostPlayedRelease.Artist.RoadieId),
|
||||
this.MakeReleaseThumbnailImage(mostPlayedRelease.RoadieId)),
|
||||
MostPlayedTrack = mostPlayedTrack == null ? null : TrackList.FromDataTrack(this.MakeTrackPlayUrl(user, mostPlayedTrack.Id, mostPlayedTrack.RoadieId),
|
||||
mostPlayedTrack,
|
||||
mostPlayedTrack.ReleaseMedia.MediaNumber,
|
||||
mostPlayedTrack.ReleaseMedia.Release,
|
||||
mostPlayedTrack.ReleaseMedia.Release.Artist,
|
||||
mostPlayedTrack.TrackArtist,
|
||||
this.HttpContext.BaseUrl,
|
||||
this.MakeTrackThumbnailImage(mostPlayedTrack.RoadieId),
|
||||
this.MakeReleaseThumbnailImage(mostPlayedTrack.ReleaseMedia.Release.RoadieId),
|
||||
this.MakeArtistThumbnailImage(mostPlayedTrack.ReleaseMedia.Release.Artist.RoadieId),
|
||||
this.MakeArtistThumbnailImage(mostPlayedTrack.TrackArtist == null ? null : (Guid?)mostPlayedTrack.TrackArtist.RoadieId)),
|
||||
MostPlayedArtist = mostPlayedArtist == null
|
||||
? null
|
||||
: models.ArtistList.FromDataArtist(mostPlayedArtist.Artist,
|
||||
MakeArtistThumbnailImage(mostPlayedArtist.Artist.RoadieId)),
|
||||
MostPlayedRelease = mostPlayedRelease == null
|
||||
? null
|
||||
: ReleaseList.FromDataRelease(mostPlayedRelease,
|
||||
mostPlayedRelease.Artist,
|
||||
HttpContext.BaseUrl,
|
||||
MakeArtistThumbnailImage(mostPlayedRelease.Artist.RoadieId),
|
||||
MakeReleaseThumbnailImage(mostPlayedRelease.RoadieId)),
|
||||
MostPlayedTrack = mostPlayedTrack == null
|
||||
? null
|
||||
: models.TrackList.FromDataTrack(
|
||||
MakeTrackPlayUrl(user, mostPlayedTrack.Id, mostPlayedTrack.RoadieId),
|
||||
mostPlayedTrack,
|
||||
mostPlayedTrack.ReleaseMedia.MediaNumber,
|
||||
mostPlayedTrack.ReleaseMedia.Release,
|
||||
mostPlayedTrack.ReleaseMedia.Release.Artist,
|
||||
mostPlayedTrack.TrackArtist,
|
||||
HttpContext.BaseUrl,
|
||||
MakeTrackThumbnailImage(mostPlayedTrack.RoadieId),
|
||||
MakeReleaseThumbnailImage(mostPlayedTrack.ReleaseMedia.Release.RoadieId),
|
||||
MakeArtistThumbnailImage(mostPlayedTrack.ReleaseMedia.Release.Artist.RoadieId),
|
||||
MakeArtistThumbnailImage(mostPlayedTrack.TrackArtist == null
|
||||
? null
|
||||
: (Guid?)mostPlayedTrack.TrackArtist.RoadieId)),
|
||||
RatedArtists = userArtists.Where(x => x.Rating > 0).Count(),
|
||||
FavoritedArtists = userArtists.Where(x => x.IsFavorite ?? false).Count(),
|
||||
DislikedArtists = userArtists.Where(x => x.IsDisliked ?? false).Count(),
|
||||
|
@ -672,7 +619,6 @@ namespace Roadie.Api.Services
|
|||
DislikedTracks = userTracks.Where(x => x.IsDisliked ?? false).Count()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult(new OperationResult<User>
|
||||
{
|
||||
|
|
|
@ -29,11 +29,11 @@
|
|||
<PackageReference Include="Microsoft.AspNetCore.OData" Version="7.1.0" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.3" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
|
||||
<PackageReference Include="Serilog.Exceptions" Version="5.2.0" />
|
||||
<PackageReference Include="Serilog.Exceptions" Version="5.3.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
||||
<PackageReference Include="Serilog.Sinks.RollingFileAlternate" Version="2.0.9" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.4.0" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.5.0" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.17" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{1BA7
|
|||
roadie.sql = roadie.sql
|
||||
Upgrade0001.sql = Upgrade0001.sql
|
||||
Upgrade0002.sql = Upgrade0002.sql
|
||||
Upgrade0003.sql = Upgrade0003.sql
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Roadie.Api.Services", "Roadie.Api.Services\Roadie.Api.Services.csproj", "{7B37031E-F2AE-4BE2-9F6F-005CA7A6FDF1}"
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
-- Create collection missing table for < 1.0.2.0 database
|
||||
CREATE TABLE `collectionMissing` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`collectionId` int(11) NOT NULL,
|
||||
`isArtistFound` tinyint(1) DEFAULT NULL,
|
||||
`position` int(11) NOT NULL,
|
||||
`artist` varchar(1000) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`release` varchar(1000) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `ix_collection_collectionId` (`collectionId`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
29
roadie.sql
29
roadie.sql
|
@ -1,7 +1,7 @@
|
|||
-- ///
|
||||
-- Roadie version 1.0.1.0 new database script, if upgrading skip this and run Upgrade*.sql scripts from your version to current.
|
||||
-- Roadie version 1.0.2.0 new database script, if upgrading skip this and run Upgrade*.sql scripts from your version to current.
|
||||
-- ///
|
||||
--
|
||||
|
||||
-- MySQL dump 10.17 Distrib 10.3.16-MariaDB, for Linux (x86_64)
|
||||
--
|
||||
-- Host: localhost Database: roadie_dev
|
||||
|
@ -186,6 +186,23 @@ 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;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `collectionMissing`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `collectionMissing`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `collectionMissing` (
|
||||
`collectionId` int(11) NOT NULL,
|
||||
`isArtistFound` tinyint(1) DEFAULT NULL,
|
||||
`position` int(11) NOT NULL,
|
||||
`artist` varchar(1000) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`release` varchar(1000) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
KEY `ix_collection_collectionId` (`collectionId`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
|
@ -212,7 +229,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 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
|
@ -256,7 +273,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 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=54 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
|
@ -282,7 +299,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 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
|
@ -1014,4 +1031,4 @@ SET character_set_client = @saved_cs_client;
|
|||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||
|
||||
-- Dump completed on 2019-06-25 15:15:52
|
||||
-- Dump completed on 2019-06-30 8:12:31
|
||||
|
|
Loading…
Reference in a new issue