using DeluxeBackend.Controllers; using DeluxeBackend.Models; using DeluxeBackend.Services; using Discord; using Discord.Interactions; using Discord.WebSocket; using Microsoft.AspNetCore.Http.HttpResults; using System.Linq; using System.Net; using System.Text.Json; using System.Text.Json.Serialization; using static DeluxeBackend.Enums; using static DeluxeBackend.Extensions.RoomExtensions; using static System.Runtime.InteropServices.JavaScript.JSType; namespace DeluxeBackend.Discord.Commands { public class Debug : InteractionModuleBase { private readonly ILiteDbService db; private readonly INotificationService ws; private readonly IMessageService message; private readonly DiscordBotService discord; private readonly IHostApplicationLifetime lifetime; public readonly static ulong AdminRole = 1509152644365811752; public Debug(ILiteDbService _db, INotificationService _ws, IMessageService _message, DiscordBotService _discord, IHostApplicationLifetime _lifetime) { db = _db; ws = _ws; message = _message; discord = _discord; lifetime = _lifetime; } private bool IsAdmin() { return Context.User is SocketGuildUser guildUser && guildUser.Roles.Any(r => r.Id == AdminRole); } [SlashCommand("send_msg", ".")] public async Task send_msg(long playerId, Enums.MessageType type, string data = "") { if (data == null) { data = string.Empty; } await DeferAsync(); if (!IsAdmin()) { await FollowupAsync($"No"); return; } await message.SendMessage(db.Accounts.FindById(1), db.Accounts.FindById(playerId), type, data); await FollowupAsync($"Done"); } [SlashCommand("upload_ua", ".")] public async Task UploadUnityAsset(string id, AssetBundleType target, AssetBundleVersion version, string fileName) { await DeferAsync(); if (!IsAdmin()) { await FollowupAsync($"No"); return; } if (!Guid.TryParse(id, out var guidId)) { await FollowupAsync("Invalid GUID format."); return; } UnityAssets unityAssets = db.UnityAssets.FindOne(x => x.Id == guidId); if (unityAssets == null) { unityAssets = new(); } unityAssets.Id = guidId; UnityAsset unityAsset = new() { Filename = fileName, Target = target, Version = version }; unityAssets.Assets.Add(unityAsset); db.UnityAssets.Upsert(unityAssets); await FollowupAsync($"Done"); } public enum Version { _2022AndOlder, _2023AndNewer, }; public class RoomData2023AndNewer { [JsonRequired] public required long RoomId { get; set; } [JsonRequired] public required string Name { get; set; } [JsonRequired] public required string Description { get; set; } [JsonRequired] public required string ImageName { get; set; } [JsonRequired] public required RoomWarningMask WarningMask { get; set; } [JsonRequired] public required RoomAccessibility Accessibility { get; set; } public string? CustomWarning { get; set; } = null; [JsonRequired] public required bool SupportsScreens { get; set; } [JsonRequired] public required bool SupportsWalkVR { get; set; } [JsonRequired] public required bool SupportsTeleportVR { get; set; } [JsonRequired] public required bool SupportsJuniors { get; set; } [JsonRequired] public required List SubRooms { get; set; } [JsonRequired] public required DateTime CreatedAt { get; set; } } public class SubRoomData2023AndNewer { [JsonRequired] public required long SubRoomId { get; set; } [JsonRequired] public required long RoomId { get; set; } [JsonRequired] public required string UnitySceneId { get; set; } [JsonRequired] public required string Name { get; set; } [JsonRequired] public required CurrentSave2023AndNewer? CurrentSave { get; set; } = null; [JsonRequired] public required bool IsSandbox { get; set; } [JsonRequired] public required int MaxPlayers { get; set; } [JsonRequired] public required RoomAccessibility Accessibility { get; set; } } public class CurrentSave2023AndNewer { public Guid? UnityAssetId { get; set; } = null; [JsonRequired] public required string DataBlob { get; set; } public string? Description { get; set; } = null; [JsonRequired] public required DateTime CreatedAt { get; set; } } public class Unity2023AndNewer { [JsonRequired] public AssetBundleType Target { get; set; } [JsonRequired] public AssetBundleVersion Version { get; set; } [JsonRequired] public required string Filename { get; set; } } public class RoomData2022AndNewer { [JsonRequired] public required long RoomId { get; set; } [JsonRequired] public required string Name { get; set; } [JsonRequired] public required string Description { get; set; } [JsonRequired] public required string ImageName { get; set; } [JsonRequired] public required RoomWarningMask WarningMask { get; set; } public string? CustomWarning { get; set; } = null; [JsonRequired] public required bool SupportsScreens { get; set; } [JsonRequired] public required bool SupportsWalkVR { get; set; } [JsonRequired] public required bool SupportsTeleportVR { get; set; } [JsonRequired] public required bool SupportsJuniors { get; set; } [JsonRequired] public required List SubRooms { get; set; } } public class SubRoomData2022AndNewer { [JsonRequired] public required long SubRoomId { get; set; } [JsonRequired] public required string UnitySceneId { get; set; } [JsonRequired] public required string Name { get; set; } [JsonRequired] public required bool IsSandbox { get; set; } [JsonRequired] public required int MaxPlayers { get; set; } [JsonRequired] public required RoomAccessibility Accessibility { get; set; } public Guid? UnityAssetId { get; set; } = null; public string? DataBlob { get; set; } = null; public string? Description { get; set; } = null; } [SlashCommand("reupload_room", ".")] public async Task ReuploadRoom(IAttachment file, Version version) { await DeferAsync(); if (!IsAdmin()) { await FollowupAsync("No"); return; } if (!file.Filename.EndsWith(".json")) { await FollowupAsync("Please upload a file ending in .json!"); return; } Account? account = db.Accounts.FindOne(x => x.DiscordId == Context.User.Id); if (account == null) { await FollowupAsync("Error: Could not find your account in the database."); return; } using var httpClient = new HttpClient(); var jsonString = await httpClient.GetStringAsync(file.Url); using var httpAuthClient = new HttpClient(); httpAuthClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {ServerConfig.RRToken}"); HttpResponseMessage testreq = await httpAuthClient.GetAsync("https://accounts.rec.net/account/me"); if (testreq.StatusCode != HttpStatusCode.OK) { await FollowupAsync($"Error: Failed to authenticate with rec.net. (Status: {testreq.StatusCode})"); return; } try { Room? newRoom = null; if (version == Version._2023AndNewer) { RoomData2023AndNewer? room = JsonSerializer.Deserialize(jsonString); if (room == null) { await FollowupAsync("Error: Failed to parse the uploaded JSON into a valid room format."); return; } newRoom = new Room { Accessibility = RoomAccessibility.Private, Name = $"{room.Name}_{DateTime.UtcNow.Ticks}", Description = room.Description, ImageName = room.ImageName, CloningAllowed = false, Creator = account, CustomWarning = room.CustomWarning, WarningMask = room.WarningMask, IsDorm = room.Name == "DormRoom", IsRRO = false, }; RoomSupports RoomSup = RoomSupports.None; if (room.SupportsScreens) RoomSup |= RoomSupports.Screens; if (room.SupportsWalkVR) RoomSup |= RoomSupports.WalkVR; if (room.SupportsTeleportVR) RoomSup |= RoomSupports.TeleportVR; RoomSup |= RoomSupports.Juniors; newRoom.SupportedPlayerTypes = RoomSup; db.Rooms.Insert(newRoom); foreach (SubRoomData2023AndNewer scene in room.SubRooms) { SubRoom newScene = new() { Room = newRoom, LocationId = scene.UnitySceneId, Name = scene.Name, IsSandbox = scene.IsSandbox, MaxPlayers = scene.MaxPlayers, CanMatchmakeInto = scene.Accessibility == RoomAccessibility.Public }; db.SubRooms.Insert(newScene); if (scene.CurrentSave != null) { SubRoomSave newSave = new() { SubRoomId = newScene.Id, DataBlob = scene.CurrentSave.DataBlob, }; if (scene.CurrentSave.UnityAssetId.HasValue) { try { var jsonString2 = await httpAuthClient.GetStringAsync($"https://rooms.rec.net/unity_assets/{scene.CurrentSave.UnityAssetId.Value}/{(int)AssetBundleType.WindowsDesktop}/{(int)AssetBundleVersion.Unity_2020_3_33f1}"); Unity2023AndNewer? u = JsonSerializer.Deserialize(jsonString2); if (u == null) { await FollowupAsync($"Error: Failed to parse Unity Asset JSON from rec.net for subroom '{scene.Name}'."); return; } UnityAssets unityAssets = db.UnityAssets.FindOne(x => x.Id == scene.CurrentSave.UnityAssetId.Value); if (unityAssets == null) { unityAssets = new(); } unityAssets.Id = scene.CurrentSave.UnityAssetId.Value; UnityAsset unityAsset = new() { Filename = u.Filename, Target = u.Target, Version = u.Version }; unityAssets.Assets.Add(unityAsset); db.UnityAssets.Upsert(unityAssets); newSave.UnityAssetId = scene.CurrentSave.UnityAssetId.Value.ToString(); } catch { } try { var jsonString2 = await httpAuthClient.GetStringAsync($"https://rooms.rec.net/unity_assets/{scene.CurrentSave.UnityAssetId.Value}/{(int)AssetBundleType.MobileAndroid}/{(int)AssetBundleVersion.Unity_2020_3_33f1}"); Unity2023AndNewer? u = JsonSerializer.Deserialize(jsonString2); if (u == null) { await FollowupAsync($"Error: Failed to parse Unity Asset JSON from rec.net for subroom '{scene.Name}'."); return; } UnityAssets unityAssets = db.UnityAssets.FindOne(x => x.Id == scene.CurrentSave.UnityAssetId.Value); if (unityAssets == null) { unityAssets = new(); } unityAssets.Id = scene.CurrentSave.UnityAssetId.Value; UnityAsset unityAsset = new() { Filename = u.Filename, Target = u.Target, Version = u.Version }; unityAssets.Assets.Add(unityAsset); db.UnityAssets.Upsert(unityAssets); newSave.UnityAssetId = scene.CurrentSave.UnityAssetId.Value.ToString(); } catch { } } db.SubRoomSave.Insert(newSave); newScene.CurrentSave = newSave; db.SubRooms.Update(newScene); } } } else if (version == Version._2022AndOlder) { RoomData2022AndNewer? room = JsonSerializer.Deserialize(jsonString); if (room == null) { await FollowupAsync("Error: Failed to parse the uploaded JSON into a valid room format."); return; } newRoom = new Room { Accessibility = RoomAccessibility.Private, Name = $"{room.Name}_{DateTime.UtcNow.Ticks}", Description = room.Description, CloningAllowed = false, Creator = account, CustomWarning = room.CustomWarning, WarningMask = room.WarningMask, IsDorm = room.Name == "DormRoom", IsRRO = false, }; RoomSupports RoomSup = RoomSupports.None; if (room.SupportsScreens) RoomSup |= RoomSupports.Screens; if (room.SupportsWalkVR) RoomSup |= RoomSupports.WalkVR; if (room.SupportsTeleportVR) RoomSup |= RoomSupports.TeleportVR; RoomSup |= RoomSupports.Juniors; newRoom.SupportedPlayerTypes = RoomSup; db.Rooms.Insert(newRoom); foreach (SubRoomData2022AndNewer scene in room.SubRooms) { SubRoom newScene = new() { Room = newRoom, LocationId = scene.UnitySceneId, Name = scene.Name, IsSandbox = scene.IsSandbox, MaxPlayers = scene.MaxPlayers, CanMatchmakeInto = scene.Accessibility == RoomAccessibility.Public }; db.SubRooms.Insert(newScene); if (scene.DataBlob != null) { SubRoomSave newSave = new() { SubRoomId = newScene.Id, DataBlob = scene.DataBlob, }; if (scene.UnityAssetId.HasValue) { try { var jsonString2 = await httpAuthClient.GetStringAsync($"https://rooms.rec.net/unity_assets/{scene.UnityAssetId.Value}/{(int)AssetBundleType.WindowsDesktop}/{(int)AssetBundleVersion.Unity_2020_3_33f1}"); Unity2023AndNewer? u = JsonSerializer.Deserialize(jsonString2); if (u == null) { await FollowupAsync($"Error: Failed to parse Unity Asset JSON from rec.net for subroom '{scene.Name}'."); return; } UnityAssets unityAssets = db.UnityAssets.FindOne(x => x.Id == scene.UnityAssetId.Value); if (unityAssets == null) { unityAssets = new(); } unityAssets.Id = scene.UnityAssetId.Value; UnityAsset unityAsset = new() { Filename = u.Filename, Target = u.Target, Version = u.Version }; unityAssets.Assets.Add(unityAsset); db.UnityAssets.Upsert(unityAssets); newSave.UnityAssetId = scene.UnityAssetId.Value.ToString(); } catch { } try { var jsonString2 = await httpAuthClient.GetStringAsync($"https://rooms.rec.net/unity_assets/{scene.UnityAssetId.Value}/{(int)AssetBundleType.MobileAndroid}/{(int)AssetBundleVersion.Unity_2020_3_33f1}"); Unity2023AndNewer? u = JsonSerializer.Deserialize(jsonString2); if (u == null) { await FollowupAsync($"Error: Failed to parse Unity Asset JSON from rec.net for subroom '{scene.Name}'."); return; } UnityAssets unityAssets = db.UnityAssets.FindOne(x => x.Id == scene.UnityAssetId.Value); if (unityAssets == null) { unityAssets = new(); } unityAssets.Id = scene.UnityAssetId.Value; UnityAsset unityAsset = new() { Filename = u.Filename, Target = u.Target, Version = u.Version }; unityAssets.Assets.Add(unityAsset); db.UnityAssets.Upsert(unityAssets); newSave.UnityAssetId = scene.UnityAssetId.Value.ToString(); } catch { } } db.SubRoomSave.Insert(newSave); newScene.CurrentSave = newSave; db.SubRooms.Update(newScene); } } } else { await FollowupAsync("Tf"); return; } if (newRoom != null) { await ws.SendToPlayer(account.Id, "RoomUpdate", await newRoom.ToDictionary(discord, db, RoomDetailsMask.StandardDetailsNoDataBlob)); } await FollowupAsync("Room reuploaded successfully!"); } catch (Exception ex) { await FollowupAsync($"Error (Exception): {ex.Message}"); } } [SlashCommand("give_role_in_room", ".")] public async Task give_role_in_room(ulong roomId, RoomRoleType role) { await DeferAsync(); if (!IsAdmin()) { await FollowupAsync("No"); return; } Account? account = db.Accounts.FindOne(x => x.DiscordId == Context.User.Id); if (account == null) { await FollowupAsync("Error: Could not find your account in the database."); return; } Room? room = db.Rooms.FindById(roomId); if (room == null) { await FollowupAsync($"room not found"); return; } room.Roles.Add(new RoomRole() { AccountId = account.Id, Role = role }); db.Rooms.Update(room); await ws.SendToPlayerSubs(account.Id, "RoomUpdate", await room.ToDictionary(discord, db, RoomDetailsMask.StandardDetailsNoDataBlob)); await FollowupAsync($"Done"); } [SlashCommand("edit_room", ".")] public async Task edit_room(ulong roomId, string rooName, RoomAccessibility accessibility, long creatorId) { await DeferAsync(); if (!IsAdmin()) { await FollowupAsync("No"); return; } Account? account = db.Accounts.FindOne(x => x.DiscordId == Context.User.Id); if (account == null) { await FollowupAsync("Error: Could not find your account in the database."); return; } Room? room = db.Rooms.FindById(roomId); if (room == null) { await FollowupAsync($"room not found"); return; } room.Name = rooName; room.Accessibility = accessibility; room.Creator = db.Accounts.FindById(creatorId); db.Rooms.Update(room); await ws.SendToPlayerSubs(account.Id, "RoomUpdate", await room.ToDictionary(discord, db, RoomDetailsMask.StandardDetailsNoDataBlob)); await FollowupAsync($"Done"); } [SlashCommand("edit_account", ".")] public async Task edit_account(ulong accountId, string Username, string DisplayName) { await DeferAsync(); if (!IsAdmin()) { await FollowupAsync("No"); return; } Account? account = db.Accounts.FindOne(x => x.DiscordId == Context.User.Id); if (account == null) { await FollowupAsync("Error: Could not find your account in the database."); return; } Account? room = db.Accounts.FindById(accountId); if (room == null) { await FollowupAsync($"account not found"); return; } room.Username = Username; room.DisplayName = DisplayName; db.Accounts.Update(room); await ws.SendToPlayerSubs(account.Id, "AccountUpdate", room.ToDictionary()); await FollowupAsync($"Done"); } [SlashCommand("shutdown", ".")] public async Task Shutdown() { await DeferAsync(); if (!IsAdmin()) { await FollowupAsync("No"); return; } await ws.SendToAllPlayer(PushNotification.ServerMaintenance, new { StartsInMinutes = 1 }); await Task.Delay(1000); lifetime.StopApplication(); await FollowupAsync($"Done"); } [SlashCommand("close_all", ".")] public async Task CloseAll() { await DeferAsync(); if (!IsAdmin()) { await FollowupAsync("No"); return; } await ws.SendToAllPlayer(PushNotification.ModerationQuitGame, new { }); await FollowupAsync($"Done"); } [SlashCommand("give_account_all_roles", ".")] public async Task GivePlayerAllRoles(long accountId) { await DeferAsync(); if (!IsAdmin()) { await FollowupAsync("No"); return; } Account account = db.Accounts.FindById(accountId); account.Roles.Add("influencer"); account.Roles.Add("developer"); account.Roles.Add("moderator"); account.Roles.Add("screenshare"); account.Roles.Add("keepsake"); account.Roles.Add("livekeepsakeeventroomsaveoverride"); account.Roles.Add("betaroomcurrencycreator"); account.Roles.Add("ps5recroomplus"); account.Roles.Add("multiinstanceevent"); db.Accounts.Update(account); await ws.SendToPlayer(account.Id, PushNotification.RefreshLogin, new Dictionary()); await FollowupAsync($"Done"); } [SlashCommand("upload_file", ".")] public async Task UploadFile(IAttachment file, FileType fileType) { } } }