mirror of
https://github.com/sphildreth/roadie
synced 2024-11-21 19:53:11 +00:00
Removed Image table definition, resolves #34
This commit is contained in:
parent
82544c143b
commit
818afd2eb0
25 changed files with 380 additions and 567 deletions
|
@ -22,7 +22,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="2.4.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace Roadie.Library.Configuration
|
|||
{
|
||||
public enum DbContexts : short
|
||||
{
|
||||
MySQL = 1
|
||||
MySQL = 1,
|
||||
File = 2
|
||||
}
|
||||
}
|
||||
|
|
14
Roadie.Api.Library/Configuration/FileDatabaseFormat.cs
Normal file
14
Roadie.Api.Library/Configuration/FileDatabaseFormat.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Roadie.Library.Configuration
|
||||
{
|
||||
public enum FileDatabaseFormat
|
||||
{
|
||||
JSON,
|
||||
BSON,
|
||||
XML,
|
||||
CSV
|
||||
}
|
||||
}
|
25
Roadie.Api.Library/Configuration/FileDatabaseOptions.cs
Normal file
25
Roadie.Api.Library/Configuration/FileDatabaseOptions.cs
Normal file
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Roadie.Library.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// Options specific when using a FileDatabase DbContext.
|
||||
/// </summary>
|
||||
public sealed class FileDatabaseOptions : IFileDatabaseOptions
|
||||
{
|
||||
public FileDatabaseFormat DatabaseFormat { get; set; }
|
||||
|
||||
public string DatabaseName { get; set; }
|
||||
|
||||
public string DatabaseFolder { get; set; }
|
||||
|
||||
public FileDatabaseOptions()
|
||||
{
|
||||
DatabaseFormat = FileDatabaseFormat.BSON;
|
||||
DatabaseName = "roadie";
|
||||
DatabaseFolder = @"M:\db";
|
||||
}
|
||||
}
|
||||
}
|
8
Roadie.Api.Library/Configuration/IFileDatabaseOptions.cs
Normal file
8
Roadie.Api.Library/Configuration/IFileDatabaseOptions.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace Roadie.Library.Configuration
|
||||
{
|
||||
public interface IFileDatabaseOptions
|
||||
{
|
||||
string DatabaseFolder { get; set; }
|
||||
FileDatabaseFormat DatabaseFormat { get; set; }
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ namespace Roadie.Library.Configuration
|
|||
string ConnectionString { get; set; }
|
||||
string ContentPath { get; set; }
|
||||
Converting Converting { get; set; }
|
||||
FileDatabaseOptions FileDatabaseOptions { get; set; }
|
||||
short DefaultRowsPerPage { get; set; }
|
||||
string DefaultTimeZone { get; set; }
|
||||
Dlna Dlna { get; set; }
|
||||
|
|
|
@ -37,6 +37,8 @@ namespace Roadie.Library.Configuration
|
|||
|
||||
public Converting Converting { get; set; }
|
||||
|
||||
public FileDatabaseOptions FileDatabaseOptions { get; set; }
|
||||
|
||||
public short DefaultRowsPerPage { get; set; }
|
||||
public string DefaultTimeZone { get; set; }
|
||||
|
||||
|
@ -175,6 +177,7 @@ namespace Roadie.Library.Configuration
|
|||
|
||||
Inspector = new Inspector();
|
||||
Converting = new Converting();
|
||||
FileDatabaseOptions = new FileDatabaseOptions();
|
||||
Integrations = new Integrations();
|
||||
Processing = new Processing();
|
||||
Dlna = new Dlna();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using FileContextCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Pomelo.EntityFrameworkCore.MySql.Infrastructure;
|
||||
using Roadie.Library.Configuration;
|
||||
using Roadie.Library.Data.Context.Implementation;
|
||||
|
@ -12,6 +13,13 @@ namespace Roadie.Library.Data.Context
|
|||
{
|
||||
switch (configuration.DbContextToUse)
|
||||
{
|
||||
case DbContexts.File:
|
||||
var fileOptionsBuilder = new DbContextOptionsBuilder<MySQLRoadieDbContext>();
|
||||
fileOptionsBuilder.UseFileContextDatabase(configuration.FileDatabaseOptions.DatabaseFormat.ToString().ToLower(),
|
||||
databaseName: configuration.FileDatabaseOptions.DatabaseName,
|
||||
location: configuration.FileDatabaseOptions.DatabaseFolder);
|
||||
return new FileRoadieDbContext(fileOptionsBuilder.Options);
|
||||
|
||||
default:
|
||||
var mysqlOptionsBuilder = new DbContextOptionsBuilder<MySQLRoadieDbContext>();
|
||||
mysqlOptionsBuilder.UseMySql(configuration.ConnectionString, mySqlOptions =>
|
||||
|
|
|
@ -26,7 +26,6 @@ namespace Roadie.Library.Data.Context
|
|||
DbSet<Comment> Comments { get; set; }
|
||||
DatabaseFacade Database { get; }
|
||||
DbSet<Genre> Genres { get; set; }
|
||||
DbSet<Image> Images { get; set; }
|
||||
DbSet<Label> Labels { get; set; }
|
||||
DbSet<Playlist> Playlists { get; set; }
|
||||
DbSet<PlaylistTrack> PlaylistTracks { get; set; }
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Roadie.Library.Data.Context.Implementation
|
||||
{
|
||||
/// <summary>
|
||||
/// File based Context using FileContextCore
|
||||
/// <seealso cref="https://github.com/morrisjdev/FileContextCore"/>
|
||||
/// </summary>
|
||||
public sealed class FileRoadieDbContext : LinqDbContextBase
|
||||
{
|
||||
public FileRoadieDbContext(DbContextOptions options)
|
||||
: base(options)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,210 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Roadie.Library.Data.Context.Implementation
|
||||
{
|
||||
/// <summary>
|
||||
/// Base DbContext using just LINQ statements against EF
|
||||
/// </summary>
|
||||
public abstract class LinqDbContextBase : RoadieDbContext
|
||||
{
|
||||
public LinqDbContextBase(DbContextOptions options)
|
||||
: base(options)
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task<Artist> LastPlayedArtist(int userId)
|
||||
{
|
||||
return await (from ut in UserTracks
|
||||
join t in Tracks on ut.TrackId equals t.Id
|
||||
join rm in ReleaseMedias on t.ReleaseMediaId equals rm.Id
|
||||
join r in Releases on rm.ReleaseId equals r.Id
|
||||
join a in Artists on r.ArtistId equals a.Id
|
||||
where ut.UserId == userId
|
||||
orderby ut.LastPlayed descending
|
||||
select a).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public override async Task<Release> LastPlayedRelease(int userId)
|
||||
{
|
||||
return await (from ut in UserTracks
|
||||
join t in Tracks on ut.TrackId equals t.Id
|
||||
join rm in ReleaseMedias on t.ReleaseMediaId equals rm.Id
|
||||
join r in Releases on rm.ReleaseId equals r.Id
|
||||
where ut.UserId == userId
|
||||
orderby ut.LastPlayed descending
|
||||
select r).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public override async Task<Track> LastPlayedTrack(int userId)
|
||||
{
|
||||
return await (from ut in UserTracks
|
||||
join t in Tracks on ut.TrackId equals t.Id
|
||||
where ut.UserId == userId
|
||||
orderby ut.LastPlayed descending
|
||||
select t).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public override async Task<Artist> MostPlayedArtist(int userId)
|
||||
{
|
||||
var mostPlayedTrack = await MostPlayedTrack(userId);
|
||||
if (mostPlayedTrack != null)
|
||||
{
|
||||
return await (from t in Tracks
|
||||
join rm in ReleaseMedias on t.ReleaseMediaId equals rm.Id
|
||||
join r in Releases on rm.ReleaseId equals r.Id
|
||||
join a in Artists on r.ArtistId equals a.Id
|
||||
where t.Id == mostPlayedTrack.Id
|
||||
select a).FirstOrDefaultAsync();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override async Task<Release> MostPlayedRelease(int userId)
|
||||
{
|
||||
var mostPlayedTrack = await MostPlayedTrack(userId);
|
||||
if (mostPlayedTrack != null)
|
||||
{
|
||||
return await (from t in Tracks
|
||||
join rm in ReleaseMedias on t.ReleaseMediaId equals rm.Id
|
||||
join r in Releases on rm.ReleaseId equals r.Id
|
||||
where t.Id == mostPlayedTrack.Id
|
||||
select r).FirstOrDefaultAsync();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override async Task<Track> MostPlayedTrack(int userId)
|
||||
{
|
||||
return await (from ut in UserTracks
|
||||
join t in Tracks on ut.TrackId equals t.Id
|
||||
where ut.UserId == userId
|
||||
orderby ut.PlayedCount descending
|
||||
select t).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public override async Task<SortedDictionary<int, int>> RandomArtistIds(int userId, int randomLimit, bool doOnlyFavorites = false, bool doOnlyRated = false)
|
||||
{
|
||||
List<Artist> randomArtists = null;
|
||||
if (doOnlyFavorites)
|
||||
{
|
||||
randomArtists = await (from ua in UserArtists
|
||||
join a in Artists on ua.ArtistId equals a.Id
|
||||
where ua.UserId == userId
|
||||
where ua.IsFavorite == true
|
||||
select a
|
||||
).OrderBy(x => Guid.NewGuid())
|
||||
.Take(randomLimit)
|
||||
.ToListAsync();
|
||||
}
|
||||
else if (doOnlyRated)
|
||||
{
|
||||
randomArtists = await (from ua in UserArtists
|
||||
join a in Artists on ua.ArtistId equals a.Id
|
||||
where ua.UserId == userId
|
||||
where ua.Rating > 0
|
||||
select a
|
||||
).OrderBy(x => Guid.NewGuid())
|
||||
.Take(randomLimit)
|
||||
.ToListAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
randomArtists = await Artists.OrderBy(x => Guid.NewGuid())
|
||||
.Take(randomLimit)
|
||||
.ToListAsync();
|
||||
}
|
||||
var dict = randomArtists.Select((x, i) => new { key = i, value = x.Id }).Take(randomLimit).ToDictionary(x => x.key, x => x.value);
|
||||
return new SortedDictionary<int, int>(dict);
|
||||
}
|
||||
|
||||
public override async Task<SortedDictionary<int, int>> RandomGenreIds(int userId, int randomLimit, bool doOnlyFavorites = false, bool doOnlyRated = false)
|
||||
{
|
||||
var randomGenres = await Genres.OrderBy(x => Guid.NewGuid())
|
||||
.Take(randomLimit)
|
||||
.ToListAsync();
|
||||
var dict = randomGenres.Select((x, i) => new { key = i, value = x.Id }).Take(randomLimit).ToDictionary(x => x.key, x => x.value);
|
||||
return new SortedDictionary<int, int>(dict);
|
||||
}
|
||||
|
||||
public override async Task<SortedDictionary<int, int>> RandomLabelIds(int userId, int randomLimit, bool doOnlyFavorites = false, bool doOnlyRated = false)
|
||||
{
|
||||
var randomLabels = await Labels.OrderBy(x => Guid.NewGuid()).Take(randomLimit).ToListAsync();
|
||||
var dict = randomLabels.Select((x, i) => new { key = i, value = x.Id }).Take(randomLimit).ToDictionary(x => x.key, x => x.value);
|
||||
return new SortedDictionary<int, int>(dict);
|
||||
}
|
||||
|
||||
public override async Task<SortedDictionary<int, int>> RandomReleaseIds(int userId, int randomLimit, bool doOnlyFavorites = false, bool doOnlyRated = false)
|
||||
{
|
||||
List<Release> randomReleases = null;
|
||||
if (doOnlyFavorites)
|
||||
{
|
||||
randomReleases = await (from ur in UserReleases
|
||||
join r in Releases on ur.ReleaseId equals r.Id
|
||||
where ur.UserId == userId
|
||||
where ur.IsFavorite == true
|
||||
select r
|
||||
).OrderBy(x => Guid.NewGuid())
|
||||
.Take(randomLimit)
|
||||
.ToListAsync();
|
||||
}
|
||||
else if (doOnlyRated)
|
||||
{
|
||||
randomReleases = await (from ur in UserReleases
|
||||
join r in Releases on ur.ReleaseId equals r.Id
|
||||
where ur.UserId == userId
|
||||
where ur.Rating > 0
|
||||
select r
|
||||
).OrderBy(x => Guid.NewGuid())
|
||||
.Take(randomLimit)
|
||||
.ToListAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
randomReleases = await Releases.OrderBy(x => Guid.NewGuid())
|
||||
.Take(randomLimit)
|
||||
.ToListAsync();
|
||||
}
|
||||
var dict = randomReleases.Select((x, i) => new { key = i, value = x.Id }).Take(randomLimit).ToDictionary(x => x.key, x => x.value);
|
||||
return new SortedDictionary<int, int>(dict);
|
||||
}
|
||||
|
||||
public override async Task<SortedDictionary<int, int>> RandomTrackIds(int userId, int randomLimit, bool doOnlyFavorites = false, bool doOnlyRated = false)
|
||||
{
|
||||
List<Track> randomTracks = null;
|
||||
if (doOnlyFavorites)
|
||||
{
|
||||
randomTracks = await (from ut in UserTracks
|
||||
join t in Tracks on ut.TrackId equals t.Id
|
||||
where ut.UserId == userId
|
||||
where ut.IsFavorite == true
|
||||
select t
|
||||
).OrderBy(x => Guid.NewGuid())
|
||||
.Take(randomLimit)
|
||||
.ToListAsync();
|
||||
}
|
||||
else if (doOnlyRated)
|
||||
{
|
||||
randomTracks = await (from ut in UserTracks
|
||||
join t in Tracks on ut.TrackId equals t.Id
|
||||
where ut.UserId == userId
|
||||
where ut.Rating > 0
|
||||
select t
|
||||
).OrderBy(x => Guid.NewGuid())
|
||||
.Take(randomLimit)
|
||||
.ToListAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
randomTracks = await Tracks.OrderBy(x => Guid.NewGuid())
|
||||
.Take(randomLimit)
|
||||
.ToListAsync();
|
||||
}
|
||||
var dict = randomTracks.Select((x, i) => new { key = i, value = x.Id }).Take(randomLimit).ToDictionary(x => x.key, x => x.value);
|
||||
return new SortedDictionary<int, int>(dict);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -7,7 +6,7 @@ using System.Threading.Tasks;
|
|||
namespace Roadie.Library.Data.Context.Implementation
|
||||
{
|
||||
/// <summary>
|
||||
/// MySQL/MariaDB implementation of DbContext
|
||||
/// MySQL/MariaDB implementation of DbContext using SQL statements for better performance.
|
||||
/// </summary>
|
||||
public sealed class MySQLRoadieDbContext : RoadieDbContext
|
||||
{
|
||||
|
@ -37,7 +36,7 @@ namespace Roadie.Library.Data.Context.Implementation
|
|||
join `track` t on (ut.trackId = t.id)
|
||||
join `releasemedia` rm on (t.releaseMediaId = rm.id)
|
||||
join `release` r on (rm.releaseId = r.id)
|
||||
WHERE ut.userId = {0}
|
||||
WHERE ut.userId = {0}
|
||||
ORDER by ut.lastPlayed desc
|
||||
LIMIT 1";
|
||||
return await Releases.FromSqlRaw(sql, userId)
|
||||
|
|
|
@ -3,7 +3,6 @@ using Microsoft.EntityFrameworkCore.ChangeTracking;
|
|||
using Roadie.Library.Enums;
|
||||
using Roadie.Library.Identity;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -35,8 +34,6 @@ namespace Roadie.Library.Data.Context
|
|||
|
||||
public DbSet<Genre> Genres { get; set; }
|
||||
|
||||
public DbSet<Image> Images { get; set; }
|
||||
|
||||
public DbSet<Label> Labels { get; set; }
|
||||
|
||||
public DbSet<Playlist> Playlists { get; set; }
|
||||
|
@ -72,7 +69,7 @@ namespace Roadie.Library.Data.Context
|
|||
public DbSet<UserTrack> UserTracks { get; set; }
|
||||
public DbSet<InviteToken> InviteTokens { get; set; }
|
||||
|
||||
public RoadieDbContext(DbContextOptions options)
|
||||
public RoadieDbContext(DbContextOptions options)
|
||||
: base(options)
|
||||
{
|
||||
}
|
||||
|
@ -218,10 +215,15 @@ namespace Roadie.Library.Data.Context
|
|||
}
|
||||
|
||||
Task<EntityEntry> IRoadieDbContext.AddAsync(object entity, CancellationToken cancellationToken) => throw new NotImplementedException();
|
||||
|
||||
Task<EntityEntry<TEntity>> IRoadieDbContext.AddAsync<TEntity>(TEntity entity, CancellationToken cancellationToken) => throw new NotImplementedException();
|
||||
|
||||
Task<TEntity> IRoadieDbContext.FindAsync<TEntity>(params object[] keyValues) => throw new NotImplementedException();
|
||||
|
||||
Task<object> IRoadieDbContext.FindAsync(Type entityType, object[] keyValues, CancellationToken cancellationToken) => throw new NotImplementedException();
|
||||
|
||||
Task<TEntity> IRoadieDbContext.FindAsync<TEntity>(object[] keyValues, CancellationToken cancellationToken) => throw new NotImplementedException();
|
||||
|
||||
Task<object> IRoadieDbContext.FindAsync(Type entityType, params object[] keyValues) => throw new NotImplementedException();
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Roadie.Library.Data
|
||||
{
|
||||
[Obsolete("Only here for transition. Will be removed in future release. Use Library.Imaging.Image")]
|
||||
[Table("image")]
|
||||
public partial class Image : EntityBase
|
||||
{
|
||||
public Artist Artist { get; set; }
|
||||
[Column("artistId")] public int? ArtistId { get; set; }
|
||||
|
||||
[Column("image", TypeName = "mediumblob")]
|
||||
public byte[] Bytes { get; set; }
|
||||
|
||||
[Column("caption")] [MaxLength(100)] public string Caption { get; set; }
|
||||
|
||||
public Release Release { get; set; }
|
||||
[Column("releaseId")] public int? ReleaseId { get; set; }
|
||||
|
||||
[Column("signature")] [MaxLength(50)] public string Signature { get; set; }
|
||||
|
||||
[Column("url")] [MaxLength(500)] public string Url { get; set; }
|
||||
}
|
||||
}
|
|
@ -20,11 +20,12 @@
|
|||
<PackageReference Include="LiteDB" Version="4.1.4" />
|
||||
<PackageReference Include="Mapster" Version="4.1.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Redis" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.1" />
|
||||
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="1.3.0" />
|
||||
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.8" />
|
||||
<PackageReference Include="Microsoft.PowerShell.SDK" Version="6.2.3" />
|
||||
<PackageReference Include="MimeMapping" Version="1.0.1.17" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
|
@ -35,7 +36,7 @@
|
|||
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.0-beta0007" />
|
||||
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta0007" />
|
||||
<PackageReference Include="SixLabors.Shapes" Version="1.0.0-beta0009" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="4.6.0" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="4.6.1" />
|
||||
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="4.6.0" />
|
||||
<PackageReference Include="System.Runtime.Caching" Version="4.6.0" />
|
||||
<PackageReference Include="z440.atl.core" Version="2.13.0" />
|
||||
|
@ -43,6 +44,9 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="FileContextCore">
|
||||
<HintPath>..\libraries\FileContextCore.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="IdSharp.AudioInfo-core">
|
||||
<HintPath>..\libraries\IdSharp.AudioInfo-core.dll</HintPath>
|
||||
</Reference>
|
||||
|
|
|
@ -1011,449 +1011,6 @@ namespace Roadie.Api.Services
|
|||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Migrate Storage from old folder structure to new folder structure.
|
||||
/// </summary>
|
||||
public async Task<OperationResult<bool>> MigrateStorage(ApplicationUser user, bool deleteEmptyFolders = true)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
var errors = new List<Exception>();
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
var artistsMigrated = 0;
|
||||
foreach (var artist in DbContext.Artists.Where(x => x.Status == Statuses.ReadyToMigrate).ToArray())
|
||||
{
|
||||
var oldArtistPath = FolderPathHelper.ArtistPathOld(Configuration, artist.SortNameValue);
|
||||
var artistpath = FolderPathHelper.ArtistPath(Configuration, artist.Id, artist.SortNameValue);
|
||||
|
||||
if (Directory.Exists(oldArtistPath))
|
||||
{
|
||||
var artistInfoFile = new FileInfo(Path.Combine(oldArtistPath, "roadie.artist.json"));
|
||||
if (artistInfoFile.Exists)
|
||||
{
|
||||
artistInfoFile.MoveTo(Path.Combine(artistpath, "roadie.artist.json"));
|
||||
}
|
||||
}
|
||||
|
||||
var createdDirectory = false;
|
||||
var filesMoved = 0;
|
||||
var artistImages = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(oldArtistPath), ImageType.Artist);
|
||||
var artistSecondaryImages = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(oldArtistPath), ImageType.ArtistSecondary).ToList();
|
||||
if (artistImages.Any())
|
||||
{
|
||||
if (!Directory.Exists(artistpath))
|
||||
{
|
||||
Directory.CreateDirectory(artistpath);
|
||||
createdDirectory = true;
|
||||
}
|
||||
var artistToMergeIntoPrimaryImage = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(artistpath), ImageType.Artist).FirstOrDefault();
|
||||
if (artistToMergeIntoPrimaryImage != null)
|
||||
{
|
||||
artistSecondaryImages.Add(artistImages.First());
|
||||
}
|
||||
else
|
||||
{
|
||||
var artistImageFilename = Path.Combine(artistpath, ImageHelper.ArtistImageFilename);
|
||||
artistImages.First().MoveTo(artistImageFilename, true);
|
||||
filesMoved++;
|
||||
}
|
||||
}
|
||||
if (artistSecondaryImages.Any())
|
||||
{
|
||||
if (!Directory.Exists(artistpath))
|
||||
{
|
||||
Directory.CreateDirectory(artistpath);
|
||||
createdDirectory = true;
|
||||
}
|
||||
var looper = 0;
|
||||
foreach (var artistSecondaryImage in artistSecondaryImages)
|
||||
{
|
||||
var artistImageFilename = Path.Combine(artistpath, string.Format(ImageHelper.ArtistSecondaryImageFilename, looper.ToString("00")));
|
||||
while (File.Exists(artistImageFilename))
|
||||
{
|
||||
looper++;
|
||||
artistImageFilename = Path.Combine(artistpath, string.Format(ImageHelper.ArtistSecondaryImageFilename, looper.ToString("00")));
|
||||
}
|
||||
artistSecondaryImage.MoveTo(artistImageFilename, true);
|
||||
filesMoved++;
|
||||
}
|
||||
}
|
||||
artist.Status = Statuses.Migrated;
|
||||
artist.LastUpdated = now;
|
||||
await DbContext.SaveChangesAsync();
|
||||
Logger.LogInformation($"Migrated Artist Storage `{ artist}` From [{ oldArtistPath }] => [{ artistpath }]");
|
||||
artistsMigrated++;
|
||||
}
|
||||
Logger.LogInformation($"Artist Migration Complete. Migrated [{ artistsMigrated }] Artists.");
|
||||
|
||||
var labelsMigrated = 0;
|
||||
foreach (var label in DbContext.Labels.Where(x => x.Status == Statuses.ReadyToMigrate).ToArray())
|
||||
{
|
||||
var oldLabelImageFileName = label.OldPathToImage(Configuration);
|
||||
var labelImageFileName = label.PathToImage(Configuration);
|
||||
if(File.Exists(oldLabelImageFileName))
|
||||
{
|
||||
var labelFileInfo = new FileInfo(labelImageFileName);
|
||||
if(!labelFileInfo.Directory.Exists)
|
||||
{
|
||||
Directory.CreateDirectory(labelFileInfo.Directory.FullName);
|
||||
}
|
||||
File.Move(oldLabelImageFileName, labelImageFileName, true);
|
||||
label.Status = Statuses.Migrated;
|
||||
label.LastUpdated = now;
|
||||
await DbContext.SaveChangesAsync();
|
||||
Logger.LogInformation($"Migrated Label Storage `{ label}` From [{ oldLabelImageFileName }] => [{ labelImageFileName }]");
|
||||
labelsMigrated++;
|
||||
}
|
||||
}
|
||||
Logger.LogInformation($"Label Migration Complete. Migrated [{ labelsMigrated }] Labels.");
|
||||
|
||||
var genresMigrated = 0;
|
||||
foreach (var genre in DbContext.Genres.Where(x => x.Status == Statuses.ReadyToMigrate).ToArray())
|
||||
{
|
||||
var oldGenreImageFileName = genre.OldPathToImage(Configuration);
|
||||
var genreImageFileName = genre.PathToImage(Configuration);
|
||||
if (File.Exists(oldGenreImageFileName))
|
||||
{
|
||||
var genreFileInfo = new FileInfo(genreImageFileName);
|
||||
if (!genreFileInfo.Directory.Exists)
|
||||
{
|
||||
Directory.CreateDirectory(genreFileInfo.Directory.FullName);
|
||||
}
|
||||
File.Move(oldGenreImageFileName, genreImageFileName, true);
|
||||
genre.Status = Statuses.Migrated;
|
||||
genre.LastUpdated = now;
|
||||
await DbContext.SaveChangesAsync();
|
||||
Logger.LogInformation($"Migrated Genre Storage `{ genre}` From [{ oldGenreImageFileName }] => [{ genreImageFileName }]");
|
||||
genresMigrated++;
|
||||
}
|
||||
}
|
||||
Logger.LogInformation($"Genre Migration Complete. Migrated [{ genresMigrated }] Genres.");
|
||||
|
||||
var releases = DbContext.Releases
|
||||
.Include(x => x.Artist)
|
||||
.Include(x => x.Medias)
|
||||
.Where(x => x.Status == Statuses.ReadyToMigrate)
|
||||
.ToArray();
|
||||
var releasesMigrated = 0;
|
||||
foreach (var release in releases)
|
||||
{
|
||||
var oldArtistPath = FolderPathHelper.ArtistPathOld(Configuration, release.Artist.SortNameValue);
|
||||
var oldReleasePath = FolderPathHelper.ReleasePathOld(oldArtistPath, release.SortTitleValue, release.ReleaseDate.Value);
|
||||
|
||||
var artistpath = FolderPathHelper.ArtistPath(Configuration, release.Artist.Id, release.Artist.SortNameValue);
|
||||
var releasePath = FolderPathHelper.ReleasePath(artistpath, release.SortTitleValue, release.ReleaseDate.Value);
|
||||
|
||||
if (!Directory.Exists(artistpath))
|
||||
{
|
||||
Directory.CreateDirectory(artistpath);
|
||||
}
|
||||
if (!Directory.Exists(releasePath))
|
||||
{
|
||||
Directory.CreateDirectory(releasePath);
|
||||
}
|
||||
var releaseTracks = (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
|
||||
where r.Id == release.Id
|
||||
where t.FileName != null
|
||||
select t).ToArray();
|
||||
|
||||
foreach(var releaseTrack in releaseTracks)
|
||||
{
|
||||
var oldTrackFileName = Path.Combine(oldReleasePath, releaseTrack.FileName);
|
||||
var newTrackFileName = Path.Combine(releasePath, releaseTrack.FileName.ToFileNameFriendly());
|
||||
if(File.Exists(oldTrackFileName))
|
||||
{
|
||||
File.Move(oldTrackFileName, newTrackFileName, true);
|
||||
releaseTrack.FilePath = FolderPathHelper.TrackPath(Configuration, release.Artist, release, releaseTrack);
|
||||
releaseTrack.FileName = releaseTrack.FileName.ToFileNameFriendly();
|
||||
releaseTrack.LastUpdated = now;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogWarning($"Migration: Track `{ releaseTrack }` Track File [{ oldTrackFileName }] Not Found");
|
||||
}
|
||||
}
|
||||
var releaseInfoFile = new FileInfo(Path.Combine(oldReleasePath, "roadie.albuminfo.json"));
|
||||
if(releaseInfoFile.Exists)
|
||||
{
|
||||
releaseInfoFile.MoveTo(Path.Combine(releasePath, "roadie.releaseinfo.json"));
|
||||
}
|
||||
var releaseToMergeImages = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(oldReleasePath), ImageType.Release);
|
||||
var releaseToMergeSecondaryImages = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(oldReleasePath), ImageType.ReleaseSecondary).ToList();
|
||||
if (releaseToMergeImages.Any())
|
||||
{
|
||||
var releaseToMergeIntoPrimaryImage = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(releasePath), ImageType.Release).FirstOrDefault();
|
||||
if (releaseToMergeIntoPrimaryImage != null)
|
||||
{
|
||||
releaseToMergeSecondaryImages.Add(releaseToMergeImages.First());
|
||||
}
|
||||
else
|
||||
{
|
||||
var releaseImageFilename = Path.Combine(releasePath, ImageHelper.ReleaseCoverFilename);
|
||||
releaseToMergeImages.First().MoveTo(releaseImageFilename, true);
|
||||
}
|
||||
}
|
||||
if (releaseToMergeSecondaryImages.Any())
|
||||
{
|
||||
var looper = 0;
|
||||
foreach (var releaseSecondaryImage in releaseToMergeSecondaryImages)
|
||||
{
|
||||
var releaseImageFilename = Path.Combine(releasePath, string.Format(ImageHelper.ReleaseSecondaryImageFilename, looper.ToString("00")));
|
||||
while (File.Exists(releaseImageFilename))
|
||||
{
|
||||
looper++;
|
||||
releaseImageFilename = Path.Combine(releasePath, string.Format(ImageHelper.ReleaseSecondaryImageFilename, looper.ToString("00")));
|
||||
}
|
||||
releaseSecondaryImage.MoveTo(releaseImageFilename, true);
|
||||
}
|
||||
}
|
||||
|
||||
release.Status = Statuses.Migrated;
|
||||
release.LastUpdated = now;
|
||||
await DbContext.SaveChangesAsync();
|
||||
Logger.LogInformation($"Migrated Release `{ release}` From [{ oldReleasePath }] => [{ releasePath }]");
|
||||
releasesMigrated++;
|
||||
}
|
||||
Logger.LogInformation($"Release Migration Complete. Migrated [{ releasesMigrated }] Releases.");
|
||||
|
||||
if (deleteEmptyFolders)
|
||||
{
|
||||
Logger.LogInformation($"Deleting Empty Folders in Library [{ Configuration.LibraryFolder }] Folder.");
|
||||
Services.FileDirectoryProcessorService.DeleteEmptyFolders(new DirectoryInfo(Configuration.LibraryFolder), Logger);
|
||||
}
|
||||
CacheManager.Clear();
|
||||
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
IsSuccess = !errors.Any(),
|
||||
Data = true,
|
||||
OperationTime = sw.ElapsedMilliseconds,
|
||||
Errors = errors
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Migrate images from Images table and Thumbnails to file storage.
|
||||
/// </summary>
|
||||
public async Task<OperationResult<bool>> MigrateImages(ApplicationUser user)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
var errors = new List<Exception>();
|
||||
var now = DateTime.UtcNow;
|
||||
foreach (var artist in DbContext.Artists.Where(x => x.Thumbnail != null).OrderBy(x => x.SortName ?? x.Name))
|
||||
{
|
||||
var artistFolder = artist.ArtistFileFolder(Configuration);
|
||||
if (!Directory.Exists(artistFolder))
|
||||
{
|
||||
Directory.CreateDirectory(artistFolder);
|
||||
}
|
||||
var artistImage = Path.Combine(artistFolder, ImageHelper.ArtistImageFilename);
|
||||
if (!File.Exists(artistImage))
|
||||
{
|
||||
File.WriteAllBytes(artistImage, ImageHelper.ConvertToJpegFormat(artist.Thumbnail));
|
||||
}
|
||||
artist.Thumbnail = null;
|
||||
artist.LastUpdated = now;
|
||||
|
||||
Logger.LogInformation($"Saved Artist Image `{artist}` path [{ artistImage }]");
|
||||
}
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
var artistImages = (from i in DbContext.Images
|
||||
join a in DbContext.Artists on i.ArtistId equals a.Id
|
||||
select new { i, a });
|
||||
foreach (var artistImage in artistImages)
|
||||
{
|
||||
var looper = 0;
|
||||
var artistFolder = artistImage.a.ArtistFileFolder(Configuration);
|
||||
var artistImageFilename = Path.Combine(artistFolder, string.Format(ImageHelper.ArtistSecondaryImageFilename, looper.ToString("00")));
|
||||
while (File.Exists(artistImageFilename))
|
||||
{
|
||||
looper++;
|
||||
artistImageFilename = Path.Combine(artistFolder, string.Format(ImageHelper.ArtistSecondaryImageFilename, looper.ToString("00")));
|
||||
}
|
||||
File.WriteAllBytes(artistImageFilename, ImageHelper.ConvertToJpegFormat(artistImage.i.Bytes));
|
||||
DbContext.Images.Remove(artistImage.i);
|
||||
Logger.LogInformation($"Saved Artist Secondary Image `{artistImage.a}` path [{ artistImageFilename }]");
|
||||
}
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
foreach (var collection in DbContext.Collections.Where(x => x.Thumbnail != null).OrderBy(x => x.SortName ?? x.Name))
|
||||
{
|
||||
var image = collection.PathToImage(Configuration);
|
||||
if (!File.Exists(image))
|
||||
{
|
||||
File.WriteAllBytes(image, ImageHelper.ConvertToJpegFormat(collection.Thumbnail));
|
||||
}
|
||||
collection.Thumbnail = null;
|
||||
collection.LastUpdated = now;
|
||||
Logger.LogInformation($"Saved Collection Image `{collection}` path [{ image }]");
|
||||
}
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
foreach (var genre in DbContext.Genres.Where(x => x.Thumbnail != null).OrderBy(x => x.Name))
|
||||
{
|
||||
var image = genre.PathToImage(Configuration);
|
||||
if (!File.Exists(image))
|
||||
{
|
||||
File.WriteAllBytes(image, ImageHelper.ConvertToJpegFormat(genre.Thumbnail));
|
||||
}
|
||||
genre.Thumbnail = null;
|
||||
genre.LastUpdated = now;
|
||||
Logger.LogInformation($"Saved Genre Image `{genre}` path [{ image }]");
|
||||
}
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
foreach (var label in DbContext.Labels.Where(x => x.Thumbnail != null).OrderBy(x => x.SortName ?? x.Name))
|
||||
{
|
||||
var image = label.PathToImage(Configuration);
|
||||
if (!File.Exists(image))
|
||||
{
|
||||
File.WriteAllBytes(image, ImageHelper.ConvertToJpegFormat(label.Thumbnail));
|
||||
}
|
||||
label.Thumbnail = null;
|
||||
label.LastUpdated = now;
|
||||
Logger.LogInformation($"Saved Label Image `{label}` path [{ image }]");
|
||||
}
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
foreach (var playlist in DbContext.Playlists.Where(x => x.Thumbnail != null).OrderBy(x => x.Name))
|
||||
{
|
||||
var image = playlist.PathToImage(Configuration);
|
||||
if (!File.Exists(image))
|
||||
{
|
||||
File.WriteAllBytes(image, ImageHelper.ConvertToJpegFormat(playlist.Thumbnail));
|
||||
}
|
||||
playlist.Thumbnail = null;
|
||||
playlist.LastUpdated = now;
|
||||
Logger.LogInformation($"Saved Playlist Image `{playlist}` path [{ image }]");
|
||||
}
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
foreach (var release in DbContext.Releases.Include(x => x.Artist).Where(x => x.Thumbnail != null).OrderBy(x => x.SortTitle ?? x.Title))
|
||||
{
|
||||
var artistFolder = release.Artist.ArtistFileFolder(Configuration);
|
||||
if (!Directory.Exists(artistFolder))
|
||||
{
|
||||
Directory.CreateDirectory(artistFolder);
|
||||
}
|
||||
var releaseFolder = release.ReleaseFileFolder(artistFolder);
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(releaseFolder))
|
||||
{
|
||||
Directory.CreateDirectory(releaseFolder);
|
||||
}
|
||||
var releaseImage = Path.Combine(releaseFolder, "cover.jpg");
|
||||
if (!File.Exists(releaseImage))
|
||||
{
|
||||
File.WriteAllBytes(releaseImage, ImageHelper.ConvertToJpegFormat(release.Thumbnail));
|
||||
}
|
||||
release.Thumbnail = null;
|
||||
release.LastUpdated = now;
|
||||
Logger.LogInformation($"Saved Release Image `{release}` path [{ releaseImage }]");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"Error saving Release Image `{release}` folder [{ releaseFolder }]");
|
||||
}
|
||||
}
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
var releaseImages = (from i in DbContext.Images
|
||||
join r in DbContext.Releases.Include(x => x.Artist) on i.ReleaseId equals r.Id
|
||||
select new { i, r });
|
||||
foreach (var releaseImage in releaseImages)
|
||||
{
|
||||
var looper = 0;
|
||||
var artistFolder = releaseImage.r.Artist.ArtistFileFolder(Configuration);
|
||||
if (!Directory.Exists(artistFolder))
|
||||
{
|
||||
Directory.CreateDirectory(artistFolder);
|
||||
}
|
||||
var releaseFolder = releaseImage.r.ReleaseFileFolder(artistFolder);
|
||||
if (!Directory.Exists(releaseFolder))
|
||||
{
|
||||
Directory.CreateDirectory(releaseFolder);
|
||||
}
|
||||
var releaseImageFilename = Path.Combine(releaseFolder, string.Format(ImageHelper.ReleaseSecondaryImageFilename, looper.ToString("00")));
|
||||
try
|
||||
{
|
||||
while (File.Exists(releaseImageFilename))
|
||||
{
|
||||
looper++;
|
||||
releaseImageFilename = Path.Combine(releaseFolder, string.Format(ImageHelper.ReleaseSecondaryImageFilename, looper.ToString("00")));
|
||||
}
|
||||
File.WriteAllBytes(releaseImageFilename, ImageHelper.ConvertToJpegFormat(releaseImage.i.Bytes));
|
||||
DbContext.Images.Remove(releaseImage.i);
|
||||
Logger.LogInformation($"Saved Release Secondary Image `{releaseImage.r}` path [{ releaseImageFilename }]");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"Error saving Release Secondary Image [{releaseImageFilename}] folder [{ releaseFolder }]");
|
||||
}
|
||||
}
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
foreach (var track in DbContext.Tracks.Include(x => x.ReleaseMedia)
|
||||
.Include(x => x.ReleaseMedia.Release)
|
||||
.Include(x => x.ReleaseMedia.Release.Artist)
|
||||
.Where(x => x.Thumbnail != null).OrderBy(x => x.Title))
|
||||
{
|
||||
var artistFolder = track.ReleaseMedia.Release.Artist.ArtistFileFolder(Configuration);
|
||||
if (!Directory.Exists(artistFolder))
|
||||
{
|
||||
Directory.CreateDirectory(artistFolder);
|
||||
}
|
||||
var releaseFolder = track.ReleaseMedia.Release.ReleaseFileFolder(artistFolder);
|
||||
if (!Directory.Exists(releaseFolder))
|
||||
{
|
||||
Directory.CreateDirectory(releaseFolder);
|
||||
}
|
||||
var trackImage = track.PathToTrackThumbnail(Configuration);
|
||||
try
|
||||
{
|
||||
if (!File.Exists(trackImage))
|
||||
{
|
||||
File.WriteAllBytes(trackImage, ImageHelper.ConvertToJpegFormat(track.Thumbnail));
|
||||
}
|
||||
track.Thumbnail = null;
|
||||
track.LastUpdated = now;
|
||||
Logger.LogInformation($"Saved Track Image `{track}` path [{ trackImage }]");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"Error saving Track Image [{trackImage}] folder [{ releaseFolder }]");
|
||||
}
|
||||
}
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
foreach (var usr in DbContext.Users.Where(x => x.Avatar != null).OrderBy(x => x.UserName))
|
||||
{
|
||||
var image = usr.PathToImage(Configuration);
|
||||
if (!File.Exists(image))
|
||||
{
|
||||
File.WriteAllBytes(image, ImageHelper.ConvertToJpegFormat(usr.Avatar));
|
||||
}
|
||||
usr.Avatar = null;
|
||||
usr.LastUpdated = now;
|
||||
Logger.LogInformation($"Saved User Image `{user}` path [{ image }]");
|
||||
}
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
IsSuccess = !errors.Any(),
|
||||
Data = true,
|
||||
OperationTime = sw.ElapsedMilliseconds,
|
||||
Errors = errors
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<OperationResult<bool>> ValidateInviteToken(Guid? tokenId)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
|
|
|
@ -52,9 +52,5 @@ namespace Roadie.Api.Services
|
|||
Task<OperationResult<bool>> UpdateInviteTokenUsed(Guid? tokenId);
|
||||
|
||||
Task<OperationResult<bool>> ValidateInviteToken(Guid? tokenId);
|
||||
|
||||
Task<OperationResult<bool>> MigrateImages(ApplicationUser user);
|
||||
|
||||
Task<OperationResult<bool>> MigrateStorage(ApplicationUser user, bool deleteEmptyFolders);
|
||||
}
|
||||
}
|
|
@ -319,7 +319,7 @@ namespace Roadie.Api.Services
|
|||
if (labelImage != null)
|
||||
{
|
||||
// Save unaltered label image
|
||||
File.WriteAllBytes(label.PathToImage(Configuration), ImageHelper.ConvertToJpegFormat(labelImage));
|
||||
File.WriteAllBytes(label.PathToImage(Configuration, true), ImageHelper.ConvertToJpegFormat(labelImage));
|
||||
}
|
||||
label.LastUpdated = now;
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
|
|
@ -209,21 +209,23 @@ namespace Roadie.Api.Services
|
|||
year = SafeParser.ToNumber<int>(x.Key),
|
||||
count = x.Count()
|
||||
});
|
||||
|
||||
var decadeInterval = 10;
|
||||
var startingDecade = (decadeInfos.Min(x => x.year) / 10) * 10;
|
||||
var endingDecade = (decadeInfos.Max(x => x.year) / 10) * 10;
|
||||
for (int decade = startingDecade; decade <= endingDecade; decade += decadeInterval)
|
||||
if (decadeInfos != null && decadeInfos.Any())
|
||||
{
|
||||
var endOfDecade = decade + 9;
|
||||
var count = decadeInfos.Where(x => x.year >= decade && x.year <= endOfDecade).Sum(x => x.count);
|
||||
if (count > 0)
|
||||
var decadeInterval = 10;
|
||||
var startingDecade = (decadeInfos.Min(x => x.year) / 10) * 10;
|
||||
var endingDecade = (decadeInfos.Max(x => x.year) / 10) * 10;
|
||||
for (int decade = startingDecade; decade <= endingDecade; decade += decadeInterval)
|
||||
{
|
||||
result.Add(new DateAndCount
|
||||
var endOfDecade = decade + 9;
|
||||
var count = decadeInfos.Where(x => x.year >= decade && x.year <= endOfDecade).Sum(x => x.count);
|
||||
if (count > 0)
|
||||
{
|
||||
Date = decade.ToString(),
|
||||
Count = count
|
||||
});
|
||||
result.Add(new DateAndCount
|
||||
{
|
||||
Date = decade.ToString(),
|
||||
Count = count
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
sw.Stop();
|
||||
|
|
|
@ -338,37 +338,5 @@ namespace Roadie.Api.Controllers
|
|||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpPost("migrateimages")]
|
||||
[ProducesResponseType(200)]
|
||||
public async Task<IActionResult> MigrateImages()
|
||||
{
|
||||
var result = await AdminService.MigrateImages(await UserManager.GetUserAsync(User));
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
if (result.Messages?.Any() ?? false)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.BadRequest, result.Messages);
|
||||
}
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
|
||||
[HttpPost("migratestorage")]
|
||||
[ProducesResponseType(200)]
|
||||
public async Task<IActionResult> MigrateStorage(bool? deleteEmptyFolders)
|
||||
{
|
||||
var result = await AdminService.MigrateStorage(await UserManager.GetUserAsync(User), deleteEmptyFolders ?? true);
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
if (result.Messages?.Any() ?? false)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.BadRequest, result.Messages);
|
||||
}
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,7 +30,8 @@
|
|||
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.3.1" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.3.1" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.3.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="3.2.0" />
|
||||
|
@ -56,4 +57,10 @@
|
|||
<ProjectReference Include="..\Roadie.Dlna.Services\Roadie.Dlna.Services.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="FileContextCore">
|
||||
<HintPath>..\libraries\FileContextCore.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#region Usings
|
||||
|
||||
using FileContextCore;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
|
@ -57,14 +58,6 @@ namespace Roadie.Api
|
|||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
TypeAdapterConfig<Library.Data.Image, Library.Models.Image>
|
||||
.NewConfig()
|
||||
.Map(i => i.ArtistId,
|
||||
src => src.Artist == null ? null : (Guid?)src.Artist.RoadieId)
|
||||
.Map(i => i.ReleaseId,
|
||||
src => src.Release == null ? null : (Guid?)src.Release.RoadieId)
|
||||
.Compile();
|
||||
|
||||
TypeAdapterConfig.GlobalSettings.Default.PreserveReference(true);
|
||||
}
|
||||
|
||||
|
@ -105,6 +98,10 @@ namespace Roadie.Api
|
|||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
|
||||
var settings = new RoadieSettings();
|
||||
_configuration.GetSection("RoadieSettings").Bind(settings);
|
||||
|
||||
services.AddSingleton<ITokenService, TokenService>();
|
||||
services.AddSingleton<IHttpEncoder, HttpEncoder>();
|
||||
services.AddSingleton<IEmailSender, EmailSenderService>();
|
||||
|
@ -115,29 +112,47 @@ namespace Roadie.Api
|
|||
return new MemoryCacheManager(logger, new CachePolicy(TimeSpan.FromHours(4)));
|
||||
});
|
||||
|
||||
services.AddDbContextPool<ApplicationUserDbContext>(
|
||||
options => options.UseMySql(_configuration.GetConnectionString("RoadieDatabaseConnection"),
|
||||
mySqlOptions =>
|
||||
{
|
||||
mySqlOptions.ServerVersion(new Version(5, 5), ServerType.MariaDb);
|
||||
mySqlOptions.EnableRetryOnFailure(
|
||||
10,
|
||||
TimeSpan.FromSeconds(30),
|
||||
null);
|
||||
}
|
||||
));
|
||||
|
||||
services.AddDbContextPool<IRoadieDbContext, MySQLRoadieDbContext>(
|
||||
options => options.UseMySql(_configuration.GetConnectionString("RoadieDatabaseConnection"),
|
||||
mySqlOptions =>
|
||||
{
|
||||
mySqlOptions.ServerVersion(new Version(5, 5), ServerType.MariaDb);
|
||||
mySqlOptions.EnableRetryOnFailure(
|
||||
10,
|
||||
TimeSpan.FromSeconds(30),
|
||||
null);
|
||||
}
|
||||
));
|
||||
switch (settings.DbContextToUse)
|
||||
{
|
||||
case DbContexts.MySQL:
|
||||
services.AddDbContextPool<ApplicationUserDbContext>(
|
||||
options => options.UseMySql(_configuration.GetConnectionString("RoadieDatabaseConnection"),
|
||||
mySqlOptions =>
|
||||
{
|
||||
mySqlOptions.ServerVersion(new Version(5, 5), ServerType.MariaDb);
|
||||
mySqlOptions.EnableRetryOnFailure(
|
||||
10,
|
||||
TimeSpan.FromSeconds(30),
|
||||
null);
|
||||
}
|
||||
));
|
||||
services.AddDbContextPool<IRoadieDbContext, MySQLRoadieDbContext>(
|
||||
options => options.UseMySql(_configuration.GetConnectionString("RoadieDatabaseConnection"),
|
||||
mySqlOptions =>
|
||||
{
|
||||
mySqlOptions.ServerVersion(new Version(5, 5), ServerType.MariaDb);
|
||||
mySqlOptions.EnableRetryOnFailure(
|
||||
10,
|
||||
TimeSpan.FromSeconds(30),
|
||||
null);
|
||||
}
|
||||
));
|
||||
break;
|
||||
case DbContexts.File:
|
||||
services.AddDbContext<ApplicationUserDbContext>(
|
||||
options => options.UseFileContextDatabase(settings.FileDatabaseOptions.DatabaseFormat.ToString().ToLower(),
|
||||
databaseName: settings.FileDatabaseOptions.DatabaseName,
|
||||
location: settings.FileDatabaseOptions.DatabaseFolder)
|
||||
);
|
||||
services.AddDbContext<IRoadieDbContext, FileRoadieDbContext>(
|
||||
options => options.UseFileContextDatabase(settings.FileDatabaseOptions.DatabaseFormat.ToString().ToLower(),
|
||||
databaseName: settings.FileDatabaseOptions.DatabaseName,
|
||||
location: settings.FileDatabaseOptions.DatabaseFolder)
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException("Unknown DbContext Type");
|
||||
}
|
||||
|
||||
services.AddIdentity<ApplicationUser, ApplicationRole>()
|
||||
.AddRoles<ApplicationRole>()
|
||||
|
|
|
@ -59,8 +59,12 @@
|
|||
},
|
||||
"CORSOrigins": "http://localhost:4200|http://localhost:8080|https://localhost:8080|http://localhost:80|https://localhost:80|http://192.168.1.177:8080",
|
||||
"RoadieSettings": {
|
||||
"DbContextToUse": "File",
|
||||
"FileDatabaseOptions": {
|
||||
"DatabaseFolder": "C:\\\\roadie_dev_root\\\\db"
|
||||
},
|
||||
"InboundFolder": "C:\\roadie_dev_root\\inbound",
|
||||
"LibraryFolder": "C:\\\\roadie_dev_root\\\\library",
|
||||
"LibraryFolder": "C:\\\\roadie_dev_root\\\\library",
|
||||
"Dlna": {
|
||||
"IsEnabled": false
|
||||
},
|
||||
|
|
BIN
libraries/FileContextCore.dll
Normal file
BIN
libraries/FileContextCore.dll
Normal file
Binary file not shown.
Loading…
Reference in a new issue