mirror of
https://github.com/sphildreth/roadie
synced 2024-11-10 06:44:12 +00:00
Playlist get work.
This commit is contained in:
parent
95e85cf3e4
commit
f0e6fa53ef
13 changed files with 234 additions and 62 deletions
|
@ -29,33 +29,22 @@ namespace Roadie.Api.Controllers
|
|||
this.PlaylistService = playlistService;
|
||||
}
|
||||
|
||||
//[EnableQuery]
|
||||
//public IActionResult Get()
|
||||
//{
|
||||
// return Ok(this._RoadieDbContext.Tracks.ProjectToType<models.Track>());
|
||||
//}
|
||||
|
||||
//[HttpGet("{id}")]
|
||||
//[ProducesResponseType(200)]
|
||||
//[ProducesResponseType(404)]
|
||||
//public IActionResult Get(Guid id)
|
||||
//{
|
||||
// var key = id.ToString();
|
||||
// var result = this._cacheManager.Get<models.Track>(key, () =>
|
||||
// {
|
||||
// var d = this._RoadieDbContext.Tracks.FirstOrDefault(x => x.RoadieId == id);
|
||||
// if (d != null)
|
||||
// {
|
||||
// return d.Adapt<models.Track>();
|
||||
// }
|
||||
// return null;
|
||||
// }, key);
|
||||
// if (result == null)
|
||||
// {
|
||||
// return NotFound();
|
||||
// }
|
||||
// return Ok(result);
|
||||
//}
|
||||
[HttpGet("{id}")]
|
||||
[ProducesResponseType(200)]
|
||||
[ProducesResponseType(404)]
|
||||
public async Task<IActionResult> Get(Guid id, string inc = null)
|
||||
{
|
||||
var result = await this.PlaylistService.ById(await this.CurrentUserModel(), id, (inc ?? models.Playlists.Playlist.DefaultIncludes).ToLower().Split(","));
|
||||
if (result == null || result.IsNotFoundResult)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[ProducesResponseType(200)]
|
||||
|
|
|
@ -31,12 +31,6 @@ namespace Roadie.Api.Controllers
|
|||
this.ReleaseService = releaseService;
|
||||
}
|
||||
|
||||
//[EnableQuery]
|
||||
//public IActionResult Get()
|
||||
//{
|
||||
// return Ok(this._RoadieDbContext.Releases.ProjectToType<models.Releases.Release>());
|
||||
//}
|
||||
|
||||
[HttpGet("{id}")]
|
||||
[ProducesResponseType(200)]
|
||||
[ProducesResponseType(404)]
|
||||
|
|
|
@ -25,8 +25,7 @@ namespace Roadie.Api.Services
|
|||
data.IRoadieDbContext context,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<BookmarkService> logger,
|
||||
ICollectionService collectionService,
|
||||
IPlaylistService playlistService)
|
||||
ICollectionService collectionService)
|
||||
: base(configuration, httpEncoder, context, cacheManager, logger, httpContext)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
using Roadie.Library.Models.Pagination;
|
||||
using Roadie.Library;
|
||||
using Roadie.Library.Models.Pagination;
|
||||
using Roadie.Library.Models.Playlists;
|
||||
using Roadie.Library.Models.Users;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Roadie.Api.Services
|
||||
{
|
||||
public interface IPlaylistService
|
||||
{
|
||||
Task<OperationResult<Playlist>> ById(User roadieUser, Guid id, IEnumerable<string> includes = null);
|
||||
|
||||
Task<PagedResult<PlaylistList>> List(PagedRequest request, User roadieUser = null);
|
||||
}
|
||||
}
|
|
@ -1,10 +1,16 @@
|
|||
using Microsoft.Extensions.Logging;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Roadie.Library;
|
||||
using Roadie.Library.Caching;
|
||||
using Roadie.Library.Configuration;
|
||||
using Roadie.Library.Encoding;
|
||||
using Roadie.Library.Enums;
|
||||
using Roadie.Library.Extensions;
|
||||
using Roadie.Library.Models;
|
||||
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;
|
||||
|
@ -19,16 +25,140 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
public class PlaylistService : ServiceBase, IPlaylistService
|
||||
{
|
||||
private IBookmarkService BookmarkService { get; } = null;
|
||||
|
||||
public PlaylistService(IRoadieSettings configuration,
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext dbContext,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<PlaylistService> logger)
|
||||
ILogger<PlaylistService> logger,
|
||||
IBookmarkService bookmarkService)
|
||||
: base(configuration, httpEncoder, dbContext, cacheManager, logger, httpContext)
|
||||
{
|
||||
this.BookmarkService = bookmarkService;
|
||||
}
|
||||
|
||||
public async Task<OperationResult<Playlist>> ById(User roadieUser, Guid id, IEnumerable<string> includes = null)
|
||||
{
|
||||
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));
|
||||
sw.Stop();
|
||||
if (result?.Data != null && roadieUser != null)
|
||||
{
|
||||
result.Data.UserCanEdit = result.Data.Maintainer.Id == roadieUser.UserId || roadieUser.IsAdmin;
|
||||
var userBookmarkResult = await this.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;
|
||||
}
|
||||
}
|
||||
return new OperationResult<Playlist>(result.Messages)
|
||||
{
|
||||
Data = result?.Data,
|
||||
IsNotFoundResult = result?.IsNotFoundResult ?? false,
|
||||
Errors = result?.Errors,
|
||||
IsSuccess = result?.IsSuccess ?? false,
|
||||
OperationTime = sw.ElapsedMilliseconds
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<OperationResult<Playlist>> PlaylistByIdAction(Guid id, IEnumerable<string> includes = null)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
sw.Start();
|
||||
|
||||
var playlist = this.GetPlaylist(id);
|
||||
|
||||
if (playlist == null)
|
||||
{
|
||||
return 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);
|
||||
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
|
||||
where pl.Id == playlist.Id
|
||||
select new { t, pltr });
|
||||
|
||||
if (includes.Contains("stats"))
|
||||
{
|
||||
result.Statistics = new Library.Models.Statistics.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
|
||||
from trackArtist in tas.DefaultIfEmpty()
|
||||
select new PlaylistTrack
|
||||
{
|
||||
ListNumber = plt.pltr.ListNumber,
|
||||
Track = new TrackList
|
||||
{
|
||||
DatabaseId = plt.t.Id,
|
||||
Id = plt.t.RoadieId,
|
||||
Track = new DataToken
|
||||
{
|
||||
Text = plt.t.Title,
|
||||
Value = plt.t.RoadieId.ToString()
|
||||
},
|
||||
Release = ReleaseList.FromDataRelease(r, releaseArtist, this.HttpContext.BaseUrl, this.MakeArtistThumbnailImage(releaseArtist.RoadieId), this.MakeReleaseThumbnailImage(r.RoadieId)),
|
||||
LastPlayed = plt.t.LastPlayed,
|
||||
Artist = ArtistList.FromDataArtist(releaseArtist, this.MakeArtistThumbnailImage(releaseArtist.RoadieId)),
|
||||
TrackArtist = trackArtist == null ? null : ArtistList.FromDataArtist(trackArtist, this.MakeArtistThumbnailImage(trackArtist.RoadieId)),
|
||||
TrackNumber = plt.t.TrackNumber,
|
||||
MediaNumber = rm.MediaNumber,
|
||||
CreatedDate = plt.t.CreatedDate,
|
||||
LastUpdated = plt.t.LastUpdated,
|
||||
Duration = plt.t.Duration,
|
||||
FileSize = plt.t.FileSize,
|
||||
ReleaseDate = r.ReleaseDate,
|
||||
PlayedCount = plt.t.PlayedCount,
|
||||
Rating = plt.t.Rating,
|
||||
Title = plt.t.Title,
|
||||
TrackPlayUrl = $"{ this.HttpContext.BaseUrl }/play/track/{ plt.t.RoadieId }.mp3",
|
||||
Thumbnail = this.MakeTrackThumbnailImage(plt.t.RoadieId)
|
||||
}
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
return new OperationResult<Playlist>
|
||||
{
|
||||
Data = result,
|
||||
IsSuccess = result != null,
|
||||
OperationTime = sw.ElapsedMilliseconds
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
public async Task<Library.Models.Pagination.PagedResult<PlaylistList>> List(PagedRequest request, User roadieUser = null)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
|
@ -62,16 +192,11 @@ namespace Roadie.Api.Services
|
|||
|
||||
var result = (from pl in this.DbContext.Playlists
|
||||
join u in this.DbContext.Users on pl.UserId equals u.Id
|
||||
let duration = (from plt in this.DbContext.PlaylistTracks
|
||||
join t in this.DbContext.Tracks on plt.TrackId equals t.Id
|
||||
where plt.PlayListId == pl.Id
|
||||
select t.Duration).Sum()
|
||||
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))
|
||||
where (request.FilterValue.Length == 0 || (request.FilterValue.Length > 0 && (pl.Name != null && pl.Name.Contains(request.FilterValue))
|
||||
))
|
||||
select new PlaylistList
|
||||
{
|
||||
|
@ -88,7 +213,8 @@ namespace Roadie.Api.Services
|
|||
},
|
||||
PlaylistCount = this.DbContext.PlaylistTracks.Where(x => x.PlayListId == pl.Id).Count(),
|
||||
IsPublic = pl.IsPublic,
|
||||
Duration = duration,
|
||||
Duration = pl.Duration,
|
||||
TrackCount = pl.TrackCount,
|
||||
CreatedDate = pl.CreatedDate,
|
||||
LastUpdated = pl.LastUpdated,
|
||||
UserThumbnail = MakeUserThumbnailImage(u.RoadieId),
|
||||
|
|
|
@ -159,6 +159,7 @@ namespace Roadie.Api.Services
|
|||
}, data.Release.CacheRegionUrn(id));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get Track by Subsonic Id ("T:guid")
|
||||
/// </summary>
|
||||
|
|
|
@ -228,6 +228,8 @@ namespace Roadie.Api.Services
|
|||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
int? rowCount = null;
|
||||
|
||||
IQueryable<int> favoriteTrackIds = (new int[0]).AsQueryable();
|
||||
if (request.FilterFavoriteOnly)
|
||||
{
|
||||
|
@ -241,7 +243,7 @@ namespace Roadie.Api.Services
|
|||
int[] playlistTrackIds = new int[0];
|
||||
if (request.FilterToPlaylistId.HasValue)
|
||||
{
|
||||
playListTrackPositions = (from plt in this.DbContext.PlaylistTracks
|
||||
var playlistTrackInfos = (from plt in this.DbContext.PlaylistTracks
|
||||
join p in this.DbContext.Playlists on plt.PlayListId equals p.Id
|
||||
join t in this.DbContext.Tracks on plt.TrackId equals t.Id
|
||||
where p.RoadieId == request.FilterToPlaylistId.Value
|
||||
|
@ -250,7 +252,10 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
plt.ListNumber,
|
||||
t.Id
|
||||
}).Skip(request.SkipValue).Take(request.LimitValue).ToDictionary(x => x.Id, x => x.ListNumber);
|
||||
});
|
||||
|
||||
rowCount = playlistTrackInfos.Count();
|
||||
playListTrackPositions = playlistTrackInfos.Skip(request.SkipValue).Take(request.LimitValue).ToDictionary(x => x.Id, x => x.ListNumber);
|
||||
playlistTrackIds = playListTrackPositions.Select(x => x.Key).ToArray();
|
||||
request.Sort = "TrackNumber";
|
||||
request.Order = "ASC";
|
||||
|
@ -434,7 +439,7 @@ namespace Roadie.Api.Services
|
|||
});
|
||||
string sortBy = null;
|
||||
|
||||
var rowCount = result.Count();
|
||||
rowCount = rowCount ?? result.Count();
|
||||
TrackList[] rows = null;
|
||||
|
||||
if (request.Action == User.ActionKeyUserRated)
|
||||
|
@ -491,7 +496,7 @@ namespace Roadie.Api.Services
|
|||
sw.Stop();
|
||||
return new Library.Models.Pagination.PagedResult<TrackList>
|
||||
{
|
||||
TotalCount = rowCount,
|
||||
TotalCount = rowCount ?? 0,
|
||||
CurrentPage = request.PageValue,
|
||||
TotalPages = (int)Math.Ceiling((double)rowCount / request.LimitValue),
|
||||
OperationTime = sw.ElapsedMilliseconds,
|
||||
|
|
|
@ -8,6 +8,9 @@ namespace Roadie.Library.Data
|
|||
[Table("playlist")]
|
||||
public partial class Playlist : NamedEntityBase
|
||||
{
|
||||
[NotMapped]
|
||||
public new string SortName { get; set; }
|
||||
|
||||
[Column("Description")]
|
||||
[MaxLength(1000)]
|
||||
public string Description { get; set; }
|
||||
|
@ -21,5 +24,14 @@ namespace Roadie.Library.Data
|
|||
|
||||
[Column("userId")]
|
||||
public int? UserId { get; set; }
|
||||
|
||||
[Column("duration")]
|
||||
public int? Duration { get; set; } // TODO update this on playlist edit
|
||||
|
||||
[Column("trackCount")]
|
||||
public short TrackCount { get; set; } // TODO update this on playlist edit
|
||||
|
||||
[Column("releaseCount")]
|
||||
public short ReleaseCount { get; set; } // TODO update this on playlist edit
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
using Roadie.Library.Models.Statistics;
|
||||
using Mapster;
|
||||
using Roadie.Library.Models.Statistics;
|
||||
using Roadie.Library.Models.Users;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
@ -6,23 +8,38 @@ using System.Text;
|
|||
namespace Roadie.Library.Models.Playlists
|
||||
{
|
||||
[Serializable]
|
||||
public class Playlist
|
||||
public class Playlist : EntityModelBase
|
||||
{
|
||||
public const string DefaultIncludes = "stats";
|
||||
|
||||
public bool IsPublic { get; set; }
|
||||
/// <summary>
|
||||
/// If true then a system generated playlist - like top 20 played songs last 30 days
|
||||
/// </summary>
|
||||
public bool IsSystemGenerated { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public Guid UserId { get; set; }
|
||||
public UserList Maintainer { get; set; }
|
||||
public IEnumerable<PlaylistTrack> Tracks { get; set; }
|
||||
public IEnumerable<string> Urls { get; set; }
|
||||
public IEnumerable<string> Tags { get; set; }
|
||||
public int? PlaylistCount { get; set; }
|
||||
public string ThumbnailUrl { get; set; }
|
||||
public ReleaseGroupingStatistics Stats { get; set; }
|
||||
public string PlaylistPlayUrl { get; set; }
|
||||
public ReleaseGroupingStatistics Statistics { get; set; }
|
||||
public bool UserCanEdit { get; set; }
|
||||
public string UrlsTokenfield { get; set; }
|
||||
public string TagsTokenfield { get; set; }
|
||||
public Image Thumbnail { get; set; }
|
||||
public string BookmarkRoadieId { get; internal set; }
|
||||
public Image MediumThumbnail { get; set; }
|
||||
public short? TrackCount { get; set; }
|
||||
public short? ReleaseCount { get; set; }
|
||||
public int? Duration { get; set; }
|
||||
public string DurationTime
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!this.Duration.HasValue)
|
||||
{
|
||||
return "--:--";
|
||||
}
|
||||
return TimeSpan.FromSeconds(this.Duration.Value / 1000).ToString(@"dd\.hh\:mm\:ss");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,5 +26,7 @@ namespace Roadie.Library.Models.Playlists
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
public short TrackCount { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace Roadie.Library.Models.Playlists
|
|||
[Serializable]
|
||||
public class PlaylistTrack
|
||||
{
|
||||
public Track Track { get; set; }
|
||||
public TrackList Track { get; set; }
|
||||
public int ListNumber { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,6 @@ namespace Roadie.Library.Models.Statistics
|
|||
public int? ReleaseMediaCount { get; set; }
|
||||
public int? TrackCount { get; set; }
|
||||
public int? TrackPlayedCount { get; set; }
|
||||
public string TrackTime { get; set; }
|
||||
public string TrackSize { get; set; }
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
using Roadie.Library.Models.Statistics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Roadie.Library.Models.Users
|
||||
|
@ -26,5 +27,27 @@ namespace Roadie.Library.Models.Users
|
|||
public bool? IsPrivate { get; set; }
|
||||
|
||||
public UserStatistics Statistics { get; set; }
|
||||
|
||||
public static UserList FromDataUser(Identity.ApplicationUser user, Image thumbnail)
|
||||
{
|
||||
return new UserList
|
||||
{
|
||||
DatabaseId = user.Id,
|
||||
Id = user.RoadieId,
|
||||
User = new DataToken
|
||||
{
|
||||
Text = user.UserName,
|
||||
Value = user.RoadieId.ToString()
|
||||
},
|
||||
IsEditor = user.UserRoles.Any(x => x.Role.Name == "Editor"),
|
||||
IsPrivate = user.IsPrivate,
|
||||
Thumbnail = thumbnail,
|
||||
CreatedDate = user.CreatedDate,
|
||||
LastUpdated = user.LastUpdated,
|
||||
RegisteredDate = user.RegisteredOn,
|
||||
LastLoginDate = user.LastLogin,
|
||||
LastApiAccessDate = user.LastApiAccess
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue