mirror of
https://github.com/sphildreth/roadie
synced 2024-11-22 12:13:10 +00:00
Merge work
This commit is contained in:
parent
d4485d08a7
commit
5acad5d4b6
9 changed files with 221 additions and 45 deletions
|
@ -396,16 +396,17 @@ namespace Roadie.Api.Services
|
|||
var newArtists = 0;
|
||||
var newReleases = 0;
|
||||
var newTracks = 0;
|
||||
OperationResult<bool> result = null;
|
||||
foreach (var folder in Directory.EnumerateDirectories(d.FullName).ToArray())
|
||||
{
|
||||
var result = await folderProcessor.Process(new DirectoryInfo(folder), isReadOnly);
|
||||
result = await folderProcessor.Process(new DirectoryInfo(folder), isReadOnly);
|
||||
processedFolders++;
|
||||
}
|
||||
if (result.AdditionalData != null)
|
||||
{
|
||||
newArtists += SafeParser.ToNumber<int>(result.AdditionalData["newArtists"]);
|
||||
newReleases += SafeParser.ToNumber<int>(result.AdditionalData["newReleases"]);
|
||||
newTracks += SafeParser.ToNumber<int>(result.AdditionalData["newTracks"]);
|
||||
}
|
||||
processedFolders++;
|
||||
newArtists = SafeParser.ToNumber<int>(result.AdditionalData["newArtists"]);
|
||||
newReleases = SafeParser.ToNumber<int>(result.AdditionalData["newReleases"]);
|
||||
newTracks = SafeParser.ToNumber<int>(result.AdditionalData["newTracks"]);
|
||||
}
|
||||
if (!isReadOnly)
|
||||
{
|
||||
|
|
|
@ -544,6 +544,53 @@ namespace Roadie.Api.Services
|
|||
};
|
||||
}
|
||||
|
||||
public async Task<OperationResult<bool>> MergeArtists(User user, Guid artistToMergeId, Guid artistToMergeIntoId)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
var errors = new List<Exception>();
|
||||
var artistToMerge = this.GetArtist(artistToMergeId);
|
||||
if (artistToMerge == null)
|
||||
{
|
||||
this.Logger.LogWarning("MergeArtists Unknown Artist [{0}]", artistToMergeId);
|
||||
return new OperationResult<bool>(true, string.Format("Artist Not Found [{0}]", artistToMergeId));
|
||||
}
|
||||
var mergeIntoArtist = this.GetArtist(artistToMergeIntoId);
|
||||
if (mergeIntoArtist == null)
|
||||
{
|
||||
this.Logger.LogWarning("MergeArtists Unknown Artist [{0}]", artistToMergeIntoId);
|
||||
return new OperationResult<bool>(true, string.Format("Artist Not Found [{0}]", artistToMergeIntoId));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var result = await this.ArtistFactory.MergeArtists(artistToMerge, mergeIntoArtist, true);
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
this.CacheManager.ClearRegion(artistToMerge.CacheRegion);
|
||||
this.CacheManager.ClearRegion(mergeIntoArtist.CacheRegion);
|
||||
this.Logger.LogInformation("MergeArtists `{0}` => `{1}`, By User `{2}`", artistToMerge, mergeIntoArtist, user);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex);
|
||||
errors.Add(ex);
|
||||
}
|
||||
sw.Stop();
|
||||
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
IsSuccess = !errors.Any(),
|
||||
Data = !errors.Any(),
|
||||
OperationTime = sw.ElapsedMilliseconds,
|
||||
Errors = errors
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
public async Task<OperationResult<Library.Models.Image>> UploadArtistImage(User user, Guid id, IFormFile file)
|
||||
{
|
||||
var bytes = new byte[0];
|
||||
|
|
|
@ -20,5 +20,7 @@ namespace Roadie.Api.Services
|
|||
Task<OperationResult<bool>> UpdateArtist(User user, Artist artist);
|
||||
|
||||
Task<OperationResult<Library.Models.Image>> UploadArtistImage(User user, Guid id, IFormFile file);
|
||||
|
||||
Task<OperationResult<bool>> MergeArtists(User user, Guid artistToMergeId, Guid artistToMergeIntoId);
|
||||
}
|
||||
}
|
|
@ -22,5 +22,7 @@ namespace Roadie.Api.Services
|
|||
Task<OperationResult<bool>> UpdateRelease(User user, Release release);
|
||||
|
||||
Task<OperationResult<Library.Models.Image>> UploadReleaseImage(User user, Guid id, IFormFile file);
|
||||
|
||||
Task<OperationResult<bool>> MergeReleases(User user, Guid releaseToMergeId, Guid releaseToMergeIntoId, bool addAsMedia);
|
||||
}
|
||||
}
|
|
@ -678,6 +678,45 @@ namespace Roadie.Api.Services
|
|||
};
|
||||
}
|
||||
|
||||
public async Task<OperationResult<bool>> MergeReleases(User user, Guid releaseToMergeId, Guid releaseToMergeIntoId, bool addAsMedia)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
var errors = new List<Exception>();
|
||||
var releaseToMerge = this.GetRelease(releaseToMergeId);
|
||||
if (releaseToMerge == null)
|
||||
{
|
||||
this.Logger.LogWarning("MergeReleases Unknown Release [{0}]", releaseToMergeId);
|
||||
return new OperationResult<bool>(true, string.Format("Release Not Found [{0}]", releaseToMergeId));
|
||||
}
|
||||
var releaseToMergeInfo = this.GetRelease(releaseToMergeIntoId);
|
||||
if (releaseToMergeInfo == null)
|
||||
{
|
||||
this.Logger.LogWarning("MergeReleases Unknown Release [{0}]", releaseToMergeIntoId);
|
||||
return new OperationResult<bool>(true, string.Format("Release Not Found [{0}]", releaseToMergeIntoId));
|
||||
}
|
||||
try
|
||||
{
|
||||
await this.ReleaseFactory.MergeReleases(releaseToMerge, releaseToMergeInfo, addAsMedia);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex);
|
||||
errors.Add(ex);
|
||||
}
|
||||
sw.Stop();
|
||||
this.Logger.LogInformation("MergeReleases Release `{0}` Merged Into Release `{1}`, By User `{2}`", releaseToMerge, releaseToMergeInfo, user);
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
IsSuccess = !errors.Any(),
|
||||
Data = !errors.Any(),
|
||||
OperationTime = sw.ElapsedMilliseconds,
|
||||
Errors = errors
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public async Task<OperationResult<Library.Models.Image>> UploadReleaseImage(User user, Guid id, IFormFile file)
|
||||
{
|
||||
var bytes = new byte[0];
|
||||
|
|
|
@ -209,6 +209,7 @@ namespace Roadie.Api.Services
|
|||
return null;
|
||||
}
|
||||
|
||||
// Only read operations
|
||||
protected data.Track GetTrack(Guid id)
|
||||
{
|
||||
return this.CacheManager.Get(data.Track.CacheUrn(id), () =>
|
||||
|
@ -324,11 +325,15 @@ namespace Roadie.Api.Services
|
|||
|
||||
protected async Task<OperationResult<short>> SetArtistRating(Guid artistId, ApplicationUser user, short rating)
|
||||
{
|
||||
var artist = this.GetArtist(artistId);
|
||||
var artist = this.DbContext.Artists
|
||||
.Include(x => x.Genres)
|
||||
.Include("Genres.Genre")
|
||||
.FirstOrDefault(x => x.RoadieId == artistId);
|
||||
if (artist == null)
|
||||
{
|
||||
return new OperationResult<short>(true, $"Invalid Artist Id [{ artistId }]");
|
||||
}
|
||||
var now = DateTime.UtcNow;
|
||||
var userArtist = this.DbContext.UserArtists.FirstOrDefault(x => x.ArtistId == artist.Id && x.UserId == user.Id);
|
||||
if (userArtist == null)
|
||||
{
|
||||
|
@ -343,15 +348,13 @@ namespace Roadie.Api.Services
|
|||
else
|
||||
{
|
||||
userArtist.Rating = rating;
|
||||
userArtist.LastUpdated = DateTime.UtcNow;
|
||||
userArtist.LastUpdated = now;
|
||||
}
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
|
||||
var sql = "UPDATE `artist` set lastUpdated = UTC_DATE(), rating = (SELECT cast(avg(ur.rating) as signed) " +
|
||||
"FROM `userartist` ur " +
|
||||
"where artistId = {0}) " +
|
||||
"WHERE id = {0};";
|
||||
await this.DbContext.Database.ExecuteSqlCommandAsync(sql, artist.Id);
|
||||
artist.Rating = (short)this.DbContext.UserArtists.Where(x => x.ArtistId == artist.Id && x.Rating > 0).Average(x => (decimal)x.Rating);
|
||||
artist.LastUpdated = now;
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
|
||||
this.CacheManager.ClearRegion(user.CacheRegion);
|
||||
this.CacheManager.ClearRegion(artist.CacheRegion);
|
||||
|
@ -367,7 +370,14 @@ namespace Roadie.Api.Services
|
|||
|
||||
protected async Task<OperationResult<short>> SetReleaseRating(Guid releaseId, ApplicationUser user, short rating)
|
||||
{
|
||||
var release = this.GetRelease(releaseId);
|
||||
var release = this.DbContext.Releases
|
||||
.Include(x => x.Artist)
|
||||
.Include(x => x.Genres)
|
||||
.Include("Genres.Genre")
|
||||
.Include(x => x.Medias)
|
||||
.Include("Medias.Tracks")
|
||||
.Include("Medias.Tracks.TrackArtist")
|
||||
.FirstOrDefault(x => x.RoadieId == releaseId);
|
||||
if (release == null)
|
||||
{
|
||||
return new OperationResult<short>(true, $"Invalid Release Id [{ releaseId }]");
|
||||
|
@ -391,11 +401,9 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
|
||||
var sql = "UPDATE `release` set lastUpdated = UTC_DATE(), rating = (SELECT cast(avg(ur.rating) as signed) " +
|
||||
"FROM `userrelease` ur " +
|
||||
"where releaseId = {0}) " +
|
||||
"WHERE id = {0};";
|
||||
await this.DbContext.Database.ExecuteSqlCommandAsync(sql, release.Id);
|
||||
release.Rating = (short)this.DbContext.UserReleases.Where(x => x.ReleaseId == release.Id && x.Rating > 0).Average(x => (decimal)x.Rating);
|
||||
release.LastUpdated = now;
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
|
||||
this.CacheManager.ClearRegion(user.CacheRegion);
|
||||
this.CacheManager.ClearRegion(release.CacheRegion);
|
||||
|
@ -412,11 +420,17 @@ namespace Roadie.Api.Services
|
|||
|
||||
protected async Task<OperationResult<short>> SetTrackRating(Guid trackId, ApplicationUser user, short rating)
|
||||
{
|
||||
var track = this.GetTrack(trackId);
|
||||
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 == trackId);
|
||||
if (track == null)
|
||||
{
|
||||
return new OperationResult<short>(true, $"Invalid Track Id [{ trackId }]");
|
||||
}
|
||||
var now = DateTime.UtcNow;
|
||||
var userTrack = this.DbContext.UserTracks.FirstOrDefault(x => x.TrackId == track.Id && x.UserId == user.Id);
|
||||
if (userTrack == null)
|
||||
{
|
||||
|
@ -431,15 +445,13 @@ namespace Roadie.Api.Services
|
|||
else
|
||||
{
|
||||
userTrack.Rating = rating;
|
||||
userTrack.LastUpdated = DateTime.UtcNow;
|
||||
userTrack.LastUpdated = now;
|
||||
}
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
|
||||
var sql = "UPDATE `track` set lastUpdated = UTC_DATE(), rating = (SELECT cast(avg(ur.rating) as signed) " +
|
||||
"FROM `usertrack` ur " +
|
||||
"where trackId = {0}) " +
|
||||
"WHERE id = {0};";
|
||||
await this.DbContext.Database.ExecuteSqlCommandAsync(sql, track.Id);
|
||||
track.Rating = (short)this.DbContext.UserTracks.Where(x => x.TrackId == track.Id && x.Rating > 0).Average(x => (decimal)x.Rating);
|
||||
track.LastUpdated = now;
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
|
||||
this.CacheManager.ClearRegion(user.CacheRegion);
|
||||
this.CacheManager.ClearRegion(track.CacheRegion);
|
||||
|
@ -457,7 +469,10 @@ namespace Roadie.Api.Services
|
|||
|
||||
protected async Task<OperationResult<bool>> ToggleArtistDisliked(Guid artistId, ApplicationUser user, bool isDisliked)
|
||||
{
|
||||
var artist = this.GetArtist(artistId);
|
||||
var artist = this.DbContext.Artists
|
||||
.Include(x => x.Genres)
|
||||
.Include("Genres.Genre")
|
||||
.FirstOrDefault(x => x.RoadieId == artistId);
|
||||
if (artist == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid Artist Id [{ artistId }]");
|
||||
|
@ -492,7 +507,10 @@ namespace Roadie.Api.Services
|
|||
|
||||
protected async Task<OperationResult<bool>> ToggleArtistFavorite(Guid artistId, ApplicationUser user, bool isFavorite)
|
||||
{
|
||||
var artist = this.GetArtist(artistId);
|
||||
var artist = this.DbContext.Artists
|
||||
.Include(x => x.Genres)
|
||||
.Include("Genres.Genre")
|
||||
.FirstOrDefault(x => x.RoadieId == artistId);
|
||||
if (artist == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid Artist Id [{ artistId }]");
|
||||
|
@ -527,7 +545,14 @@ namespace Roadie.Api.Services
|
|||
|
||||
protected async Task<OperationResult<bool>> ToggleReleaseDisliked(Guid releaseId, ApplicationUser user, bool isDisliked)
|
||||
{
|
||||
var release = this.GetRelease(releaseId);
|
||||
var release = this.DbContext.Releases
|
||||
.Include(x => x.Artist)
|
||||
.Include(x => x.Genres)
|
||||
.Include("Genres.Genre")
|
||||
.Include(x => x.Medias)
|
||||
.Include("Medias.Tracks")
|
||||
.Include("Medias.Tracks.TrackArtist")
|
||||
.FirstOrDefault(x => x.RoadieId == releaseId);
|
||||
if (release == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid Release Id [{ releaseId }]");
|
||||
|
@ -563,7 +588,14 @@ namespace Roadie.Api.Services
|
|||
|
||||
protected async Task<OperationResult<bool>> ToggleReleaseFavorite(Guid releaseId, ApplicationUser user, bool isFavorite)
|
||||
{
|
||||
var release = this.GetRelease(releaseId);
|
||||
var release = this.DbContext.Releases
|
||||
.Include(x => x.Artist)
|
||||
.Include(x => x.Genres)
|
||||
.Include("Genres.Genre")
|
||||
.Include(x => x.Medias)
|
||||
.Include("Medias.Tracks")
|
||||
.Include("Medias.Tracks.TrackArtist")
|
||||
.FirstOrDefault(x => x.RoadieId == releaseId);
|
||||
if (release == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid Release Id [{ releaseId }]");
|
||||
|
@ -599,7 +631,12 @@ namespace Roadie.Api.Services
|
|||
|
||||
protected async Task<OperationResult<bool>> ToggleTrackDisliked(Guid trackId, ApplicationUser user, bool isDisliked)
|
||||
{
|
||||
var track = this.GetTrack(trackId);
|
||||
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 == trackId);
|
||||
if (track == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid Track Id [{ trackId }]");
|
||||
|
@ -636,7 +673,12 @@ namespace Roadie.Api.Services
|
|||
|
||||
protected async Task<OperationResult<bool>> ToggleTrackFavorite(Guid trackId, ApplicationUser user, bool isFavorite)
|
||||
{
|
||||
var track = this.GetTrack(trackId);
|
||||
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 == trackId);
|
||||
if (track == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, $"Invalid Track Id [{ trackId }]");
|
||||
|
|
|
@ -20,6 +20,7 @@ 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
|
||||
|
@ -533,7 +534,6 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
if (includes.Contains("stats"))
|
||||
{
|
||||
|
||||
var userArtists = this.DbContext.UserArtists.Include(x => x.Artist).Where(x => x.UserId == user.Id).ToArray();
|
||||
var userReleases = this.DbContext.UserReleases.Include(x => x.Release).Where(x => x.UserId == user.Id).ToArray();
|
||||
var userTracks = this.DbContext.UserTracks.Include(x => x.Track).Where(x => x.UserId == user.Id).ToArray();
|
||||
|
@ -546,7 +546,8 @@ namespace Roadie.Api.Services
|
|||
where ut.UserId == user.Id
|
||||
select new { a, ut.PlayedCount })
|
||||
.GroupBy(a => a.a)
|
||||
.Select(x => new {
|
||||
.Select(x => new
|
||||
{
|
||||
Artist = x.Key,
|
||||
Played = x.Sum(t => t.PlayedCount)
|
||||
})
|
||||
|
@ -560,7 +561,8 @@ namespace Roadie.Api.Services
|
|||
where ut.UserId == user.Id
|
||||
select new { r, ut.PlayedCount })
|
||||
.GroupBy(r => r.r)
|
||||
.Select(x => new {
|
||||
.Select(x => new
|
||||
{
|
||||
Release = x.Key,
|
||||
Played = x.Sum(t => t.PlayedCount)
|
||||
})
|
||||
|
|
|
@ -68,9 +68,29 @@ namespace Roadie.Api.Controllers
|
|||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpPost("mergeArtists/{artistToMergeId}/{artistToMergeIntoId}")]
|
||||
[ProducesResponseType(200)]
|
||||
[ProducesResponseType(404)]
|
||||
[Authorize(Policy = "Editor")]
|
||||
public async Task<IActionResult> MergeArtists(Guid artistToMergeId, Guid artistToMergeIntoId)
|
||||
{
|
||||
var result = await this.ArtistService.MergeArtists(await this.CurrentUserModel(), artistToMergeId, artistToMergeIntoId);
|
||||
if (result == null || result.IsNotFoundResult)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
|
||||
[HttpPost("setImageByUrl/{id}/{imageUrl}")]
|
||||
[ProducesResponseType(200)]
|
||||
[ProducesResponseType(404)]
|
||||
[Authorize(Policy = "Editor")]
|
||||
public async Task<IActionResult> SetArtistImageByUrl(Guid id, string imageUrl)
|
||||
{
|
||||
var result = await this.ArtistService.SetReleaseImageByUrl(await this.CurrentUserModel(), id, HttpUtility.UrlDecode(imageUrl));
|
||||
|
@ -88,6 +108,7 @@ namespace Roadie.Api.Controllers
|
|||
[HttpPost("uploadImage/{id}")]
|
||||
[ProducesResponseType(200)]
|
||||
[ProducesResponseType(404)]
|
||||
[Authorize(Policy = "Editor")]
|
||||
public async Task<IActionResult> UploadImage(Guid id, IFormFile file)
|
||||
{
|
||||
var result = await this.ArtistService.UploadArtistImage(await this.CurrentUserModel(), id, file);
|
||||
|
|
|
@ -50,6 +50,24 @@ namespace Roadie.Api.Controllers
|
|||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpPost("mergeReleases/{releaseToMergeId}/{releaseToMergeIntoId}")]
|
||||
[ProducesResponseType(200)]
|
||||
[ProducesResponseType(404)]
|
||||
[Authorize(Policy = "Editor")]
|
||||
public async Task<IActionResult> MergeReleases(Guid releaseToMergeId, Guid releaseToMergeIntoId, bool addAsMedia)
|
||||
{
|
||||
var result = await this.ReleaseService.MergeReleases(await this.CurrentUserModel(), releaseToMergeId, releaseToMergeIntoId, addAsMedia);
|
||||
if (result == null || result.IsNotFoundResult)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpPost("edit")]
|
||||
[ProducesResponseType(200)]
|
||||
[ProducesResponseType(404)]
|
||||
|
@ -98,6 +116,7 @@ namespace Roadie.Api.Controllers
|
|||
[HttpPost("setImageByUrl/{id}/{imageUrl}")]
|
||||
[ProducesResponseType(200)]
|
||||
[ProducesResponseType(404)]
|
||||
[Authorize(Policy = "Editor")]
|
||||
public async Task<IActionResult> SetReleaseImageByUrl(Guid id, string imageUrl)
|
||||
{
|
||||
var result = await this.ReleaseService.SetReleaseImageByUrl(await this.CurrentUserModel(), id, HttpUtility.UrlDecode(imageUrl));
|
||||
|
@ -115,6 +134,7 @@ namespace Roadie.Api.Controllers
|
|||
[HttpPost("uploadImage/{id}")]
|
||||
[ProducesResponseType(200)]
|
||||
[ProducesResponseType(404)]
|
||||
[Authorize(Policy = "Editor")]
|
||||
public async Task<IActionResult> UploadImage(Guid id, IFormFile file)
|
||||
{
|
||||
var result = await this.ReleaseService.UploadReleaseImage(await this.CurrentUserModel(), id, file);
|
||||
|
|
Loading…
Reference in a new issue