Subsonic API work.

This commit is contained in:
Steven Hildreth 2018-11-25 15:15:51 -06:00
parent be7aa45f16
commit ec0ecd7b00
8 changed files with 133 additions and 5 deletions

View file

@ -530,6 +530,34 @@ namespace Roadie.Api.Controllers
return this.BuildResponse(request, result, "topSongs");
}
[HttpGet("getChatMessages.view")]
[HttpPost("getChatMessages.view")]
[ProducesResponseType(200)]
public async Task<IActionResult> GetChatMessages(SubsonicRequest request, long? since)
{
var authResult = await this.AuthenticateUser(request);
if (authResult != null)
{
return authResult;
}
var result = await this.SubsonicService.GetChatMessages(request, this.SubsonicUser, since);
return this.BuildResponse(request, result, "chatMessages");
}
[HttpGet("addChatMessage.view")]
[HttpPost("addChatMessage.view")]
[ProducesResponseType(200)]
public async Task<IActionResult> AddChatMessage(SubsonicRequest request)
{
var authResult = await this.AuthenticateUser(request);
if (authResult != null)
{
return authResult;
}
var result = await this.SubsonicService.AddChatMessage(request, this.SubsonicUser);
return this.BuildResponse(request, result);
}
[HttpGet("getUser.view")]
[HttpPost("getUser.view")]
[ProducesResponseType(200)]

View file

@ -39,6 +39,7 @@ namespace Roadie.Api.ModelBinding
{ "musicFolderId", null },
{ "offset", null },
{ "p", null },
{ "message", null },
{ "query", null },
{ "s", null },
{ "size", null },
@ -78,6 +79,7 @@ namespace Roadie.Api.ModelBinding
modelDictionary["type"] = queryDictionary.ContainsKey("type") ? SafeParser.ToEnum<ListType>(queryDictionary["type"].First()) : ListType.AlphabeticalByName;
modelDictionary["u"] = queryDictionary.ContainsKey("u") ? queryDictionary["u"].First() : null;
modelDictionary["v"] = queryDictionary.ContainsKey("v") ? queryDictionary["v"].First() : null;
modelDictionary["message"] = queryDictionary.ContainsKey("message") ? queryDictionary["message"].First() : null;
// Setup model dictionary from Posted Body values
if (!bindingContext.HttpContext.Request.Method.Equals("GET", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(bindingContext.HttpContext.Request.ContentType))
@ -113,6 +115,7 @@ namespace Roadie.Api.ModelBinding
Genre = SafeParser.ToString(modelDictionary["genre"]),
id = SafeParser.ToString(modelDictionary["id"]),
MusicFolderId = SafeParser.ToNumber<int?>(modelDictionary["musicFolderId"]),
Message = SafeParser.ToString(modelDictionary["message"]),
Offset = SafeParser.ToNumber<int?>(modelDictionary["offset"]),
p = SafeParser.ToString(modelDictionary["p"]),
Query = SafeParser.ToString(modelDictionary["query"]),

View file

@ -1,17 +1,20 @@
using Roadie.Library.Identity;
using Roadie.Library.Models.ThirdPartyApi.Subsonic;
using Roadie.Library.Models.ThirdPartyApi.Subsonic;
using System.Threading.Tasks;
namespace Roadie.Api.Services
{
public interface ISubsonicService
{
Task<SubsonicOperationResult<Response>> AddChatMessage(Request request, Roadie.Library.Models.Users.User roadieUser);
Task<SubsonicOperationResult<SubsonicAuthenticateResponse>> Authenticate(Request request);
Task<SubsonicOperationResult<Response>> CreateBookmark(Request request, Roadie.Library.Models.Users.User roadieUser, int position, string comment);
Task<SubsonicOperationResult<Response>> CreatePlaylist(Request request, Roadie.Library.Models.Users.User roadieUser, string name, string[] songIds, string playlistId = null);
Task<SubsonicOperationResult<Response>> DeleteBookmark(Request request, Roadie.Library.Models.Users.User roadieUser);
Task<SubsonicOperationResult<Response>> DeletePlaylist(Request request, Roadie.Library.Models.Users.User roadieUser);
Task<SubsonicOperationResult<Response>> GetAlbum(Request request, Roadie.Library.Models.Users.User roadieUser);
@ -28,6 +31,8 @@ namespace Roadie.Api.Services
Task<SubsonicOperationResult<Response>> GetBookmarks(Request request, Roadie.Library.Models.Users.User roadieUser);
Task<SubsonicOperationResult<Response>> GetChatMessages(Request request, Roadie.Library.Models.Users.User roadieUser, long? since);
Task<SubsonicFileOperationResult<Roadie.Library.Models.Image>> GetCoverArt(Request request, int? size);
Task<SubsonicOperationResult<Response>> GetGenres(Request request);
@ -42,6 +47,8 @@ namespace Roadie.Api.Services
Task<SubsonicOperationResult<Response>> GetMusicFolders(Request request);
Task<SubsonicOperationResult<Response>> GetNowPlaying(Request request, Roadie.Library.Models.Users.User roadieUser);
Task<SubsonicOperationResult<Response>> GetPlaylist(Request request, Roadie.Library.Models.Users.User roadieUser);
Task<SubsonicOperationResult<Response>> GetPlaylists(Request request, Roadie.Library.Models.Users.User roadieUser, string filterToUserName);
@ -66,13 +73,12 @@ namespace Roadie.Api.Services
SubsonicOperationResult<Response> Ping(Request request);
Task<SubsonicOperationResult<Response>> GetNowPlaying(Request request, Roadie.Library.Models.Users.User roadieUser);
Task<SubsonicOperationResult<Response>> Search(Request request, Roadie.Library.Models.Users.User roadieUser, SearchVersion version);
Task<SubsonicOperationResult<Response>> ToggleStar(Request request, Roadie.Library.Models.Users.User roadieUser, bool star, string[] albumIds = null, string[] artistIds = null);
Task<SubsonicOperationResult<Response>> SetRating(Request request, Roadie.Library.Models.Users.User roadieUser, short rating);
Task<SubsonicOperationResult<Response>> ToggleStar(Request request, Roadie.Library.Models.Users.User roadieUser, bool star, string[] albumIds = null, string[] artistIds = null);
Task<SubsonicOperationResult<Response>> UpdatePlaylist(Request request, Roadie.Library.Models.Users.User roadieUser, string playlistId, string name = null, string comment = null, bool? isPublic = null, string[] songIdsToAdd = null, int[] songIndexesToRemove = null);
}
}

View file

@ -1643,6 +1643,68 @@ namespace Roadie.Api.Services
};
}
/// <summary>
/// Returns the current visible (non-expired) chat messages.
/// </summary>
public async Task<subsonic.SubsonicOperationResult<subsonic.Response>> GetChatMessages(subsonic.Request request, User roadieUser, long? since)
{
DateTime? messagesSince = since.HasValue ? (DateTime?)since.Value.FromUnixTime() : null;
var chatMessages = (from cm in this.DbContext.ChatMessages
join u in this.DbContext.Users on cm.UserId equals u.Id
where messagesSince == null || cm.CreatedDate >= messagesSince
where cm.Status != Library.Enums.Statuses.Deleted
orderby cm.CreatedDate descending
select new subsonic.ChatMessage
{
message = cm.Message,
username = u.UserName,
time = cm.CreatedDate.ToUnixTime()
}).ToArray();
return new subsonic.SubsonicOperationResult<subsonic.Response>
{
IsSuccess = true,
Data = new subsonic.Response
{
version = SubsonicService.SubsonicVersion,
status = subsonic.ResponseStatus.ok,
ItemElementName = subsonic.ItemChoiceType.chatMessages,
Item = new subsonic.ChatMessages
{
chatMessage = chatMessages.ToArray()
}
}
};
}
/// <summary>
/// Adds a message to the chat log.
/// </summary>
public async Task<subsonic.SubsonicOperationResult<subsonic.Response>> AddChatMessage(subsonic.Request request, User roadieUser)
{
if(string.IsNullOrEmpty(request.Message))
{
return new subsonic.SubsonicOperationResult<subsonic.Response>(subsonic.ErrorCodes.RequiredParameterMissing, $"Message is required");
}
var chatMessage = new data.ChatMessage
{
UserId = roadieUser.Id,
Message = request.Message
};
this.DbContext.ChatMessages.Add(chatMessage);
await this.DbContext.SaveChangesAsync();
return new subsonic.SubsonicOperationResult<subsonic.Response>
{
IsSuccess = true,
Data = new subsonic.Response
{
version = SubsonicService.SubsonicVersion,
status = subsonic.ResponseStatus.ok
}
};
}
#region Privates
private async Task<subsonic.SubsonicOperationResult<subsonic.Response>> GetArtistsAction(subsonic.Request request, User roadieUser)

