mirror of
https://github.com/sphildreth/roadie
synced 2024-11-10 06:44:12 +00:00
Reworked play activity to handle scrobble engine better.
This commit is contained in:
parent
740683e93b
commit
17b542af91
14 changed files with 234 additions and 61 deletions
|
@ -33,6 +33,8 @@ namespace Roadie.Library.Models
|
|||
public Image UserThumbnail { get; set; }
|
||||
public UserTrack UserTrack { get; set; }
|
||||
|
||||
public bool IsNowPlaying { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"User [{ this.User }], Artist [{ this.Artist }], Release [{ this.Release }], Track [{ this.Track}]";
|
||||
|
|
|
@ -36,6 +36,16 @@ namespace Roadie.Library.Models.ThirdPartyApi.Subsonic
|
|||
/// </summary>
|
||||
public string c { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The time (in milliseconds since 1 Jan 1970) at which the song was listened to.
|
||||
/// </summary>
|
||||
public string time { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether this is a "submission" or a "now playing" notification.
|
||||
/// </summary>
|
||||
public string submission { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <seealso cref="f"/>
|
||||
/// </summary>
|
||||
|
|
|
@ -3,6 +3,7 @@ using Roadie.Library.Caching;
|
|||
using Roadie.Library.Configuration;
|
||||
using Roadie.Library.MetaData.LastFm;
|
||||
using Roadie.Library.Models.Users;
|
||||
using Roadie.Library.Utility;
|
||||
using System.Threading.Tasks;
|
||||
using data = Roadie.Library.Data;
|
||||
|
||||
|
@ -16,8 +17,9 @@ namespace Roadie.Library.Scrobble
|
|||
{
|
||||
private ILastFmHelper LastFmHelper { get; }
|
||||
|
||||
public LastFMScrobbler(IRoadieSettings configuration, ILogger logger, data.IRoadieDbContext dbContext, ICacheManager cacheManager, ILastFmHelper lastFmHelper)
|
||||
: base(configuration, logger, dbContext, cacheManager)
|
||||
public LastFMScrobbler(IRoadieSettings configuration, ILogger logger, data.IRoadieDbContext dbContext,
|
||||
ICacheManager cacheManager, ILastFmHelper lastFmHelper, IHttpContext httpContext)
|
||||
: base(configuration, logger, dbContext, cacheManager, httpContext)
|
||||
{
|
||||
LastFmHelper = lastFmHelper;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
using Microsoft.Extensions.Logging;
|
||||
using Roadie.Library.Caching;
|
||||
using Roadie.Library.Configuration;
|
||||
using Roadie.Library.Models;
|
||||
using Roadie.Library.Models.Users;
|
||||
using Roadie.Library.Utility;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
@ -13,25 +15,41 @@ namespace Roadie.Library.Scrobble
|
|||
{
|
||||
public class RoadieScrobbler : ScrobblerIntegrationBase
|
||||
{
|
||||
public RoadieScrobbler(IRoadieSettings configuration, ILogger logger, data.IRoadieDbContext dbContext, ICacheManager cacheManager)
|
||||
: base(configuration, logger, dbContext, cacheManager)
|
||||
public RoadieScrobbler(IRoadieSettings configuration, ILogger logger, data.IRoadieDbContext dbContext,
|
||||
ICacheManager cacheManager, IHttpContext httpContext)
|
||||
: base(configuration, logger, dbContext, cacheManager, httpContext)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The user has started playing a track.
|
||||
/// For Roadie we only add a user play on the full scrobble event, otherwise we get double track play numbers.
|
||||
/// </summary>
|
||||
public override async Task<OperationResult<bool>> NowPlaying(User roadieUser, ScrobbleInfo scrobble) => await ScrobbleAction(roadieUser, scrobble, true);
|
||||
public override async Task<OperationResult<bool>> NowPlaying(User roadieUser, ScrobbleInfo scrobble)
|
||||
{
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
Data = true,
|
||||
IsSuccess = true
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The user has played a track.
|
||||
/// </summary>
|
||||
public override async Task<OperationResult<bool>> Scrobble(User roadieUser, ScrobbleInfo scrobble) => await ScrobbleAction(roadieUser, scrobble, false);
|
||||
|
||||
private async Task<OperationResult<bool>> ScrobbleAction(User roadieUser, ScrobbleInfo scrobble, bool isNowPlaying)
|
||||
{
|
||||
public override async Task<OperationResult<bool>> Scrobble(User roadieUser, ScrobbleInfo scrobble)
|
||||
{
|
||||
try
|
||||
{
|
||||
// If less than half of duration then do nothing
|
||||
if (scrobble.ElapsedTimeOfTrackPlayed.TotalSeconds < (scrobble.TrackDuration.TotalSeconds / 2))
|
||||
{
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
Data = true,
|
||||
IsSuccess = true
|
||||
};
|
||||
}
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
var track = this.DbContext.Tracks
|
||||
.Include(x => x.ReleaseMedia)
|
||||
|
@ -52,25 +70,47 @@ namespace Roadie.Library.Scrobble
|
|||
var success = false;
|
||||
try
|
||||
{
|
||||
// Only create (or update) a user track activity record when the user has played the entire track.
|
||||
if (!isNowPlaying)
|
||||
var user = this.DbContext.Users.FirstOrDefault(x => x.RoadieId == roadieUser.UserId);
|
||||
userTrack = this.DbContext.UserTracks.FirstOrDefault(x => x.UserId == roadieUser.Id && x.TrackId == track.Id);
|
||||
if (userTrack == null)
|
||||
{
|
||||
var user = this.DbContext.Users.FirstOrDefault(x => x.RoadieId == roadieUser.UserId);
|
||||
userTrack = this.DbContext.UserTracks.FirstOrDefault(x => x.UserId == roadieUser.Id && x.TrackId == track.Id);
|
||||
if (userTrack == null)
|
||||
userTrack = new data.UserTrack(now)
|
||||
{
|
||||
userTrack = new data.UserTrack(now)
|
||||
{
|
||||
UserId = user.Id,
|
||||
TrackId = track.Id
|
||||
};
|
||||
this.DbContext.UserTracks.Add(userTrack);
|
||||
}
|
||||
userTrack.LastPlayed = now;
|
||||
userTrack.PlayedCount = (userTrack.PlayedCount ?? 0) + 1;
|
||||
this.CacheManager.ClearRegion(user.CacheRegion);
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
UserId = user.Id,
|
||||
TrackId = track.Id
|
||||
};
|
||||
this.DbContext.UserTracks.Add(userTrack);
|
||||
}
|
||||
userTrack.LastPlayed = now;
|
||||
userTrack.PlayedCount = (userTrack.PlayedCount ?? 0) + 1;
|
||||
|
||||
track.PlayedCount = (track.PlayedCount ?? 0) + 1;
|
||||
track.LastPlayed = now;
|
||||
|
||||
var release = this.DbContext.Releases.Include(x => x.Artist).FirstOrDefault(x => x.RoadieId == track.ReleaseMedia.Release.RoadieId);
|
||||
release.LastPlayed = now;
|
||||
release.PlayedCount = (release.PlayedCount ?? 0) + 1;
|
||||
|
||||
var artist = this.DbContext.Artists.FirstOrDefault(x => x.RoadieId == release.Artist.RoadieId);
|
||||
artist.LastPlayed = now;
|
||||
artist.PlayedCount = (artist.PlayedCount ?? 0) + 1;
|
||||
|
||||
data.Artist trackArtist = null;
|
||||
if (track.ArtistId.HasValue)
|
||||
{
|
||||
trackArtist = this.DbContext.Artists.FirstOrDefault(x => x.Id == track.ArtistId);
|
||||
trackArtist.LastPlayed = now;
|
||||
trackArtist.PlayedCount = (trackArtist.PlayedCount ?? 0) + 1;
|
||||
this.CacheManager.ClearRegion(trackArtist.CacheRegion);
|
||||
}
|
||||
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
|
||||
this.CacheManager.ClearRegion(track.CacheRegion);
|
||||
this.CacheManager.ClearRegion(track.ReleaseMedia.Release.CacheRegion);
|
||||
this.CacheManager.ClearRegion(track.ReleaseMedia.Release.Artist.CacheRegion);
|
||||
this.CacheManager.ClearRegion(user.CacheRegion);
|
||||
|
||||
success = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -78,7 +118,7 @@ namespace Roadie.Library.Scrobble
|
|||
this.Logger.LogError(ex, $"Error in Scrobble, Creating UserTrack: User `{ roadieUser}` TrackId [{ track.Id }");
|
||||
}
|
||||
sw.Stop();
|
||||
this.Logger.LogInformation($"RoadieScrobbler: RoadieUser `{ roadieUser }` { (isNowPlaying ? "NowPlaying" : "Scrobble") } `{ scrobble }`");
|
||||
this.Logger.LogInformation($"RoadieScrobbler: RoadieUser `{ roadieUser }` Scrobble `{ scrobble }`");
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
Data = success,
|
||||
|
|
|
@ -4,6 +4,7 @@ using Roadie.Library.Configuration;
|
|||
using Roadie.Library.Encoding;
|
||||
using Roadie.Library.MetaData.LastFm;
|
||||
using Roadie.Library.Models.Users;
|
||||
using Roadie.Library.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -21,18 +22,21 @@ namespace Roadie.Library.Scrobble
|
|||
private data.IRoadieDbContext DbContext { get; }
|
||||
private ILogger Logger { get; }
|
||||
private IHttpEncoder HttpEncoder { get; }
|
||||
private IHttpContext HttpContext { get; }
|
||||
|
||||
private IEnumerable<IScrobblerIntegration> Scrobblers { get; }
|
||||
|
||||
public ScrobbleHandler(IRoadieSettings configuration, ILogger<ScrobbleHandler> logger, data.IRoadieDbContext dbContext, ICacheManager cacheManager, IHttpEncoder httpEncoder)
|
||||
public ScrobbleHandler(IRoadieSettings configuration, ILogger<ScrobbleHandler> logger, data.IRoadieDbContext dbContext,
|
||||
ICacheManager cacheManager, IHttpEncoder httpEncoder, IHttpContext httpContext)
|
||||
{
|
||||
Logger = logger;
|
||||
Configuration = configuration;
|
||||
DbContext = dbContext;
|
||||
HttpEncoder = httpEncoder;
|
||||
HttpContext = httpContext;
|
||||
var scrobblers = new List<IScrobblerIntegration>
|
||||
{
|
||||
new RoadieScrobbler(configuration, logger, dbContext, cacheManager)
|
||||
new RoadieScrobbler(configuration, logger, dbContext, cacheManager, httpContext)
|
||||
};
|
||||
if (configuration.Integrations.LastFmProviderEnabled)
|
||||
{
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using Roadie.Library.Caching;
|
||||
using Roadie.Library.Configuration;
|
||||
using Roadie.Library.Models.Users;
|
||||
using Roadie.Library.Utility;
|
||||
using System.Threading.Tasks;
|
||||
using data = Roadie.Library.Data;
|
||||
|
||||
|
@ -13,13 +14,16 @@ namespace Roadie.Library.Scrobble
|
|||
protected IRoadieSettings Configuration { get; }
|
||||
protected data.IRoadieDbContext DbContext { get; }
|
||||
protected ILogger Logger { get; }
|
||||
protected IHttpContext HttpContext { get; }
|
||||
|
||||
public ScrobblerIntegrationBase(IRoadieSettings configuration, ILogger logger, data.IRoadieDbContext dbContext, ICacheManager cacheManager)
|
||||
public ScrobblerIntegrationBase(IRoadieSettings configuration, ILogger logger, data.IRoadieDbContext dbContext,
|
||||
ICacheManager cacheManager, IHttpContext httpContext)
|
||||
{
|
||||
Logger = logger;
|
||||
Configuration = configuration;
|
||||
DbContext = dbContext;
|
||||
CacheManager = cacheManager;
|
||||
HttpContext = httpContext;
|
||||
}
|
||||
|
||||
public abstract Task<OperationResult<bool>> NowPlaying(User roadieUser, ScrobbleInfo scrobble);
|
||||
|
|
|
@ -40,7 +40,9 @@ namespace Roadie.Library.MetaData.LastFm
|
|||
{
|
||||
get
|
||||
{
|
||||
return this.Configuration.Integrations.LastFmProviderEnabled;
|
||||
return this.Configuration.Integrations.LastFmProviderEnabled &&
|
||||
!string.IsNullOrEmpty(this.Configuration.Integrations.LastFMApiKey) &&
|
||||
!string.IsNullOrEmpty(this.Configuration.Integrations.LastFmApiSecret);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using Roadie.Library.Models;
|
||||
using Roadie.Library.Models.Pagination;
|
||||
using Roadie.Library.Models.Users;
|
||||
using Roadie.Library.Scrobble;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -9,6 +10,8 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
public interface IPlayActivityService
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ using Roadie.Library.Encoding;
|
|||
using Roadie.Library.Models;
|
||||
using Roadie.Library.Models.Pagination;
|
||||
using Roadie.Library.Models.Users;
|
||||
using Roadie.Library.Scrobble;
|
||||
using Roadie.Library.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -22,6 +23,7 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
public class PlayActivityService : ServiceBase, IPlayActivityService
|
||||
{
|
||||
protected IScrobbleHandler ScrobblerHandler { get; }
|
||||
protected IHubContext<PlayActivityHub> PlayActivityHub { get; }
|
||||
|
||||
public PlayActivityService(IRoadieSettings configuration,
|
||||
|
@ -30,10 +32,12 @@ namespace Roadie.Api.Services
|
|||
data.IRoadieDbContext dbContext,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<PlayActivityService> logger,
|
||||
IHubContext<PlayActivityHub> playHubContext)
|
||||
IScrobbleHandler scrobbleHandler,
|
||||
IHubContext<PlayActivityHub> playActivityHub)
|
||||
: base(configuration, httpEncoder, dbContext, cacheManager, logger, httpContext)
|
||||
{
|
||||
this.PlayActivityHub = playHubContext;
|
||||
this.PlayActivityHub = playActivityHub;
|
||||
this.ScrobblerHandler = scrobbleHandler;
|
||||
}
|
||||
|
||||
public Task<Library.Models.Pagination.PagedResult<PlayActivityList>> List(PagedRequest request, User roadieUser = null, DateTime? newerThan = null)
|
||||
|
@ -113,5 +117,90 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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))
|
||||
{
|
||||
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 pl = new PlayActivityList
|
||||
{
|
||||
Artist = new DataToken
|
||||
{
|
||||
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()
|
||||
},
|
||||
Release = new DataToken
|
||||
{
|
||||
Text = track.ReleaseMedia.Release.Title,
|
||||
Value = track.ReleaseMedia.Release.RoadieId.ToString()
|
||||
},
|
||||
Track = new DataToken
|
||||
{
|
||||
Text = track.Title,
|
||||
Value = track.RoadieId.ToString()
|
||||
},
|
||||
User = new DataToken
|
||||
{
|
||||
Text = roadieUser.UserName,
|
||||
Value = roadieUser.UserId.ToString()
|
||||
},
|
||||
ArtistThumbnail = this.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",
|
||||
UserRating = userTrack?.Rating,
|
||||
UserThumbnail = this.MakeUserThumbnailImage(roadieUser.UserId)
|
||||
};
|
||||
try
|
||||
{
|
||||
await this.PlayActivityHub.Clients.All.SendAsync("SendActivity", pl);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -57,7 +57,7 @@ namespace Roadie.Api.Controllers
|
|||
return this._currentUser;
|
||||
}
|
||||
|
||||
protected async Task<IActionResult> StreamTrack(Guid id, ITrackService trackService, IScrobbleHandler scrobbleHandler, models.User currentUser = null)
|
||||
protected async Task<IActionResult> StreamTrack(Guid id, ITrackService trackService, IPlayActivityService playActivityService, models.User currentUser = null)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
var timings = new Dictionary<string, long>();
|
||||
|
@ -126,15 +126,7 @@ namespace Roadie.Api.Controllers
|
|||
TimePlayed = DateTime.UtcNow,
|
||||
TrackId = id
|
||||
};
|
||||
if(!info.Data.IsFullRequest)
|
||||
{
|
||||
await scrobbleHandler.NowPlaying(user, scrobble);
|
||||
}
|
||||
else
|
||||
{
|
||||
await scrobbleHandler.Scrobble(user, scrobble);
|
||||
}
|
||||
|
||||
await playActivityService.NowPlaying(user, scrobble);
|
||||
sw.Stop();
|
||||
this.Logger.LogInformation($"StreamTrack ElapsedTime [{ sw.ElapsedMilliseconds }], Timings [{ JsonConvert.SerializeObject(timings) }], StreamInfo `{ info?.Data.ToString() }`");
|
||||
return new EmptyResult();
|
||||
|
|
|
@ -22,18 +22,18 @@ namespace Roadie.Api.Controllers
|
|||
[Authorize]
|
||||
public class PlayController : EntityControllerBase
|
||||
{
|
||||
private IScrobbleHandler ScrobbleHandler { get; }
|
||||
private IPlayActivityService PlayActivityService { get; }
|
||||
private IReleaseService ReleaseService { get; }
|
||||
private ITrackService TrackService { get; }
|
||||
|
||||
public PlayController(ITrackService trackService, IReleaseService releaseService, IScrobbleHandler scrobblerHandler,
|
||||
public PlayController(ITrackService trackService, IReleaseService releaseService, IPlayActivityService playActivityService,
|
||||
ILoggerFactory logger, ICacheManager cacheManager, UserManager<ApplicationUser> userManager,
|
||||
IRoadieSettings roadieSettings)
|
||||
: base(cacheManager, roadieSettings, userManager)
|
||||
{
|
||||
this.Logger = logger.CreateLogger("RoadieApi.Controllers.PlayController");
|
||||
this.TrackService = trackService;
|
||||
this.ScrobbleHandler = scrobblerHandler;
|
||||
this.PlayActivityService = playActivityService;
|
||||
this.ReleaseService = releaseService;
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ namespace Roadie.Api.Controllers
|
|||
[ProducesResponseType(404)]
|
||||
public async Task<IActionResult> Scrobble(Guid id, string startedPlaying, bool isRandom)
|
||||
{
|
||||
var result = await this.ScrobbleHandler.Scrobble(await this.CurrentUserModel(), new ScrobbleInfo
|
||||
var result = await this.PlayActivityService.Scrobble(await this.CurrentUserModel(), new ScrobbleInfo
|
||||
{
|
||||
TrackId = id,
|
||||
TimePlayed = SafeParser.ToDateTime(startedPlaying) ?? DateTime.UtcNow,
|
||||
|
@ -109,7 +109,7 @@ namespace Roadie.Api.Controllers
|
|||
{
|
||||
return StatusCode((int)HttpStatusCode.Unauthorized);
|
||||
}
|
||||
return await base.StreamTrack(id, this.TrackService, this.ScrobbleHandler, this.UserModelForUser(user));
|
||||
return await base.StreamTrack(id, this.TrackService, this.PlayActivityService, this.UserModelForUser(user));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
using Mapster;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using Roadie.Api.ModelBinding;
|
||||
|
@ -12,6 +11,7 @@ using Roadie.Library.Extensions;
|
|||
using Roadie.Library.Identity;
|
||||
using Roadie.Library.Models.ThirdPartyApi.Subsonic;
|
||||
using Roadie.Library.Scrobble;
|
||||
using Roadie.Library.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -24,7 +24,7 @@ namespace Roadie.Api.Controllers
|
|||
[ApiController]
|
||||
public class SubsonicController : EntityControllerBase
|
||||
{
|
||||
private IScrobbleHandler ScrobbleHandler { get; }
|
||||
private IPlayActivityService PlayActivityService { get; }
|
||||
private IReleaseService ReleaseService { get; }
|
||||
private ISubsonicService SubsonicService { get; }
|
||||
|
||||
|
@ -35,8 +35,8 @@ namespace Roadie.Api.Controllers
|
|||
|
||||
private ITrackService TrackService { get; }
|
||||
|
||||
public SubsonicController(ISubsonicService subsonicService, ITrackService trackService, IReleaseService releaseService,
|
||||
IScrobbleHandler scrobbleHandler, ILoggerFactory logger, ICacheManager cacheManager,
|
||||
public SubsonicController(ISubsonicService subsonicService, ITrackService trackService, IReleaseService releaseService,
|
||||
IPlayActivityService playActivityService, ILoggerFactory logger, ICacheManager cacheManager,
|
||||
UserManager<ApplicationUser> userManager, IRoadieSettings roadieSettings)
|
||||
: base(cacheManager, roadieSettings, userManager)
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ namespace Roadie.Api.Controllers
|
|||
this.SubsonicService = subsonicService;
|
||||
this.TrackService = trackService;
|
||||
this.ReleaseService = releaseService;
|
||||
this.ScrobbleHandler = scrobbleHandler;
|
||||
this.PlayActivityService = playActivityService;
|
||||
}
|
||||
|
||||
[HttpGet("addChatMessage.view")]
|
||||
|
@ -130,7 +130,7 @@ namespace Roadie.Api.Controllers
|
|||
var trackId = request.TrackId;
|
||||
if (trackId != null)
|
||||
{
|
||||
return await base.StreamTrack(trackId.Value, this.TrackService, this.ScrobbleHandler, this.SubsonicUser);
|
||||
return await base.StreamTrack(trackId.Value, this.TrackService, this.PlayActivityService, this.SubsonicUser);
|
||||
}
|
||||
var releaseId = request.ReleaseId;
|
||||
if (releaseId != null)
|
||||
|
@ -635,6 +635,31 @@ namespace Roadie.Api.Controllers
|
|||
return this.BuildResponse(request, result);
|
||||
}
|
||||
|
||||
[HttpGet("scrobble.view")]
|
||||
[HttpGet("scrobble")]
|
||||
[HttpPost("scrobble.view")]
|
||||
[HttpPost("scrobble")]
|
||||
[ProducesResponseType(200)]
|
||||
public async Task<IActionResult> Scrobble(SubsonicRequest request)
|
||||
{
|
||||
var authResult = await this.AuthenticateUser(request);
|
||||
if (authResult != null)
|
||||
{
|
||||
return authResult;
|
||||
}
|
||||
var timePlayed = string.IsNullOrEmpty(request.time) ? DateTime.UtcNow.AddDays(-1) : SafeParser.ToNumber<long>(request.time).FromUnixTime();
|
||||
var scrobblerResponse = await this.PlayActivityService.Scrobble(this.SubsonicUser, new ScrobbleInfo
|
||||
{
|
||||
TrackId = request.TrackId.Value,
|
||||
TimePlayed = timePlayed
|
||||
});
|
||||
return this.BuildResponse(request, new SubsonicOperationResult<Response>
|
||||
{
|
||||
IsSuccess = scrobblerResponse.IsSuccess,
|
||||
Data = new Response()
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns albums, artists and songs matching the given search criteria. Supports paging through the result.
|
||||
/// </summary>
|
||||
|
@ -723,7 +748,7 @@ namespace Roadie.Api.Controllers
|
|||
{
|
||||
return NotFound("Invalid TrackId");
|
||||
}
|
||||
return await base.StreamTrack(trackId.Value, this.TrackService, this.ScrobbleHandler, this.SubsonicUser);
|
||||
return await base.StreamTrack(trackId.Value, this.TrackService, this.PlayActivityService, this.SubsonicUser);
|
||||
}
|
||||
|
||||
[HttpGet("unstar.view")]
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"Roadie.Api": {
|
||||
"commandName": "Project",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
"ASPNETCORE_ENVIRONMENT": "Production"
|
||||
},
|
||||
"applicationUrl": "http://localhost:5123/"
|
||||
}
|
||||
|
|
|
@ -96,17 +96,17 @@
|
|||
"ApiKeys": [
|
||||
{
|
||||
"ApiName": "BingImageSearch",
|
||||
"Key": "<KEY HERE>"
|
||||
"Key": ""
|
||||
},
|
||||
{
|
||||
"ApiName": "LastFMApiKey",
|
||||
"Key": "<KEY HERE>",
|
||||
"KeySecret": "<SECRET HERE>"
|
||||
"Key": "",
|
||||
"KeySecret": ""
|
||||
},
|
||||
{
|
||||
"ApiName": "DiscogsConsumerKey",
|
||||
"Key": "<KEY HERE>",
|
||||
"KeySecret": "<SECRET HERE>"
|
||||
"Key": "",
|
||||
"KeySecret": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue