Files
Radicade/Server/Clubs/PlayerSubscriptions.cs
T
2026-10-16 23:33:13 -07:00

118 lines
3.6 KiB
C#

using Microsoft.EntityFrameworkCore;
using RadicadeServer.DB;
using RadicadeServer.Extensions;
using RadicadeServer.RecNet.Config;
namespace RadicadeServer.Clubs;
public sealed class PlayerSubscriptionRecord
{
public long subscriberAccountId { get; set; }
public long creatorAccountId { get; set; }
public DateTime createdAt { get; set; } = DateTime.UtcNow;
}
public static class PlayerSubscriptions
{
private const string ConfigKey = "PlayerSubscriptions";
private const long PersonalClubIdBase = 1_000_000_000_000L;
public static long PersonalClubId(long accountId) => accountId > 0 ? PersonalClubIdBase + accountId : 0;
public static bool IsPersonalClubId(long clubId) => clubId >= PersonalClubIdBase;
public static long? AccountIdForPersonalClub(long clubId) =>
IsPersonalClubId(clubId) ? clubId - PersonalClubIdBase : null;
public static async Task<List<PlayerSubscriptionRecord>> LoadAsync(RecDBContext db)
{
var config = await db.ServerConfig.AsNoTracking().FirstOrDefaultAsync(x => x.Key == ConfigKey);
if (config == null || string.IsNullOrWhiteSpace(config.Value)) return new List<PlayerSubscriptionRecord>();
try
{
return config.Value.FromJson<List<PlayerSubscriptionRecord>>() ?? new List<PlayerSubscriptionRecord>();
}
catch
{
return new List<PlayerSubscriptionRecord>();
}
}
private static async Task SaveAsync(RecDBContext db, List<PlayerSubscriptionRecord> subscriptions)
{
var config = await db.ServerConfig.FirstOrDefaultAsync(x => x.Key == ConfigKey);
if (config == null)
{
config = new ServerConfigVal(ConfigKey, "[]");
await db.ServerConfig.AddAsync(config);
}
config.Value = subscriptions.ToJson();
await db.SaveChangesAsync();
}
public static async Task<bool> SubscribeAsync(RecDBContext db, long subscriberId, long creatorId)
{
if (subscriberId <= 0 || creatorId <= 0 || subscriberId == creatorId) return false;
var subscriptions = await LoadAsync(db);
if (subscriptions.Any(x => x.subscriberAccountId == subscriberId && x.creatorAccountId == creatorId))
return true;
subscriptions.Add(new PlayerSubscriptionRecord
{
subscriberAccountId = subscriberId,
creatorAccountId = creatorId
});
await SaveAsync(db, subscriptions);
return true;
}
public static async Task<bool> UnsubscribeAsync(RecDBContext db, long subscriberId, long creatorId)
{
var subscriptions = await LoadAsync(db);
if (subscriptions.RemoveAll(x => x.subscriberAccountId == subscriberId && x.creatorAccountId == creatorId) == 0)
return false;
await SaveAsync(db, subscriptions);
return true;
}
public static async Task<List<long>> SubscriptionIdsAsync(RecDBContext db, long accountId) =>
(await LoadAsync(db))
.Where(x => x.subscriberAccountId == accountId)
.Select(x => x.creatorAccountId)
.Distinct()
.ToList();
public static async Task<List<long>> SubscriberIdsAsync(RecDBContext db, long accountId) =>
(await LoadAsync(db))
.Where(x => x.creatorAccountId == accountId)
.Select(x => x.subscriberAccountId)
.Distinct()
.ToList();
public static async Task<int> SubscriberCountAsync(RecDBContext db, long accountId) =>
(await SubscriberIdsAsync(db, accountId)).Count;
public static async Task<List<object>> TopCreatorsAsync(RecDBContext db, int limit)
{
var creators = (await LoadAsync(db))
.GroupBy(x => x.creatorAccountId)
.Select(group => new
{
clubId = PersonalClubId(group.Key),
accountId = group.Key,
subscriberCount = group.Select(x => x.subscriberAccountId).Distinct().Count()
})
.OrderByDescending(creator => creator.subscriberCount)
.ThenBy(creator => creator.accountId)
.Take(limit)
.ToList();
return creators.Cast<object>().ToList();
}
}