mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-05-17 15:22:26 +00:00
Implement hearting playlists
This commit is contained in:
parent
1d4d143519
commit
4483819bd7
6 changed files with 185 additions and 8 deletions
|
@ -197,6 +197,69 @@ public class ListController : ControllerBase
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Hearted Playlists
|
||||||
|
|
||||||
|
[HttpGet("favouritePlaylists/{username}")]
|
||||||
|
public async Task<IActionResult> GetFavouritePlaylists(string username, [FromQuery] int pageStart, [FromQuery] int pageSize)
|
||||||
|
{
|
||||||
|
GameToken? token = await this.database.GameTokenFromRequest(this.Request);
|
||||||
|
if (token == null) return this.StatusCode(403, "");
|
||||||
|
|
||||||
|
if (pageSize <= 0) return this.BadRequest();
|
||||||
|
|
||||||
|
User? targetUser = await this.database.Users.FirstOrDefaultAsync(u => u.Username == username);
|
||||||
|
if (targetUser == null) return this.StatusCode(403, "");
|
||||||
|
|
||||||
|
IEnumerable<Playlist> heartedPlaylists = this.database.Playlists.Where(p => p.CreatorId == targetUser.UserId)
|
||||||
|
.Skip(Math.Max(0, pageStart - 1))
|
||||||
|
.Take(Math.Min(pageSize, 30))
|
||||||
|
.AsEnumerable();
|
||||||
|
|
||||||
|
string response = heartedPlaylists.Aggregate(string.Empty, (current, p) => current + p.Serialize());
|
||||||
|
|
||||||
|
return this.Ok
|
||||||
|
(
|
||||||
|
LbpSerializer.TaggedStringElement("favouritePlaylists", response, new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "total", this.database.HeartedPlaylists.Count(p => p.UserId == targetUser.UserId) },
|
||||||
|
{ "hint_start", pageStart + Math.Min(pageSize, 30) },
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("favourite/playlist/{playlistId:int}")]
|
||||||
|
public async Task<IActionResult> AddFavouritePlaylist(int playlistId)
|
||||||
|
{
|
||||||
|
GameToken? token = await this.database.GameTokenFromRequest(this.Request);
|
||||||
|
if (token == null) return this.StatusCode(403, "");
|
||||||
|
|
||||||
|
User? user = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == token.UserId);
|
||||||
|
if (user == null) return this.BadRequest();
|
||||||
|
|
||||||
|
Playlist? playlist = await this.database.Playlists.FirstOrDefaultAsync(s => s.PlaylistId == playlistId);
|
||||||
|
if (playlist == null) return this.NotFound();
|
||||||
|
|
||||||
|
await this.database.HeartPlaylist(token.UserId, playlist);
|
||||||
|
|
||||||
|
return await this.GetFavouritePlaylists(user.Username, 1, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("unfavourite/slot/{playlistId:int}")]
|
||||||
|
public async Task<IActionResult> RemoveFavouritePlaylist(int playlistId)
|
||||||
|
{
|
||||||
|
GameToken? token = await this.database.GameTokenFromRequest(this.Request);
|
||||||
|
if (token == null) return this.StatusCode(403, "");
|
||||||
|
|
||||||
|
Playlist? playlist = await this.database.Playlists.FirstOrDefaultAsync(s => s.PlaylistId == playlistId);
|
||||||
|
if (playlist == null) return this.NotFound();
|
||||||
|
|
||||||
|
await this.database.UnheartPlaylist(token.UserId, playlist);
|
||||||
|
|
||||||
|
return this.Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#endregion Levels
|
#endregion Levels
|
||||||
|
|
||||||
#region Users
|
#region Users
|
||||||
|
|
|
@ -30,6 +30,7 @@ public class Database : DbContext
|
||||||
public DbSet<QueuedLevel> QueuedLevels { get; set; }
|
public DbSet<QueuedLevel> QueuedLevels { get; set; }
|
||||||
public DbSet<HeartedLevel> HeartedLevels { get; set; }
|
public DbSet<HeartedLevel> HeartedLevels { get; set; }
|
||||||
public DbSet<HeartedProfile> HeartedProfiles { get; set; }
|
public DbSet<HeartedProfile> HeartedProfiles { get; set; }
|
||||||
|
public DbSet<HeartedPlaylist> HeartedPlaylists { get; set; }
|
||||||
public DbSet<Comment> Comments { get; set; }
|
public DbSet<Comment> Comments { get; set; }
|
||||||
public DbSet<GameToken> GameTokens { get; set; }
|
public DbSet<GameToken> GameTokens { get; set; }
|
||||||
public DbSet<WebToken> WebTokens { get; set; }
|
public DbSet<WebToken> WebTokens { get; set; }
|
||||||
|
@ -51,6 +52,7 @@ public class Database : DbContext
|
||||||
public DbSet<PasswordResetToken> PasswordResetTokens { get; set; }
|
public DbSet<PasswordResetToken> PasswordResetTokens { get; set; }
|
||||||
public DbSet<RegistrationToken> RegistrationTokens { get; set; }
|
public DbSet<RegistrationToken> RegistrationTokens { get; set; }
|
||||||
public DbSet<APIKey> APIKeys { get; set; }
|
public DbSet<APIKey> APIKeys { get; set; }
|
||||||
|
public DbSet<Playlist> Playlists { get; set; }
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder options)
|
protected override void OnConfiguring(DbContextOptionsBuilder options)
|
||||||
=> options.UseMySql(ServerConfiguration.Instance.DbConnectionString, MySqlServerVersion.LatestSupportedServerVersion);
|
=> options.UseMySql(ServerConfiguration.Instance.DbConnectionString, MySqlServerVersion.LatestSupportedServerVersion);
|
||||||
|
@ -231,6 +233,28 @@ public class Database : DbContext
|
||||||
await this.SaveChangesAsync();
|
await this.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task HeartPlaylist(int userId, Playlist heartedPlaylist)
|
||||||
|
{
|
||||||
|
HeartedPlaylist? heartedList = await this.HeartedPlaylists.FirstOrDefaultAsync(p => p.UserId == userId && p.PlaylistId == heartedPlaylist.PlaylistId);
|
||||||
|
if (heartedList != null) return;
|
||||||
|
|
||||||
|
this.HeartedPlaylists.Add(new HeartedPlaylist()
|
||||||
|
{
|
||||||
|
PlaylistId = heartedPlaylist.PlaylistId,
|
||||||
|
UserId = userId,
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UnheartPlaylist(int userId, Playlist heartedPlaylist)
|
||||||
|
{
|
||||||
|
HeartedPlaylist? heartedList = await this.HeartedPlaylists.FirstOrDefaultAsync(p => p.UserId == userId && p.PlaylistId == heartedPlaylist.PlaylistId);
|
||||||
|
if (heartedList != null) this.HeartedPlaylists.Remove(heartedList);
|
||||||
|
|
||||||
|
await this.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
public async Task HeartLevel(int userId, Slot heartedSlot)
|
public async Task HeartLevel(int userId, Slot heartedSlot)
|
||||||
{
|
{
|
||||||
HeartedLevel? heartedLevel = await this.HeartedLevels.FirstOrDefaultAsync(q => q.UserId == userId && q.SlotId == heartedSlot.SlotId);
|
HeartedLevel? heartedLevel = await this.HeartedLevels.FirstOrDefaultAsync(q => q.UserId == userId && q.SlotId == heartedSlot.SlotId);
|
||||||
|
|
|
@ -27,6 +27,8 @@ public class Playlist
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public User? Creator { get; set; }
|
public User? Creator { get; set; }
|
||||||
|
|
||||||
|
public int Hearts(Database database) => database.HeartedPlaylists.Count(p => p.HeartedPlaylistId == this.PlaylistId);
|
||||||
|
|
||||||
public string SlotCollection { get; set; } = "";
|
public string SlotCollection { get; set; } = "";
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
|
@ -50,9 +52,7 @@ public class Playlist
|
||||||
LbpSerializer.StringElement("name", this.Name) +
|
LbpSerializer.StringElement("name", this.Name) +
|
||||||
LbpSerializer.StringElement("description", this.Description) +
|
LbpSerializer.StringElement("description", this.Description) +
|
||||||
LbpSerializer.StringElement("levels", this.SlotIds.Length) +
|
LbpSerializer.StringElement("levels", this.SlotIds.Length) +
|
||||||
LbpSerializer.StringElement("thumbs", 0) +
|
LbpSerializer.StringElement("hearts", this.Hearts(database)) +
|
||||||
LbpSerializer.StringElement("plays", 0) +
|
|
||||||
LbpSerializer.StringElement("unique_plays", 0) +
|
|
||||||
LbpSerializer.StringElement("levels_quota", ServerConfiguration.Instance.UserGeneratedContentLimits.ListsQuota) +
|
LbpSerializer.StringElement("levels_quota", ServerConfiguration.Instance.UserGeneratedContentLimits.ListsQuota) +
|
||||||
this.SerializeIcons(database);
|
this.SerializeIcons(database);
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ public class Playlist
|
||||||
private string SerializeIcons(Database database)
|
private string SerializeIcons(Database database)
|
||||||
{
|
{
|
||||||
string iconList = this.SlotIds.Select(id => database.Slots.FirstOrDefault(s => s.SlotId == id))
|
string iconList = this.SlotIds.Select(id => database.Slots.FirstOrDefault(s => s.SlotId == id))
|
||||||
.Where(slot => slot != null)
|
.Where(slot => slot != null && slot.IconHash.Length > 0)
|
||||||
.Aggregate(string.Empty, (current, slot) => current + LbpSerializer.StringElement("icon", slot?.IconHash));
|
.Aggregate(string.Empty, (current, slot) => current + LbpSerializer.StringElement("icon", slot?.IconHash));
|
||||||
return LbpSerializer.StringElement("icons", iconList);
|
return LbpSerializer.StringElement("icons", iconList);
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,10 @@ public class User
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public int HeartedUsers => this.database.HeartedProfiles.Count(p => p.UserId == this.UserId);
|
public int HeartedUsers => this.database.HeartedProfiles.Count(p => p.UserId == this.UserId);
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
[JsonIgnore]
|
||||||
|
public int HeartedPlaylists => this.database.HeartedPlaylists.Count(p => p.UserId == this.UserId);
|
||||||
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public int QueuedLevels => this.database.QueuedLevels.Count(p => p.UserId == this.UserId);
|
public int QueuedLevels => this.database.QueuedLevels.Count(p => p.UserId == this.UserId);
|
||||||
|
@ -218,6 +222,7 @@ public class User
|
||||||
LbpSerializer.StringElement("location", this.Location.Serialize()) +
|
LbpSerializer.StringElement("location", this.Location.Serialize()) +
|
||||||
LbpSerializer.StringElement<int>("favouriteSlotCount", this.HeartedLevels, true) +
|
LbpSerializer.StringElement<int>("favouriteSlotCount", this.HeartedLevels, true) +
|
||||||
LbpSerializer.StringElement<int>("favouriteUserCount", this.HeartedUsers, true) +
|
LbpSerializer.StringElement<int>("favouriteUserCount", this.HeartedUsers, true) +
|
||||||
|
LbpSerializer.StringElement<int>("favouritePlaylistCount", this.HeartedPlaylists, true) +
|
||||||
LbpSerializer.StringElement<int>("lolcatftwCount", this.QueuedLevels, true) +
|
LbpSerializer.StringElement<int>("lolcatftwCount", this.QueuedLevels, true) +
|
||||||
LbpSerializer.StringElement<string>("pins", this.Pins, true);
|
LbpSerializer.StringElement<string>("pins", this.Pins, true);
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace ProjectLighthouse.Migrations
|
||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.HasAnnotation("ProductVersion", "6.0.8")
|
.HasAnnotation("ProductVersion", "6.0.9")
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||||
|
|
||||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Administration.CompletedMigration", b =>
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Administration.CompletedMigration", b =>
|
||||||
|
@ -172,6 +172,55 @@ namespace ProjectLighthouse.Migrations
|
||||||
b.ToTable("HeartedLevels");
|
b.ToTable("HeartedLevels");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.HeartedPlaylist", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("HeartedPlaylistId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("PlaylistId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("HeartedPlaylistId");
|
||||||
|
|
||||||
|
b.HasIndex("PlaylistId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("HeartedPlaylists");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.Playlist", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("PlaylistId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CreatorId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("SlotCollection")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("PlaylistId");
|
||||||
|
|
||||||
|
b.HasIndex("CreatorId");
|
||||||
|
|
||||||
|
b.ToTable("Playlists");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.QueuedLevel", b =>
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.QueuedLevel", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("QueuedLevelId")
|
b.Property<int>("QueuedLevelId")
|
||||||
|
@ -273,6 +322,9 @@ namespace ProjectLighthouse.Migrations
|
||||||
b.Property<int>("InternalSlotId")
|
b.Property<int>("InternalSlotId")
|
||||||
.HasColumnType("int");
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdventurePlanet")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
b.Property<long>("LastUpdated")
|
b.Property<long>("LastUpdated")
|
||||||
.HasColumnType("bigint");
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
@ -903,6 +955,9 @@ namespace ProjectLighthouse.Migrations
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("int");
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ChildSlotId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
b.Property<string>("PlayerIdCollection")
|
b.Property<string>("PlayerIdCollection")
|
||||||
.HasColumnType("longtext");
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
@ -989,6 +1044,36 @@ namespace ProjectLighthouse.Migrations
|
||||||
b.Navigation("User");
|
b.Navigation("User");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.HeartedPlaylist", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Levels.Playlist", "Playlist")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("PlaylistId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Playlist");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.Playlist", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "Creator")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CreatorId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Creator");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.QueuedLevel", b =>
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.QueuedLevel", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("LBPUnion.ProjectLighthouse.Levels.Slot", "Slot")
|
b.HasOne("LBPUnion.ProjectLighthouse.Levels.Slot", "Slot")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue