mirror of
https://github.com/JogmansonReal/Radicade.git
synced 2026-10-26 23:49:02 -07:00
Radicade Public Code
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using RadicadeServer.API.Notifications;
|
||||
using RadicadeServer.DB;
|
||||
using RadicadeServer.RecNet.Enums.Messages;
|
||||
using RadicadeServer.RecNet.Messages;
|
||||
using RadicadeServer.RecNet.Rooms;
|
||||
|
||||
namespace RadicadeServer.Admin;
|
||||
|
||||
public static class RoomBanStore
|
||||
{
|
||||
private static readonly JsonSerializerOptions JsonOptions = new() { WriteIndented = true };
|
||||
private static readonly object FileLock = new();
|
||||
|
||||
private const long CoachAccountId = 1;
|
||||
|
||||
private static string ClosedMessage(string roomName, string reason) =>
|
||||
$"We have closed the room '{roomName}' for: {reason}. We encourage creators to review our Creator Code of Conduct to help make Radicade a fun and safe place for everyone.";
|
||||
|
||||
private static string RestoredMessage(string roomName) =>
|
||||
$"We have restored the room '{roomName}' after a thorough review of the previous accusations. Thank you for continuing to follow the Creator Code of Conduct, and making Radicade a better place.";
|
||||
|
||||
public static string FilePath => Path.Join(DBConfig.PersistentLogs, "banned-rooms.json");
|
||||
|
||||
public static List<BannedRoom> Load()
|
||||
{
|
||||
lock (FileLock) return LoadLocked();
|
||||
}
|
||||
|
||||
public static BannedRoom? Find(long roomId) => Load().FirstOrDefault(x => x.RoomId == roomId);
|
||||
|
||||
public static bool IsBanned(long roomId) => Find(roomId) != null;
|
||||
|
||||
public static async Task<BannedRoom> BanAsync(RecDBContext db, RoomData room, string reason, string bannedBy)
|
||||
{
|
||||
var entry = new BannedRoom
|
||||
{
|
||||
RoomId = room.RoomId,
|
||||
Name = room.Name,
|
||||
Reason = reason,
|
||||
BannedBy = bannedBy,
|
||||
BannedAt = DateTime.UtcNow,
|
||||
PublishedAt = room.PublishedAt,
|
||||
Room = room,
|
||||
SubRooms = await db.SubRooms.AsNoTracking().Where(x => x.RoomId == room.RoomId).ToListAsync(),
|
||||
Roles = await db.RoomRoles.AsNoTracking().Where(x => x.RoomId == room.RoomId).ToListAsync(),
|
||||
Stats = await db.RoomStats.AsNoTracking().FirstOrDefaultAsync(x => x.RoomId == room.RoomId)
|
||||
};
|
||||
|
||||
Upsert(entry);
|
||||
|
||||
db.Rooms.Remove(room);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
var why = string.IsNullOrWhiteSpace(reason) ? "a breach of the Creator Code of Conduct" : reason;
|
||||
await TellOwnerAsync(room.CreatorAccountId, ClosedMessage(room.Name, why));
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
public static async Task<bool> RestoreAsync(RecDBContext db, long roomId)
|
||||
{
|
||||
var entry = Find(roomId);
|
||||
if (entry == null) return false;
|
||||
|
||||
await InsertRoomWithItsIdAsync(db, entry.Room, entry.PublishedAt);
|
||||
|
||||
Remove(roomId);
|
||||
|
||||
await TellOwnerAsync(entry.Room.CreatorAccountId, RestoredMessage(entry.Name));
|
||||
return true;
|
||||
}
|
||||
|
||||
private static async Task InsertRoomWithItsIdAsync(RecDBContext db, RoomData room, DateTime publishedAt)
|
||||
{
|
||||
var entity = db.Model.FindEntityType(typeof(RoomData))
|
||||
?? throw new InvalidOperationException("RoomData is not part of the model.");
|
||||
|
||||
var table = entity.GetTableName() ?? nameof(RoomData);
|
||||
var qualified = entity.GetSchema() is { Length: > 0 } schema ? $"[{schema}].[{table}]" : $"[{table}]";
|
||||
|
||||
var columns = new List<string>();
|
||||
var cells = new List<string>();
|
||||
var parameters = new List<object>();
|
||||
foreach (var property in entity.GetProperties())
|
||||
{
|
||||
if (property.IsShadowProperty() || property.PropertyInfo == null) continue;
|
||||
|
||||
var value = property.Name == nameof(RoomData.PublishedAt)
|
||||
? publishedAt
|
||||
: property.PropertyInfo.GetValue(room);
|
||||
|
||||
columns.Add($"[{property.GetColumnName()}]");
|
||||
|
||||
var sqlValue = ToSqlValue(value);
|
||||
if (sqlValue == null)
|
||||
{
|
||||
cells.Add("NULL");
|
||||
}
|
||||
else
|
||||
{
|
||||
cells.Add("{" + parameters.Count + "}");
|
||||
parameters.Add(sqlValue);
|
||||
}
|
||||
}
|
||||
|
||||
var sql =
|
||||
$"SET IDENTITY_INSERT {qualified} ON;\n" +
|
||||
$"INSERT INTO {qualified} ({string.Join(", ", columns)}) VALUES ({string.Join(", ", cells)});\n" +
|
||||
$"SET IDENTITY_INSERT {qualified} OFF;";
|
||||
|
||||
await db.Database.ExecuteSqlRawAsync(sql, parameters);
|
||||
}
|
||||
|
||||
private static async Task TellOwnerAsync(long ownerAccountId, string message)
|
||||
{
|
||||
if (ownerAccountId <= 0) return;
|
||||
|
||||
try
|
||||
{
|
||||
await Notify.SendMessage(ownerAccountId, new Message
|
||||
{
|
||||
Type = MessageType.CoachMessage,
|
||||
Data = message,
|
||||
FromPlayerId = CoachAccountId
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private static object? ToSqlValue(object? value) => value switch
|
||||
{
|
||||
null => null,
|
||||
Enum enumValue => Convert.ChangeType(enumValue, Enum.GetUnderlyingType(enumValue.GetType())),
|
||||
_ => value
|
||||
};
|
||||
|
||||
private static void Upsert(BannedRoom entry)
|
||||
{
|
||||
lock (FileLock)
|
||||
{
|
||||
var rooms = LoadLocked();
|
||||
rooms.RemoveAll(x => x.RoomId == entry.RoomId);
|
||||
rooms.Add(entry);
|
||||
SaveLocked(rooms);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Remove(long roomId)
|
||||
{
|
||||
lock (FileLock)
|
||||
{
|
||||
var rooms = LoadLocked();
|
||||
if (rooms.RemoveAll(x => x.RoomId == roomId) == 0) return;
|
||||
SaveLocked(rooms);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<BannedRoom> LoadLocked()
|
||||
{
|
||||
if (!File.Exists(FilePath)) return new List<BannedRoom>();
|
||||
|
||||
try
|
||||
{
|
||||
var json = File.ReadAllText(FilePath);
|
||||
var rooms = JsonSerializer.Deserialize<List<BannedRoom>>(json, JsonOptions) ?? new List<BannedRoom>();
|
||||
|
||||
foreach (var room in rooms) room.Room.PublishedAt = room.PublishedAt;
|
||||
|
||||
return rooms;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return new List<BannedRoom>();
|
||||
}
|
||||
}
|
||||
|
||||
private static void SaveLocked(List<BannedRoom> rooms)
|
||||
{
|
||||
Directory.CreateDirectory(DBConfig.PersistentLogs);
|
||||
File.WriteAllText(FilePath, JsonSerializer.Serialize(rooms, JsonOptions));
|
||||
}
|
||||
}
|
||||
|
||||
public class BannedRoom
|
||||
{
|
||||
public long RoomId { get; set; }
|
||||
public string Name { get; set; } = "";
|
||||
public string Reason { get; set; } = "";
|
||||
public string BannedBy { get; set; } = "";
|
||||
public DateTime BannedAt { get; set; }
|
||||
public DateTime PublishedAt { get; set; }
|
||||
|
||||
public RoomData Room { get; set; } = new();
|
||||
public List<SubRoom> SubRooms { get; set; } = new();
|
||||
public List<RoomRole> Roles { get; set; } = new();
|
||||
public RoomStats? Stats { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user