View file

@ -0,0 +1,24 @@
using Roadie.Library.Identity;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;
namespace Roadie.Library.Data
{
[Table("chatMessage")]
public class ChatMessage : EntityBase
{
public ApplicationUser User { get; set; }
[Column("userId")]
[Required]
public int UserId { get; set; }
[Column("message")]
[Required]
[MaxLength(5000)]
public string Message { get; set; }
}
}

View file

@ -17,6 +17,7 @@ namespace Roadie.Library.Data
DbSet<Artist> Artists { get; set; }
DbSet<Bookmark> Bookmarks { get; set; }
ChangeTracker ChangeTracker { get; }
DbSet<ChatMessage> ChatMessages { get; set; }
DbSet<CollectionRelease> CollectionReleases { get; set; }
DbSet<Collection> Collections { get; set; }
DatabaseFacade Database { get; }

View file

@ -12,6 +12,7 @@ namespace Roadie.Library.Data
public DbSet<ArtistGenre> ArtistGenres { get; set; }
public DbSet<Artist> Artists { get; set; }
public DbSet<Bookmark> Bookmarks { get; set; }
public DbSet<ChatMessage> ChatMessages { get; set; }
public DbSet<CollectionRelease> CollectionReleases { get; set; }
public DbSet<Collection> Collections { get; set; }
public DbSet<Genre> Genres { get; set; }

View file

@ -232,6 +232,9 @@ namespace Roadie.Library.Models.ThirdPartyApi.Subsonic
/// </summary>
public int? MusicFolderId { get; set; }
// When adding a chat message this is the message to add
public string Message { get; set; }
/// <summary>
/// The list offset. Useful if you for example want to page through the list of newest albums.
/// </summary>