Add remaining project files
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
using DeluxeBackend.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/announcement")]
|
||||
[ApiController]
|
||||
public class AnnouncementController : ControllerBase
|
||||
{
|
||||
[HttpGet("v1/get")]
|
||||
[Authorize(Roles = "gameClient")]
|
||||
public async Task<IActionResult> None()
|
||||
{
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
using DeluxeBackend.Models;
|
||||
using DeluxeBackend.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Text.Json;
|
||||
using static DeluxeBackend.Enums;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/avatar")]
|
||||
[ApiController]
|
||||
public class AvatarController : ControllerBase
|
||||
{
|
||||
private readonly IJwtService jwt;
|
||||
private readonly ILiteDbService db;
|
||||
|
||||
public AvatarController(IJwtService _jwt, ILiteDbService _db)
|
||||
{
|
||||
jwt = _jwt;
|
||||
db = _db;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpGet("v1/defaultunlocked")]
|
||||
public async Task<IActionResult> Defaultunlocked()
|
||||
{
|
||||
return Ok(ServerConfig.avatarItems);
|
||||
}
|
||||
[HttpGet("v1/defaultbaseavataritems")]
|
||||
public async Task<IActionResult> Defaultbaseavataritems()
|
||||
{
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
|
||||
[HttpGet("v4/items")]
|
||||
[Authorize(Roles = "gameClient")]
|
||||
public async Task<IActionResult> Items()
|
||||
{
|
||||
return Ok(ServerConfig.avatarItems);
|
||||
}
|
||||
|
||||
[HttpGet("v2")]
|
||||
[Authorize(Roles = "gameClient")]
|
||||
public async Task<IActionResult> MyAv()
|
||||
{
|
||||
Account? account = await jwt.GetLogin(User);
|
||||
|
||||
if (account == null)
|
||||
{
|
||||
return NotFound("User not found in database");
|
||||
}
|
||||
|
||||
AccountAvatar? accountAvatar = db.Avatar.FindOne(x => x.Account!.Id == account.Id);
|
||||
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
OutfitSelections = accountAvatar?.OutfitSelections ?? "",
|
||||
OutfitSelectionsV2 = accountAvatar?.OutfitSelectionsV2 ?? "",
|
||||
FaceFeatures = accountAvatar?.FaceFeatures ?? "",
|
||||
SkinColor = accountAvatar?.SkinColor ?? "",
|
||||
HairColor = accountAvatar?.HairColor ?? "",
|
||||
CustomAvatarItems = new List<object>()
|
||||
});
|
||||
}
|
||||
[HttpGet("v2/{accId}")]
|
||||
[Authorize(Roles = "gameClient")]
|
||||
public async Task<IActionResult> Av(long accId)
|
||||
{
|
||||
Account? account = db.Accounts.FindById(accId);
|
||||
|
||||
if (account == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
AccountAvatar? accountAvatar = db.Avatar.FindOne(x => x.Account!.Id == account.Id);
|
||||
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
OutfitSelections = accountAvatar?.OutfitSelections ?? "",
|
||||
OutfitSelectionsV2 = accountAvatar?.OutfitSelectionsV2 ?? "",
|
||||
FaceFeatures = accountAvatar?.FaceFeatures ?? "",
|
||||
SkinColor = accountAvatar?.SkinColor ?? "",
|
||||
HairColor = accountAvatar?.HairColor ?? "",
|
||||
CustomAvatarItems = new List<object>()
|
||||
});
|
||||
}
|
||||
|
||||
public class AvatarSetRequest
|
||||
{
|
||||
public required string OutfitSelections { get; set; }
|
||||
public required string OutfitSelectionsV2 { get; set; }
|
||||
public required string FaceFeatures { get; set; }
|
||||
public required string SkinColor { get; set; }
|
||||
public required string HairColor { get; set; }
|
||||
}
|
||||
[HttpPost("v2/set")]
|
||||
[Authorize(Roles = "gameClient")]
|
||||
public async Task<IActionResult> Set([FromBody] AvatarSetRequest request)
|
||||
{
|
||||
if (request == null) return BadRequest();
|
||||
|
||||
Account? account = await jwt.GetLogin(User);
|
||||
|
||||
if (account == null)
|
||||
{
|
||||
return NotFound("User not found in database");
|
||||
}
|
||||
|
||||
AccountAvatar? accountAvatar = db.Avatar.FindOne(x => x.Account!.Id == account.Id);
|
||||
if (accountAvatar == null)
|
||||
{
|
||||
accountAvatar = new AccountAvatar() { Account = account };
|
||||
}
|
||||
|
||||
accountAvatar.OutfitSelections = request.OutfitSelections;
|
||||
accountAvatar.OutfitSelectionsV2 = request.OutfitSelectionsV2;
|
||||
accountAvatar.FaceFeatures = request.FaceFeatures;
|
||||
accountAvatar.HairColor = request.HairColor;
|
||||
accountAvatar.SkinColor = request.SkinColor;
|
||||
|
||||
db.Avatar.Upsert(accountAvatar);
|
||||
return Ok(new { Success = true });
|
||||
}
|
||||
[HttpGet("v2/gifts")]
|
||||
[Authorize(Roles = "gameClient")]
|
||||
public async Task<IActionResult> Gifts()
|
||||
{
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
|
||||
private Dictionary<string, object> SavedAvToDict(AvatarSaved av)
|
||||
{
|
||||
return new Dictionary<string, object> {
|
||||
["CustomAvatarItems"] = new List<object>(),
|
||||
["FaceFeatures"] = av.FaceFeatures,
|
||||
["HairColor"] = av.HairColor,
|
||||
["Name"] = av.Name,
|
||||
["OutfitSelections"] = av.OutfitSelections,
|
||||
["OutfitSelectionsV2"] = av.OutfitSelectionsV2,
|
||||
["PreviewImageName"] = av.PreviewImageName,
|
||||
["SkinColor"] = av.SkinColor,
|
||||
["Slot"] = av.Slot
|
||||
};
|
||||
}
|
||||
|
||||
[HttpGet("v3/saved")]
|
||||
[Authorize(Roles = "gameClient")]
|
||||
public async Task<IActionResult> Saved()
|
||||
{
|
||||
Account? account = await jwt.GetLogin(User);
|
||||
|
||||
if (account == null)
|
||||
{
|
||||
return NotFound("User not found in database");
|
||||
}
|
||||
return Ok(db.AvatarSaveds.Find(x => x.Account.Id == account.Id).Select(d => SavedAvToDict(d)).ToList());
|
||||
}
|
||||
|
||||
public class AvatarSavedSetRequest
|
||||
{
|
||||
public required string OutfitSelections { get; set; }
|
||||
public required string OutfitSelectionsV2 { get; set; }
|
||||
public required string FaceFeatures { get; set; }
|
||||
public required string SkinColor { get; set; }
|
||||
public required string HairColor { get; set; }
|
||||
public string? Name { get; set; } = null;
|
||||
public int Slot { get; set; }
|
||||
public required string PreviewImageName { get; set; }
|
||||
}
|
||||
|
||||
[HttpPost("v4/saved/set")]
|
||||
[Authorize(Roles = "gameClient")]
|
||||
public async Task<IActionResult> SavedSet([FromBody] AvatarSavedSetRequest request)
|
||||
{
|
||||
Account? account = await jwt.GetLogin(User);
|
||||
|
||||
if (account == null)
|
||||
{
|
||||
return NotFound("User not found in database");
|
||||
}
|
||||
|
||||
|
||||
SavedImage? image = db.SavedImages.Include(x => x.Player).FindOne(x => x.ImageName == request.PreviewImageName);
|
||||
if (image == null) { return NotFound("image not found"); }
|
||||
if (image.SavedImageType != SavedImageType.OutfitThumbnail)
|
||||
{
|
||||
return BadRequest("image not for outfut");
|
||||
}
|
||||
|
||||
|
||||
AvatarSaved avatarSaved = new()
|
||||
{
|
||||
Account = account,
|
||||
Slot = request.Slot,
|
||||
PreviewImageName = request.PreviewImageName,
|
||||
Name = request.Name ?? "",
|
||||
OutfitSelections = request.OutfitSelections,
|
||||
OutfitSelectionsV2 = request.OutfitSelectionsV2,
|
||||
SkinColor = request.SkinColor,
|
||||
HairColor = request.HairColor,
|
||||
FaceFeatures = request.FaceFeatures,
|
||||
};
|
||||
db.AvatarSaveds.Insert(avatarSaved);
|
||||
|
||||
|
||||
return Ok(new { Success = true, Value = SavedAvToDict(avatarSaved)});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using DeluxeBackend.Models;
|
||||
using DeluxeBackend.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.HttpResults;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using static DeluxeBackend.Enums;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class CampusCardController : ControllerBase
|
||||
{
|
||||
private readonly IJwtService jwt;
|
||||
private readonly ILiteDbService db;
|
||||
private readonly INotificationService ws;
|
||||
private readonly DiscordBotService bot;
|
||||
|
||||
public CampusCardController(IJwtService _jwt, ILiteDbService _db, INotificationService _ws, DiscordBotService _bot)
|
||||
{
|
||||
jwt = _jwt;
|
||||
db = _db;
|
||||
ws = _ws;
|
||||
bot = _bot;
|
||||
}
|
||||
[HttpPost("v1/UpdateAndGetSubscription")]
|
||||
[Authorize(Roles = "gameClient")]
|
||||
public async Task<IActionResult> UpdateAndGetSubscription()
|
||||
{
|
||||
|
||||
Account? account = await jwt.GetLogin(User);
|
||||
|
||||
if (account == null)
|
||||
{
|
||||
return NotFound("User not found in database");
|
||||
}
|
||||
bool isActive = false;
|
||||
if (account.DiscordId.HasValue)
|
||||
{
|
||||
isActive = await bot.HasUserBoostedGuild(account.DiscordId.Value);
|
||||
}
|
||||
if (isActive)
|
||||
{
|
||||
return Ok(new
|
||||
{
|
||||
CanBuySubscription = false,
|
||||
PlatformAccountSubscribedPlayerId = 0,
|
||||
Subscription = new
|
||||
{
|
||||
CreatedAt = DateTime.MinValue.ToString("O"),
|
||||
ExpirationDate = DateTime.MaxValue.ToString("O"),
|
||||
IsActive = true,
|
||||
IsAutoRenewing = true,
|
||||
Level = 0,
|
||||
ModifiedAt = DateTime.MinValue.ToString("O"),
|
||||
Period = 0,
|
||||
PlatformId = "1",
|
||||
PlatformPurchaseId = "0",
|
||||
PlatformType = (int)PlatformType.RecNet,
|
||||
RecNetPlayerId = account.Id,
|
||||
SubscriptionId = 0
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
return Ok(new
|
||||
{
|
||||
CanBuySubscription = false,
|
||||
PlatformAccountSubscribedPlayerId = 0,
|
||||
Subscription = (string?)null
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/checklist")]
|
||||
[ApiController]
|
||||
public class ChecklistController : ControllerBase
|
||||
{
|
||||
[HttpGet("v1/current")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> Current()
|
||||
{
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/communityboard")]
|
||||
[ApiController]
|
||||
public class CommunityBoardController : ControllerBase
|
||||
{
|
||||
[HttpGet("v2/current")]
|
||||
[Authorize(Roles = "gameClient")]
|
||||
public async Task<IActionResult> Current()
|
||||
{
|
||||
return Ok(new
|
||||
{
|
||||
CurrentAnnouncement = new Dictionary<string, object>()
|
||||
{
|
||||
["Message"] = ":3",
|
||||
["MoreInfoUrl"] = ""
|
||||
},
|
||||
InstagramImages = new List<object>(),
|
||||
Videos = new List<object>(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
using Microsoft.AspNetCore.DataProtection.KeyManagement;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/config")]
|
||||
[ApiController]
|
||||
public class ConfigController : ControllerBase
|
||||
{
|
||||
[HttpGet("v1/amplitude")]
|
||||
public IActionResult Amplitude()
|
||||
{
|
||||
return Ok(new
|
||||
{
|
||||
AmplitudeKey = "e1693a1003671058b6abc356c8ba8d59",
|
||||
UseRudderStack = false,
|
||||
RudderStackKey = "23NiJHIgu3koaGNCZIiuYvIQNCu",
|
||||
UseStatSig = false,
|
||||
StatSigKey = "client-SBZkOrjD3r1Cat3f3W8K6sBd11WKlXZXIlCWj6l4Aje",
|
||||
StatSigEnvironment = 0
|
||||
});
|
||||
}
|
||||
[HttpGet("v1/backtrace")]
|
||||
public IActionResult Backtrace()
|
||||
{
|
||||
return Ok(new
|
||||
{
|
||||
ReportBudget = 0,
|
||||
FilterType = 0,
|
||||
SampleRate = 0.025,
|
||||
LogLineCount = 50,
|
||||
CaptureNativeCrashes = 1,
|
||||
ANRThresholdMs = 0,
|
||||
MessageCount = 1000,
|
||||
MessageRegex = "^Cannot set the parent of the GameObject .* while its new parent|^\\\\u003E\\\\x2010x\\\\:\\\\x20|\\'LabelTheme\\' contains missing PaletteTheme reference on",
|
||||
VersionRegex = ".*"
|
||||
});
|
||||
}
|
||||
|
||||
[HttpGet("v2")]
|
||||
public IActionResult GetConfig()
|
||||
{
|
||||
return Ok(new
|
||||
{
|
||||
ShareBaseUrl = "https://127.0.0.1:5000{0}",
|
||||
LevelProgressionMaps = new[]
|
||||
{
|
||||
new { Level = 1, RequiredXp = 2, GiftDropId = 1 },
|
||||
new { Level = 2, RequiredXp = 3, GiftDropId = 881 },
|
||||
new { Level = 3, RequiredXp = 4, GiftDropId = 19 },
|
||||
new { Level = 4, RequiredXp = 6, GiftDropId = 2134 },
|
||||
new { Level = 5, RequiredXp = 9, GiftDropId = 1063 },
|
||||
new { Level = 6, RequiredXp = 13, GiftDropId = 1043 },
|
||||
new { Level = 7, RequiredXp = 19, GiftDropId = 1287 },
|
||||
new { Level = 8, RequiredXp = 28, GiftDropId = 1765 },
|
||||
new { Level = 9, RequiredXp = 42, GiftDropId = 1328 },
|
||||
new { Level = 10, RequiredXp = 63, GiftDropId = 1857 },
|
||||
new { Level = 11, RequiredXp = 94, GiftDropId = 1359 },
|
||||
new { Level = 12, RequiredXp = 141, GiftDropId = 1433 },
|
||||
new { Level = 13, RequiredXp = 211, GiftDropId = 320 },
|
||||
new { Level = 14, RequiredXp = 316, GiftDropId = 1373 },
|
||||
new { Level = 15, RequiredXp = 474, GiftDropId = 1949 },
|
||||
new { Level = 16, RequiredXp = 711, GiftDropId = 961 },
|
||||
new { Level = 17, RequiredXp = 1066, GiftDropId = 934 },
|
||||
new { Level = 18, RequiredXp = 1599, GiftDropId = 633 },
|
||||
new { Level = 19, RequiredXp = 2398, GiftDropId = 1766 },
|
||||
new { Level = 20, RequiredXp = 3597, GiftDropId = 523 },
|
||||
new { Level = 21, RequiredXp = 5395, GiftDropId = 106 },
|
||||
new { Level = 22, RequiredXp = 8092, GiftDropId = 1075 },
|
||||
new { Level = 23, RequiredXp = 12138, GiftDropId = 352 },
|
||||
new { Level = 24, RequiredXp = 18207, GiftDropId = 49 },
|
||||
new { Level = 25, RequiredXp = 27310, GiftDropId = 879 },
|
||||
new { Level = 26, RequiredXp = 40965, GiftDropId = 2115 },
|
||||
new { Level = 27, RequiredXp = 61447, GiftDropId = 2167 },
|
||||
new { Level = 28, RequiredXp = 92170, GiftDropId = 2246 },
|
||||
new { Level = 29, RequiredXp = 138255, GiftDropId = 1895 },
|
||||
new { Level = 30, RequiredXp = 207382, GiftDropId = 1584 },
|
||||
new { Level = 31, RequiredXp = 311073, GiftDropId = 385 },
|
||||
new { Level = 32, RequiredXp = 466609, GiftDropId = 2308 },
|
||||
new { Level = 33, RequiredXp = 699913, GiftDropId = 1499 },
|
||||
new { Level = 34, RequiredXp = 1049869, GiftDropId = 1410 },
|
||||
new { Level = 35, RequiredXp = 1574803, GiftDropId = 373 },
|
||||
new { Level = 36, RequiredXp = 2362204, GiftDropId = 254 },
|
||||
new { Level = 37, RequiredXp = 3543306, GiftDropId = 1069 },
|
||||
new { Level = 38, RequiredXp = 5314959, GiftDropId = 993 },
|
||||
new { Level = 39, RequiredXp = 7972438, GiftDropId = 1887 },
|
||||
new { Level = 40, RequiredXp = 11958657, GiftDropId = 985 },
|
||||
new { Level = 41, RequiredXp = 17937986, GiftDropId = 2079 },
|
||||
new { Level = 42, RequiredXp = 26906980, GiftDropId = 105 },
|
||||
new { Level = 43, RequiredXp = 40360472, GiftDropId = 1363 },
|
||||
new { Level = 44, RequiredXp = 60540708, GiftDropId = 1526 },
|
||||
new { Level = 45, RequiredXp = 90811064, GiftDropId = 131 },
|
||||
new { Level = 46, RequiredXp = 136216592, GiftDropId = 1376 },
|
||||
new { Level = 47, RequiredXp = 204324896, GiftDropId = 834 },
|
||||
new { Level = 48, RequiredXp = 306487360, GiftDropId = 816 },
|
||||
new { Level = 49, RequiredXp = 459731040, GiftDropId = 138 },
|
||||
new { Level = 50, RequiredXp = 689596544, GiftDropId = 10 }
|
||||
},
|
||||
DailyObjectives = new[]
|
||||
{
|
||||
new[] { new { type = 101, score = 1, xp = 10 }, new { type = 1000, score = 1, xp = 10 }, new { type = 802, score = 2, xp = 10 } },
|
||||
new[] { new { type = 26, score = 1, xp = 10 }, new { type = 1021, score = 2, xp = 10 }, new { type = 2004, score = 1, xp = 10 } },
|
||||
new[] { new { type = 3001, score = 1, xp = 10 }, new { type = 102, score = 1, xp = 10 }, new { type = 601, score = 2, xp = 10 } },
|
||||
new[] { new { type = 14, score = 2, xp = 10 }, new { type = 1000, score = 1, xp = 10 }, new { type = 14, score = 2, xp = 10 } },
|
||||
new[] { new { type = 801, score = 1, xp = 10 }, new { type = 2001, score = 1, xp = 10 }, new { type = 21, score = 1, xp = 10 } },
|
||||
new[] { new { type = 603, score = 1, xp = 10 }, new { type = 1002, score = 1, xp = 10 }, new { type = 1041, score = 1, xp = 10 } },
|
||||
new[] { new { type = 700, score = 1, xp = 10 }, new { type = 4001, score = 1, xp = 10 }, new { type = 602, score = 2, xp = 10 } }
|
||||
},
|
||||
ServerMaintenance = new { StartsInMinutes = 0 },
|
||||
AutoMicMutingConfig = new
|
||||
{
|
||||
MicSpamVolumeThreshold = 1.125,
|
||||
MicVolumeSampleInterval = 0.25,
|
||||
MicVolumeSampleRollingWindowLength = 7,
|
||||
MicSpamSamplePercentageForWarning = 0.8,
|
||||
MicSpamSamplePercentageForWarningToEnd = 0.2,
|
||||
MicSpamSamplePercentageForForceMute = 0.8,
|
||||
MicSpamSamplePercentageForForceMuteToEnd = 0.2,
|
||||
MicSpamWarningStateVolumeMultiplier = 0.25
|
||||
},
|
||||
StorefrontConfig = new { MinPlayerLevelForGifting = 15 },
|
||||
RoomKeyConfig = new { MaxKeysPerRoom = 10 },
|
||||
RoomCurrencyConfig = new { AwardCurrencyCooldownSeconds = 10 }
|
||||
});
|
||||
}
|
||||
|
||||
[HttpGet("v1/azurespeech")]
|
||||
public IActionResult Azurespeech()
|
||||
{
|
||||
return Ok(new
|
||||
{
|
||||
Key = "dce8de5b297747d9b5bddcc7f19e8c5b",
|
||||
Region= "eastus",
|
||||
Enabled=true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/consumables")]
|
||||
[ApiController]
|
||||
public class ConsumablesController : ControllerBase
|
||||
{
|
||||
[HttpGet("v2/getUnlocked")]
|
||||
public async Task<IActionResult> Saved()
|
||||
{
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
using DeluxeBackend.Models;
|
||||
using DeluxeBackend.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Drawing;
|
||||
using System.Linq.Expressions;
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using static DeluxeBackend.Enums;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/customAvatarItems")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class CustomAvatarItemsController(
|
||||
ILiteDbService db,
|
||||
IJwtService jwt,
|
||||
DiscordBotService discord,
|
||||
ICdnService cdn,
|
||||
HttpClient httpClient) : ControllerBase
|
||||
{
|
||||
private readonly JsonSerializerOptions _jsonOptions = new() { PropertyNameCaseInsensitive = true };
|
||||
|
||||
|
||||
[HttpGet("v1/isCreationEnabled")]
|
||||
[HttpGet("v1/isRenderingEnabled")]
|
||||
public IActionResult IsCreationEnabled() => Ok(true);
|
||||
|
||||
[HttpGet("v1/minPriceForPublicItem")]
|
||||
public IActionResult MinPriceForPublicItem() => Ok(0);
|
||||
|
||||
[HttpGet("v1/isCreationAllowedForAccount")]
|
||||
public async Task<IActionResult> IsCreationAllowedForAccount()
|
||||
{
|
||||
var account = await GetAuthenticatedAccountAsync();
|
||||
if (account == null) return Unauthorized();
|
||||
|
||||
if (!account.DiscordId.HasValue)
|
||||
return Ok(new { Success = false });
|
||||
|
||||
bool hasBoosted = await discord.HasUserBoostedGuild(account.DiscordId.Value);
|
||||
return Ok(new { Success = hasBoosted });
|
||||
}
|
||||
|
||||
[HttpGet("/econ/customAvatarItems/v1/owned")]
|
||||
public async Task<IActionResult> Owned([FromQuery] int skip = 0, [FromQuery] int take = 100)
|
||||
{
|
||||
var account = await GetAuthenticatedAccountAsync();
|
||||
if (account == null) return Unauthorized();
|
||||
|
||||
const bool isCreator = true;
|
||||
Expression<Func<CustomAvatarItem, bool>> filter = x =>
|
||||
x.Creator.Id == account.Id && (isCreator || x.Accessibility == RoomAccessibility.Public);
|
||||
|
||||
return GetPagedItems(filter, skip, take);
|
||||
}
|
||||
|
||||
[HttpGet("v2/fromCreator/{accId}")]
|
||||
public async Task<IActionResult> FromCreator(long accId, [FromQuery] int skip = 0, [FromQuery] int take = 100)
|
||||
{
|
||||
var account = await GetAuthenticatedAccountAsync();
|
||||
if (account == null) return Unauthorized();
|
||||
|
||||
bool isCreator = account.Id == accId;
|
||||
Expression<Func<CustomAvatarItem, bool>> filter = x =>
|
||||
x.Creator.Id == accId && (isCreator || x.Accessibility == RoomAccessibility.Public);
|
||||
|
||||
return GetPagedItems(filter, skip, take);
|
||||
}
|
||||
|
||||
[HttpPost("v1")]
|
||||
public async Task<IActionResult> Create(
|
||||
[FromForm(Name = "thumbnailImage"), Required] IFormFile thumbnailImage,
|
||||
[FromForm(Name = "design"), Required] IFormFile designImage,
|
||||
[FromForm(Name = "metadata"), Required] string metaJson)
|
||||
{
|
||||
var account = await GetAuthenticatedAccountAsync();
|
||||
if (account == null) return Unauthorized();
|
||||
|
||||
if (!account.DiscordId.HasValue || !await discord.HasUserBoostedGuild(account.DiscordId.Value))
|
||||
return StatusCode(StatusCodes.Status403Forbidden);
|
||||
|
||||
CustomAvatarItemMetaDTO? meta;
|
||||
try
|
||||
{
|
||||
meta = JsonSerializer.Deserialize<CustomAvatarItemMetaDTO>(metaJson);
|
||||
if (meta == null) return BadRequest("Invalid metadata format.");
|
||||
}
|
||||
catch
|
||||
{
|
||||
return BadRequest("Metadata is not valid JSON.");
|
||||
}
|
||||
|
||||
using var thumbStream = thumbnailImage.OpenReadStream();
|
||||
string? thumbRemotePath = await cdn.UploadFile(thumbStream, "img");
|
||||
if (thumbRemotePath == null)
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, "Failed to upload ThumbnailImage to the CDN.");
|
||||
|
||||
using var designStream = designImage.OpenReadStream();
|
||||
string? designRemotePath = await cdn.UploadFile(designStream, "img");
|
||||
if (designRemotePath == null)
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, "Failed to upload DesignImage to the CDN.");
|
||||
|
||||
var customAvatar = new CustomAvatarItem
|
||||
{
|
||||
Creator = account,
|
||||
Name = meta.Name,
|
||||
Price = meta.Price,
|
||||
BaseAvatarItemColor = ColorTranslator.FromHtml(meta.BaseAvatarItemColor),
|
||||
ThumbnailImageFilename = thumbRemotePath,
|
||||
DesignFilename = designRemotePath,
|
||||
PreviewOrientation = meta.PreviewOrientation
|
||||
};
|
||||
|
||||
db.CustomAvatarItems.Insert(customAvatar);
|
||||
return Ok(new { Success = true, Value = customAvatar.ToDictionary() });
|
||||
}
|
||||
|
||||
[HttpPost("v1/bulk")]
|
||||
public async Task<IActionResult> Bulk([FromForm(Name = "customAvatarItemIds")] List<Guid> customAvatarItemIds)
|
||||
{
|
||||
var account = await GetAuthenticatedAccountAsync();
|
||||
if (account == null) return Unauthorized();
|
||||
|
||||
var items = db.CustomAvatarItems.Find(x => customAvatarItemIds.Contains(x.Id)).ToList();
|
||||
var foundIds = items.Select(x => x.Id).ToHashSet();
|
||||
var missingIds = customAvatarItemIds.Where(id => !foundIds.Contains(id)).ToList();
|
||||
|
||||
if (missingIds.Any())
|
||||
{
|
||||
var importAccount = GetOrCreateImportAccount();
|
||||
|
||||
foreach (var missingId in missingIds)
|
||||
{
|
||||
var fallbackItem = await FetchItemFromRecNetAsync(missingId, importAccount);
|
||||
if (fallbackItem != null)
|
||||
{
|
||||
items.Add(fallbackItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(items.Select(x => x.ToDictionary()).ToList());
|
||||
}
|
||||
|
||||
[HttpGet("v1/{customAvatarItemId}")]
|
||||
public async Task<IActionResult> Get(Guid customAvatarItemId)
|
||||
{
|
||||
var account = await GetAuthenticatedAccountAsync();
|
||||
if (account == null) return Unauthorized();
|
||||
|
||||
var customAvatarItem = db.CustomAvatarItems.FindById(customAvatarItemId);
|
||||
|
||||
if (customAvatarItem == null)
|
||||
{
|
||||
var importAccount = GetOrCreateImportAccount();
|
||||
customAvatarItem = await FetchItemFromRecNetAsync(customAvatarItemId, importAccount);
|
||||
}
|
||||
|
||||
if (customAvatarItem == null)
|
||||
return NotFound();
|
||||
|
||||
return Ok(customAvatarItem.ToDictionary());
|
||||
}
|
||||
|
||||
#region Helper Methods
|
||||
|
||||
private async Task<Account?> GetAuthenticatedAccountAsync()
|
||||
{
|
||||
var login = await jwt.GetLoginWithInfo(User);
|
||||
return login?.Account;
|
||||
}
|
||||
|
||||
private IActionResult GetPagedItems(Expression<Func<CustomAvatarItem, bool>> filter, int skip, int take)
|
||||
{
|
||||
int totalCount = db.CustomAvatarItems.Count(filter);
|
||||
var results = db.CustomAvatarItems
|
||||
.Include(x => x.Creator)
|
||||
.Find(filter)
|
||||
.Skip(skip)
|
||||
.Take(take)
|
||||
.Select(x => x.ToDictionary());
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
Results = results,
|
||||
TotalResults = totalCount
|
||||
});
|
||||
}
|
||||
|
||||
private Account GetOrCreateImportAccount()
|
||||
{
|
||||
var importAccount = db.Accounts.FindOne(x => x.Username == "Import");
|
||||
if (importAccount == null)
|
||||
{
|
||||
importAccount = new Account
|
||||
{
|
||||
Username = "Import",
|
||||
DisplayName = "Import",
|
||||
Birthday = DateOnly.MinValue,
|
||||
ImageName = "DefaultProfileImage",
|
||||
IsRecentHistoryVisible = false,
|
||||
};
|
||||
importAccount.Roles.AddRange(["developer", "keepsake", "livekeepsakeeventroomsaveoverride", "betaroomcurrencycreator", "multiinstanceevent"]);
|
||||
db.Accounts.Insert(importAccount);
|
||||
}
|
||||
return importAccount;
|
||||
}
|
||||
|
||||
private async Task<CustomAvatarItem?> FetchItemFromRecNetAsync(Guid itemId, Account importAccount)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var request = new HttpRequestMessage(HttpMethod.Get, $"https://api.rec.net/api/customAvatarItems/v1/{itemId}");
|
||||
request.Headers.Add("Authorization", $"Bearer {ServerConfig.RRToken}");
|
||||
|
||||
using var response = await httpClient.SendAsync(request);
|
||||
if (response.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
string content = await response.Content.ReadAsStringAsync();
|
||||
var recNetResult = JsonSerializer.Deserialize<CAvatarItemDto>(content, _jsonOptions);
|
||||
|
||||
if (recNetResult != null && !string.IsNullOrEmpty(recNetResult.DesignFilename))
|
||||
{
|
||||
var customAvatarItem = new CustomAvatarItem
|
||||
{
|
||||
Id = recNetResult.CustomAvatarItemId,
|
||||
Accessibility=recNetResult.Accessibility,
|
||||
Creator = importAccount,
|
||||
Name = recNetResult.Name,
|
||||
Description = recNetResult.Description,
|
||||
Price = recNetResult.Price,
|
||||
BaseAvatarItemId = recNetResult.BaseAvatarItemId,
|
||||
BaseAvatarItemColor = ColorTranslator.FromHtml(recNetResult.BaseAvatarItemColor),
|
||||
DesignFilename = recNetResult.DesignFilename,
|
||||
ThumbnailImageFilename = recNetResult.ThumbnailImageFilename,
|
||||
PreviewOrientation = recNetResult.PreviewOrientation
|
||||
};
|
||||
|
||||
db.CustomAvatarItems.Insert(customAvatarItem);
|
||||
return customAvatarItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DTOs
|
||||
|
||||
public class CustomAvatarItemMetaDTO
|
||||
{
|
||||
[Required] public required string Name { get; set; }
|
||||
[Required] public required string Description { get; set; }
|
||||
[Required] public required int Price { get; set; }
|
||||
[Required] public required long BaseAvatarItemId { get; set; }
|
||||
[Required] public required string BaseAvatarItemColor { get; set; }
|
||||
[Required] public required RoomAccessibility Accessibility { get; set; }
|
||||
[Required] public required PreviewOrientationType PreviewOrientation { get; set; }
|
||||
}
|
||||
|
||||
public class CAvatarItemDto
|
||||
{
|
||||
public Guid CustomAvatarItemId { get; set; }
|
||||
public long CreatorAccountId { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Description { get; set; } = string.Empty;
|
||||
public int Price { get; set; }
|
||||
public RoomAccessibility Accessibility { get; set; }
|
||||
public bool IsFeatured { get; set; }
|
||||
public string BaseAvatarItemColor { get; set; } = string.Empty;
|
||||
public string DesignFilename { get; set; } = string.Empty;
|
||||
public string ThumbnailImageFilename { get; set; } = string.Empty;
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime ModifiedAt { get; set; }
|
||||
public int? BaseAvatarItemId { get; set; }
|
||||
public PreviewOrientationType PreviewOrientation { get; set; } = PreviewOrientationType.Front;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/equipment")]
|
||||
[ApiController]
|
||||
public class EquipmentController : ControllerBase
|
||||
{
|
||||
[HttpGet("v2/getUnlocked")]
|
||||
public async Task<IActionResult> Saved()
|
||||
{
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using static DeluxeBackend.Enums;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/gameconfigs")]
|
||||
[ApiController]
|
||||
public class GameConfigsController : ControllerBase
|
||||
{
|
||||
private readonly List<GameConfigDto> gameConfigDtos = [];
|
||||
|
||||
public GameConfigsController()
|
||||
{
|
||||
if (gameConfigDtos.Count == 0)
|
||||
{
|
||||
var json = System.IO.File.ReadAllText(Path.Combine("data", "GameConfigs.json"));
|
||||
var gameConfigs = JsonSerializer.Deserialize<List<GameConfigDto>>(json);
|
||||
gameConfigDtos.AddRange(gameConfigs);
|
||||
}
|
||||
}
|
||||
public class GameConfigDto
|
||||
{
|
||||
public required string Key { get; set; }
|
||||
public required string Value { get; set; }
|
||||
public string? ActiveExperiments { get; set; } = null;
|
||||
}
|
||||
|
||||
[HttpGet("v1/all")]
|
||||
public async Task<IActionResult> List()
|
||||
{
|
||||
return Ok(gameConfigDtos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/gamerewards")]
|
||||
[ApiController]
|
||||
public class GameRewardsController : ControllerBase
|
||||
{
|
||||
[HttpGet("v1/pending")]
|
||||
[Authorize(Roles = "gameClient")]
|
||||
public async Task<IActionResult> Pending()
|
||||
{
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/gamesight")]//we are not going to fucking pay for gamesight
|
||||
[ApiController]
|
||||
public class GamesightController : ControllerBase
|
||||
{
|
||||
[HttpPost("event")]
|
||||
public async Task<IActionResult> Event()
|
||||
{
|
||||
return Ok(new
|
||||
{
|
||||
Success=true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
using DeluxeBackend.Models;
|
||||
using DeluxeBackend.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using static DeluxeBackend.Enums;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/images")]
|
||||
[ApiController]
|
||||
public class ImagesController(IJwtService jwt, ILiteDbService db, ICdnService cdn, DiscordBotService discord) : ControllerBase
|
||||
{
|
||||
[HttpGet("v2/named")]
|
||||
public async Task<IActionResult> Named()
|
||||
{
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
[HttpGet("v5/cheered/bulk")]
|
||||
public async Task<IActionResult> cheeredBulk()
|
||||
{
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
|
||||
[HttpGet("v5/player/{accId}")]
|
||||
public async Task<IActionResult> FromPlayer(long accId)
|
||||
{
|
||||
var images = db.SavedImages.Include(x => x.Player).Find(x => x.Player.Id == accId && x.Accessibility == SavedImageAccessibility.Public).OrderByDescending(x => x.Id).Select(image => image.ToDictionary()).ToList();
|
||||
return Ok(images);
|
||||
}
|
||||
|
||||
public class SavedImageMetaDTO
|
||||
{
|
||||
[JsonPropertyName("playerIds")]
|
||||
[Required]
|
||||
public required List<ulong> PlayerIds { get; set; }
|
||||
[JsonPropertyName("savedImageType")]
|
||||
[Required]
|
||||
public required SavedImageType SavedImageType { get; set; }
|
||||
[JsonPropertyName("roomId")]
|
||||
[Required]
|
||||
public required long RoomId { get; set; }
|
||||
[JsonPropertyName("accessibility")]
|
||||
[Required]
|
||||
public required SavedImageAccessibility Accessibility { get; set; }
|
||||
}
|
||||
|
||||
|
||||
[HttpPost("v4/uploadsaved")]
|
||||
[Authorize(Roles = "gameClient")]
|
||||
//[Consumes("image/jpeg")]
|
||||
public async Task<IActionResult> UploadSaved([FromForm(Name = "image"), Required] IFormFile Image, [FromForm(Name = "imgMeta"), Required] string metaJson)
|
||||
{
|
||||
|
||||
Account? account = await jwt.GetLogin(User);
|
||||
|
||||
if (account == null)
|
||||
{
|
||||
return NotFound("User not found in database");
|
||||
}
|
||||
|
||||
SavedImageMetaDTO? Meta;
|
||||
try
|
||||
{
|
||||
Meta = JsonSerializer.Deserialize<SavedImageMetaDTO>(metaJson);
|
||||
if (Meta == null) return BadRequest("Invalid metadata format.");
|
||||
}
|
||||
catch { return BadRequest("Metadata is not valid JSON."); }
|
||||
|
||||
using var stream = Image.OpenReadStream();
|
||||
|
||||
string? remotePath = await cdn.UploadFile(
|
||||
stream,
|
||||
"img"
|
||||
);
|
||||
|
||||
if (remotePath == null)
|
||||
{
|
||||
return StatusCode(500, "Failed to upload image to the CDN.");
|
||||
}
|
||||
|
||||
SavedImage image = new()
|
||||
{
|
||||
Player = account,
|
||||
PlayerIds = Meta.PlayerIds,
|
||||
ImageName = remotePath,
|
||||
SavedImageType = Meta.SavedImageType,
|
||||
Accessibility = Meta.Accessibility,
|
||||
RoomId = Meta.RoomId == -1 ? null : Meta.RoomId
|
||||
};
|
||||
db.SavedImages.Insert(image);
|
||||
|
||||
await discord.SendSavedImg(account, image);
|
||||
|
||||
return Ok(new { ImageName = remotePath });
|
||||
}
|
||||
|
||||
[HttpGet("v6")]
|
||||
public async Task<IActionResult> GetByName([FromQuery] string name)
|
||||
{
|
||||
SavedImage? image = db.SavedImages.Include(x => x.Player).FindOne(x => x.ImageName == name);
|
||||
if (image == null) { return NotFound(); }
|
||||
return Ok(image.ToDictionary());
|
||||
}
|
||||
[HttpGet("v4/room/{roomId}")]
|
||||
public async Task<IActionResult> GetByRoom([FromQuery] long roomId)
|
||||
{
|
||||
var images = db.SavedImages.Include(x => x.Player).Find(x => x.RoomId == roomId && x.Accessibility == SavedImageAccessibility.Public).OrderByDescending(x => x.Id).Select(image => image.ToDictionary()).ToList();
|
||||
return Ok(images);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,333 @@
|
||||
using DeluxeBackend.Controllers.Matchmaking;
|
||||
using DeluxeBackend.Models;
|
||||
using DeluxeBackend.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Net.NetworkInformation;
|
||||
using static DeluxeBackend.Controllers.Api.PlayerEventsController;
|
||||
using static DeluxeBackend.Enums;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/inventions")]
|
||||
[ApiController]
|
||||
[Authorize(Roles = "gameClient")]
|
||||
public class InventionsController(ILiteDbService db, IJwtService jwt, DiscordBotService discord) : ControllerBase
|
||||
{
|
||||
|
||||
public class NewInventionRequestDTO
|
||||
{
|
||||
public required string name { get; set; }
|
||||
|
||||
public required string description { get; set; }
|
||||
|
||||
public required string imageName { get; set; }
|
||||
|
||||
public int instantiationCost { get; set; }
|
||||
|
||||
public int lightsCost { get; set; }
|
||||
|
||||
public int chipsCost { get; set; }
|
||||
|
||||
public int cloudVariablesCost { get; set; }
|
||||
|
||||
public int aiCost { get; set; }
|
||||
|
||||
public long creationRoomId { get; set; } = -1;
|
||||
|
||||
public required string inventionDataFilename { get; set; }
|
||||
|
||||
public required List<long> referencedInventions { get; set; }
|
||||
|
||||
public RoomRoleType creatorAccountRole { get; set; }
|
||||
}
|
||||
public class AddVersionInventionRequestDTO
|
||||
{
|
||||
public long inventionId { get; set; }
|
||||
|
||||
public int instantiationCost { get; set; }
|
||||
|
||||
public int lightsCost { get; set; }
|
||||
|
||||
public int chipsCost { get; set; }
|
||||
|
||||
public int cloudVariablesCost { get; set; }
|
||||
|
||||
public int aiCost { get; set; }
|
||||
|
||||
public long creationRoomId { get; set; } = -1;
|
||||
|
||||
public string? inventionDataFilename { get; set; }
|
||||
|
||||
public List<long>? referencedInventions { get; set; }
|
||||
}
|
||||
|
||||
[Token(Token = "0x200056D")]
|
||||
public enum FDOIOPFMNJL
|
||||
{
|
||||
[Token(Token = "0x4001262")]
|
||||
Success,
|
||||
[Token(Token = "0x4001263")]
|
||||
InvalidParameters,
|
||||
[Token(Token = "0x4001264")]
|
||||
PlayerCannotUpload,
|
||||
[Token(Token = "0x4001265")]
|
||||
DuplicateName,
|
||||
[Token(Token = "0x4001266")]
|
||||
NameTooShort,
|
||||
[Token(Token = "0x4001267")]
|
||||
NameTooLong,
|
||||
[Token(Token = "0x4001268")]
|
||||
NotCreator,
|
||||
[Token(Token = "0x4001269")]
|
||||
DoesNotExist,
|
||||
[Token(Token = "0x400126A")]
|
||||
ImageDoesNotExist,
|
||||
[Token(Token = "0x400126B")]
|
||||
InventionLimitReached,
|
||||
[Token(Token = "0x400126C")]
|
||||
DescriptionTooLong,
|
||||
[Token(Token = "0x400126D")]
|
||||
InnapropriateName,
|
||||
[Token(Token = "0x400126E")]
|
||||
InnapropriateDescription,
|
||||
[Token(Token = "0x400126F")]
|
||||
CannotBeModified,
|
||||
[Token(Token = "0x4001270")]
|
||||
PlayerCannotPublish,
|
||||
[Token(Token = "0x4001271")]
|
||||
AlreadyPublished,
|
||||
[Token(Token = "0x4001272")]
|
||||
AlreadyUnpublished,
|
||||
[Token(Token = "0x4001273")]
|
||||
InventionUnderModerationReview,
|
||||
[Token(Token = "0x4001274")]
|
||||
PlayerCannotDownload,
|
||||
[Token(Token = "0x4001275")]
|
||||
PlayerAlreadyOwns,
|
||||
[Token(Token = "0x4001276")]
|
||||
DescriptionTooShort,
|
||||
[Token(Token = "0x4001277")]
|
||||
DoesNotHavePermission,
|
||||
[Token(Token = "0x4001278")]
|
||||
PermissionLevelCannotBeChanged,
|
||||
[Token(Token = "0x4001279")]
|
||||
AlreadyCheered,
|
||||
[Token(Token = "0x400127A")]
|
||||
AlreadyRemovedCheer,
|
||||
[Token(Token = "0x400127B")]
|
||||
ModeratorRestrictedPublishing,
|
||||
[Token(Token = "0x400127C")]
|
||||
PlayerCannotSell,
|
||||
[Token(Token = "0x400127D")]
|
||||
InvalidPrice,
|
||||
[Token(Token = "0x400127E")]
|
||||
PriceCannotBeChanged,
|
||||
[Token(Token = "0x400127F")]
|
||||
InvalidPermissionForPaidInvention,
|
||||
[Token(Token = "0x4001280")]
|
||||
PurchaseFailed,
|
||||
[Token(Token = "0x4001281")]
|
||||
CannotDownloadPaidInvention,
|
||||
[Token(Token = "0x4001282")]
|
||||
CannotSellUnownedLineage,
|
||||
[Token(Token = "0x4001283")]
|
||||
DoesNotAllowTrial,
|
||||
[Token(Token = "0x4001284")]
|
||||
StillOnTrialCooldown,
|
||||
[Token(Token = "0x4001285")]
|
||||
PlayerCannotTrial,
|
||||
[Token(Token = "0x4001286")]
|
||||
PaidInventionPublishingDisabled,
|
||||
[Token(Token = "0x4001287")]
|
||||
PaidInventionPurchasingDisabled,
|
||||
[Token(Token = "0x4001288")]
|
||||
OperationIsDisabled,
|
||||
[Token(Token = "0x4001289")]
|
||||
PlayerRestrictedFromP2PSelling,
|
||||
[Token(Token = "0x400128A")]
|
||||
PlayerNotRecRoomPlusMember,
|
||||
[Token(Token = "0x400128B")]
|
||||
InvalidInstantiationCost,
|
||||
[Token(Token = "0x400128C")]
|
||||
FeaturedInventionNotPublished,
|
||||
[Token(Token = "0x400128D")]
|
||||
FeaturedInventionNotActive,
|
||||
[Token(Token = "0x400128E")]
|
||||
InventionContainsBlockedFiles,
|
||||
[Token(Token = "0x400128F")]
|
||||
PlayerRestrictedFromP2PBuying
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("v2/mine")]
|
||||
public async Task<IActionResult> Mine()
|
||||
{
|
||||
LoginWithInfoResult? login = await jwt.GetLoginWithInfo(User);
|
||||
if (login == null) return Unauthorized();
|
||||
|
||||
Account account = login.Account;
|
||||
var downloadedInventions = db.Inventions
|
||||
.Include(x => x.Creator)
|
||||
.Include(x => x.Room)
|
||||
.Find(x => x.DownloadIds.Contains(account.Id))
|
||||
.Select(x => x.ToDictionary())
|
||||
.ToList();
|
||||
|
||||
return Ok(downloadedInventions);
|
||||
}
|
||||
|
||||
[HttpPost("v6/save")]
|
||||
public async Task<IActionResult> Save([FromBody] NewInventionRequestDTO request)
|
||||
{
|
||||
LoginWithInfoResult? login = await jwt.GetLoginWithInfo(User);
|
||||
if (login == null) return Unauthorized();
|
||||
|
||||
Account account = login.Account;
|
||||
|
||||
if (!account.DiscordId.HasValue)
|
||||
{
|
||||
return Ok(new { Status = (int)FDOIOPFMNJL.PlayerNotRecRoomPlusMember });
|
||||
}
|
||||
if (!await discord.HasUserBoostedGuild(account.DiscordId.Value))
|
||||
{
|
||||
return Ok(new { Status = (int)FDOIOPFMNJL.PlayerNotRecRoomPlusMember });
|
||||
}
|
||||
|
||||
Room? room = db.Rooms.FindById(request.creationRoomId);
|
||||
if (room == null) return NotFound();
|
||||
|
||||
InventionVersion inventionVersion = new()
|
||||
{
|
||||
Id = 1,
|
||||
ReplicationId = Guid.NewGuid(),
|
||||
InstantiationCost = request.instantiationCost,
|
||||
LightsCost = request.lightsCost,
|
||||
ChipsCost = request.chipsCost,
|
||||
CloudVariablesCost = request.cloudVariablesCost,
|
||||
BlobName = request.inventionDataFilename
|
||||
};
|
||||
|
||||
Invention invention = new()
|
||||
{
|
||||
ReplicationId = Guid.NewGuid(),
|
||||
Creator = account,
|
||||
Name = request.name,
|
||||
Description = request.description,
|
||||
ImageName = request.imageName,
|
||||
CurrentVersionNumber = 1,
|
||||
Accessibility = RoomAccessibility.Private,
|
||||
Room = room,
|
||||
Versions=[inventionVersion],
|
||||
DownloadIds = [account.Id]
|
||||
};
|
||||
db.Inventions.Insert(invention);
|
||||
return Ok(new { Status= (int)FDOIOPFMNJL.Success, Invention=invention.ToDictionary(), InventionVersion=inventionVersion.ToDictionary(invention.Id) });
|
||||
}
|
||||
[HttpGet("v1/versions")]
|
||||
public async Task<IActionResult> Versions([FromQuery] long inventionId)
|
||||
{
|
||||
LoginWithInfoResult? login = await jwt.GetLoginWithInfo(User);
|
||||
if (login == null) return Unauthorized();
|
||||
|
||||
Account account = login.Account;
|
||||
|
||||
Invention? invention = db.Inventions.FindById(inventionId);
|
||||
if (invention == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var versionList = invention.Versions.Select(v => v.ToDictionary(invention.Id)).ToList();
|
||||
|
||||
return Ok(versionList);
|
||||
}
|
||||
[HttpPatch("v4/addversion")]
|
||||
public async Task<IActionResult> AddVersion([FromBody] AddVersionInventionRequestDTO request)
|
||||
{
|
||||
LoginWithInfoResult? login = await jwt.GetLoginWithInfo(User);
|
||||
if (login == null) return Unauthorized();
|
||||
|
||||
Account account = login.Account;
|
||||
|
||||
Invention? invention = db.Inventions.Include(x => x.Creator).Include(x => x.Room).FindById(request.inventionId);
|
||||
|
||||
if (invention == null)
|
||||
{
|
||||
return Ok(new { Status = (int)FDOIOPFMNJL.DoesNotExist });
|
||||
}
|
||||
|
||||
if (invention.Creator.Id != account.Id)
|
||||
{
|
||||
return Ok(new { Status = (int)FDOIOPFMNJL.NotCreator });
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(request.inventionDataFilename))
|
||||
{
|
||||
return Ok(new { Status = (int)FDOIOPFMNJL.InvalidParameters });
|
||||
}
|
||||
|
||||
if (!account.DiscordId.HasValue)
|
||||
{
|
||||
return Ok(new { Status = (int)FDOIOPFMNJL.PlayerNotRecRoomPlusMember });
|
||||
}
|
||||
if (!await discord.HasUserBoostedGuild(account.DiscordId.Value))
|
||||
{
|
||||
return Ok(new { Status = (int)FDOIOPFMNJL.PlayerNotRecRoomPlusMember });
|
||||
}
|
||||
|
||||
int nextVersionNumber = invention.CurrentVersionNumber + 1;
|
||||
|
||||
InventionVersion inventionVersion = new()
|
||||
{
|
||||
Id = nextVersionNumber,
|
||||
ReplicationId = Guid.NewGuid(),
|
||||
InstantiationCost = request.instantiationCost,
|
||||
LightsCost = request.lightsCost,
|
||||
ChipsCost = request.chipsCost,
|
||||
CloudVariablesCost = request.cloudVariablesCost,
|
||||
BlobName = request.inventionDataFilename
|
||||
};
|
||||
|
||||
invention.Versions.Add(inventionVersion);
|
||||
invention.CurrentVersionNumber = nextVersionNumber;
|
||||
invention.ModifiedAt = DateTime.UtcNow;
|
||||
|
||||
db.Inventions.Update(invention);
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
Status = (int)FDOIOPFMNJL.Success,
|
||||
Invention = invention.ToDictionary(),
|
||||
InventionVersion = inventionVersion.ToDictionary(invention.Id)
|
||||
});
|
||||
}
|
||||
|
||||
[HttpGet("v2/batch")]
|
||||
[HttpPost("v2/batch")]
|
||||
public async Task<IActionResult> Versions([FromQuery(Name = "id")] List<long>? queryIds,[FromForm(Name = "id")] List<long>? formIds)
|
||||
{
|
||||
List<long> id = (queryIds != null && queryIds.Count > 0)
|
||||
? queryIds
|
||||
: (formIds ?? new List<long>());
|
||||
|
||||
LoginWithInfoResult? login = await jwt.GetLoginWithInfo(User);
|
||||
if (login == null) return Unauthorized();
|
||||
|
||||
Account account = login.Account;
|
||||
|
||||
if (id.Count == 0)
|
||||
{
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
|
||||
var inventionsBatch = db.Inventions
|
||||
.Find(x => id.Contains(x.Id))
|
||||
.Select(x => x.ToDictionary())
|
||||
.ToList();
|
||||
|
||||
return Ok(inventionsBatch);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
using DeluxeBackend.Models;
|
||||
using DeluxeBackend.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Numerics;
|
||||
using System.Security.Claims;
|
||||
using static DeluxeBackend.Enums;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/messages")]
|
||||
[ApiController]
|
||||
public class MessagesController : ControllerBase
|
||||
{
|
||||
private readonly ILiteDbService db;
|
||||
private readonly IJwtService jwt;
|
||||
private readonly INotificationService ws;
|
||||
private readonly IMessageService messageService;
|
||||
|
||||
public List<MessageType> allowedMsgs =
|
||||
[
|
||||
MessageType.TextMessage,
|
||||
MessageType.GameInvite,
|
||||
MessageType.GameInviteDeclined,
|
||||
MessageType.GameJoinFailed,
|
||||
MessageType.FriendStatusOnline,
|
||||
MessageType.RequestGameInvite,
|
||||
MessageType.RequestGameInviteDeclined,
|
||||
MessageType.PartyUpRequest
|
||||
];
|
||||
|
||||
public MessagesController(ILiteDbService _db, IJwtService _jwt, INotificationService _ws, IMessageService _messageService)
|
||||
{
|
||||
db = _db;
|
||||
jwt = _jwt;
|
||||
ws = _ws;
|
||||
messageService = _messageService;
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpGet("v2/get")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> get()
|
||||
{
|
||||
string? playerId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? User.FindFirst("sub")?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(playerId))
|
||||
{
|
||||
return Unauthorized();
|
||||
}
|
||||
|
||||
Account player = db.Accounts.FindById((long)Convert.ToDouble(playerId));
|
||||
if (player == null)
|
||||
{
|
||||
return Unauthorized();
|
||||
}
|
||||
|
||||
var msgs = db.Messages
|
||||
.Query()
|
||||
.Include(x => x.Player)
|
||||
.Include(x => x.FromPlayer)
|
||||
.Where(x => x.Player.Id == player.Id)
|
||||
.OrderByDescending(x => x.Id)
|
||||
.ToList()
|
||||
.Select(r => r.ToDictionary())
|
||||
.ToList();
|
||||
|
||||
return Ok(msgs);
|
||||
}
|
||||
|
||||
[HttpPost("v2/delete")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> delete([FromForm(Name = "Id"), Required] long msgId)
|
||||
{
|
||||
string? rawPlayerId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value
|
||||
?? User.FindFirst("sub")?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(rawPlayerId))
|
||||
return Unauthorized();
|
||||
|
||||
if (!long.TryParse(rawPlayerId, out long playerId))
|
||||
return Unauthorized();
|
||||
|
||||
Account? player = db.Accounts.FindById(playerId);
|
||||
if (player == null)
|
||||
return Unauthorized();
|
||||
|
||||
|
||||
Message? message = db.Messages.Include(x => x.Player).FindById(msgId);
|
||||
if (message == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (message.Player.Id != player.Id)
|
||||
{
|
||||
return StatusCode(403);
|
||||
}
|
||||
|
||||
db.Messages.Delete(msgId);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
public class V3DeleteRequestDto
|
||||
{
|
||||
public required List<long> MessageIds { get; set; }
|
||||
}
|
||||
|
||||
[HttpPost("v3/delete")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> V3Delete([FromBody] V3DeleteRequestDto request)
|
||||
{
|
||||
string? rawPlayerId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value
|
||||
?? User.FindFirst("sub")?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(rawPlayerId))
|
||||
return Unauthorized();
|
||||
|
||||
if (!long.TryParse(rawPlayerId, out long playerId))
|
||||
return Unauthorized();
|
||||
|
||||
Account? player = db.Accounts.FindById(playerId);
|
||||
if (player == null)
|
||||
return Unauthorized();
|
||||
|
||||
if (request.MessageIds == null || request.MessageIds.Count == 0)
|
||||
return BadRequest("No message IDs provided.");
|
||||
|
||||
foreach (ulong messageId in request.MessageIds)
|
||||
{
|
||||
Message? message = db.Messages
|
||||
.Include(x => x.Player)
|
||||
.FindById((long)messageId);
|
||||
|
||||
if (message == null)
|
||||
continue;
|
||||
|
||||
if (message.Player.Id != player.Id)
|
||||
continue;
|
||||
|
||||
db.Messages.Delete(messageId);
|
||||
}
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpPost("v2/send")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> send([FromForm(Name = "ToPlayerId"), Required] long toPlayerId, [FromForm(Name = "Type"), Required] MessageType type, [FromForm(Name = "Data")] string data = "", [FromForm(Name = "RoomId")] long? roomId = null)
|
||||
{
|
||||
string? rawPlayerId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value
|
||||
?? User.FindFirst("sub")?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(rawPlayerId))
|
||||
return Unauthorized();
|
||||
|
||||
if (!long.TryParse(rawPlayerId, out long playerId))
|
||||
return Unauthorized();
|
||||
|
||||
Account? player = db.Accounts.FindById(playerId);
|
||||
if (player == null)
|
||||
return Unauthorized();
|
||||
Account? player2 = db.Accounts.FindById(toPlayerId);
|
||||
if (player2 == null)
|
||||
return NotFound();
|
||||
|
||||
|
||||
if (!allowedMsgs.Contains(type) && false)
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
await messageService.SendMessage(player, player2, type, data);
|
||||
|
||||
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/objectives")]
|
||||
[ApiController]
|
||||
public class ObjectivesController : ControllerBase
|
||||
{
|
||||
[HttpGet("v1/myprogress")]
|
||||
public async Task<IActionResult> MyProgress()
|
||||
{
|
||||
return Ok(new { Objectives = new List<object>(), ObjectiveGroups= new List<object>() });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
using DeluxeBackend.Controllers.Matchmaking;
|
||||
using DeluxeBackend.Models;
|
||||
using DeluxeBackend.Services;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using static DeluxeBackend.Controllers.Api.AvatarController;
|
||||
using static DeluxeBackend.Controllers.RoomsController;
|
||||
using static DeluxeBackend.Enums;
|
||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/playerevents")]
|
||||
[ApiController]
|
||||
public class PlayerEventsController(IJwtService jwt, ILiteDbService db, ICdnService cdn, INotificationService ws, DiscordBotService discord) : ControllerBase
|
||||
{
|
||||
[HttpGet("v1/all")]
|
||||
public async Task<IActionResult> All()
|
||||
{
|
||||
return Ok(new { Created = new List<object>(), Responses = new List<object>() });
|
||||
}
|
||||
|
||||
[Token(Token = "0x2000F45")]
|
||||
public enum DNPDKMHJGAO
|
||||
{
|
||||
[Token(Token = "0x4003C04")]
|
||||
Success,
|
||||
[Token(Token = "0x4003C05")]
|
||||
HasModeratorClosedEvent,
|
||||
[Token(Token = "0x4003C06")]
|
||||
DoesNotExist,
|
||||
[Token(Token = "0x4003C07")]
|
||||
PlayerDoesNotExist,
|
||||
[Token(Token = "0x4003C08")]
|
||||
RoomDoesNotExist,
|
||||
[Token(Token = "0x4003C09")]
|
||||
StatusUnchanged,
|
||||
[Token(Token = "0x4003C0A")]
|
||||
PrivateEvent,
|
||||
[Token(Token = "0x4003C0B")]
|
||||
SomethingWentWrong,
|
||||
[Token(Token = "0x4003C0C")]
|
||||
DoesNotOwnRoom,
|
||||
[Token(Token = "0x4003C0D")]
|
||||
ResponseDoesNotExist,
|
||||
[Token(Token = "0x4003C0E")]
|
||||
PlayerAlreadyInvited,
|
||||
[Token(Token = "0x4003C0F")]
|
||||
EventDatesInvalid,
|
||||
[Token(Token = "0x4003C10")]
|
||||
EventTooLong,
|
||||
[Token(Token = "0x4003C11")]
|
||||
EventTooShort,
|
||||
[Token(Token = "0x4003C12")]
|
||||
InappropriateName,
|
||||
[Token(Token = "0x4003C13")]
|
||||
InappropriateDescription,
|
||||
[Token(Token = "0x4003C14")]
|
||||
SomeInvitesFailed,
|
||||
[Token(Token = "0x4003C15")]
|
||||
CannotInviteJunior,
|
||||
[Token(Token = "0x4003C16")]
|
||||
EventCountLimitReached,
|
||||
[Token(Token = "0x4003C17")]
|
||||
DoesNotOwnEvent,
|
||||
[Token(Token = "0x4003C18")]
|
||||
UnregisteredOrJuniorNotAllowed,
|
||||
[Token(Token = "0x4003C19")]
|
||||
InvalidClubPermissions,
|
||||
[Token(Token = "0x4003C1A")]
|
||||
ImageDoesNotExist,
|
||||
[Token(Token = "0x4003C1B")]
|
||||
SubRoomDoesNotExist,
|
||||
[Token(Token = "0x4003C1C")]
|
||||
DoesNotOwnSubRoom,
|
||||
[Token(Token = "0x4003C1D")]
|
||||
ModifyTagsFailed,
|
||||
[Token(Token = "0x4003C1E")]
|
||||
RoomCapacityTooLow,
|
||||
[Token(Token = "0x4003C1F")]
|
||||
BroadcastEventNotMultiInstance,
|
||||
[Token(Token = "0x4003C20")]
|
||||
PlayerNotAllowedToCreateMultiInstanceEvents,
|
||||
[Token(Token = "0x4003C21")]
|
||||
PlayerBannedFromEventCreation,
|
||||
[Token(Token = "0x4003C22")]
|
||||
EventIsModerationClosed,
|
||||
[Token(Token = "0x4003C23")]
|
||||
EventIsModerationPendingReview
|
||||
}
|
||||
|
||||
[HttpGet("v1/tagfilters")]
|
||||
public async Task<IActionResult> Tagfilters()
|
||||
{
|
||||
return Ok(new
|
||||
{
|
||||
PinnedFilters = new[]
|
||||
{
|
||||
"workshops",
|
||||
"celebration",
|
||||
"game",
|
||||
"meetup",
|
||||
"performance",
|
||||
"coop",
|
||||
"grandopening",
|
||||
"class",
|
||||
"competition"
|
||||
},
|
||||
PopularFilters = new[]
|
||||
{
|
||||
"workshops",
|
||||
"celebration",
|
||||
"class",
|
||||
"coop",
|
||||
"competition",
|
||||
"game",
|
||||
"grandopening",
|
||||
"meetup",
|
||||
"performance"
|
||||
},
|
||||
TrendingFilters = (string[]?)null
|
||||
});
|
||||
}
|
||||
|
||||
public class CreateEventRequest
|
||||
{
|
||||
public RoomAccessibility Accessibility { get; set; }
|
||||
public BroadcastPerms CanRequestBroadcastPermissions { get; set; } = BroadcastPerms.None;
|
||||
public int? ClubId { get; set; }
|
||||
public BroadcastPerms DefaultBroadcastPermissions { get; set; } = BroadcastPerms.None;
|
||||
public string Description { get; set; } = string.Empty;
|
||||
public DateTime EndTime { get; set; }
|
||||
public string? ImageName { get; set; }
|
||||
public bool IsMultiInstance { get; set; } = false;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public int RoomId { get; set; }
|
||||
public DateTime StartTime { get; set; }
|
||||
public int? SubRoomId { get; set; }
|
||||
public bool SupportMultiInstanceRoomChat { get; set; } = false;
|
||||
public List<string> Tags { get; set; } = new();
|
||||
}
|
||||
|
||||
[HttpPost("v2")]
|
||||
public async Task<IActionResult> V2([FromBody] CreateEventRequest request)
|
||||
{
|
||||
LoginWithInfoResult? login = await jwt.GetLoginWithInfo(User);
|
||||
|
||||
if (login == null) return Unauthorized();
|
||||
Account account = login.Account;
|
||||
/*if (request.IsMultiInstance && !account.HasRoleAsync(discord, "").Result)
|
||||
{
|
||||
//return Ok(new { Result = DNPDKMHJGAO.PlayerNotAllowedToCreateMultiInstanceEvents });
|
||||
request.IsMultiInstance = false;
|
||||
}*/
|
||||
|
||||
Room? room = db.Rooms.Include(x => x.Creator).FindOne(x => x.Id == request.RoomId);
|
||||
if (room == null)
|
||||
{
|
||||
return Ok(new { Result = DNPDKMHJGAO.RoomDoesNotExist });
|
||||
}
|
||||
|
||||
if (room.Accessibility == RoomAccessibility.Private)
|
||||
{
|
||||
if (!room.HasRole(account.Id, RoomRoleType.CoOwner))
|
||||
{
|
||||
return Ok(new { Result = DNPDKMHJGAO.DoesNotOwnRoom });
|
||||
}
|
||||
}
|
||||
|
||||
List<SubRoom> subRooms = db.SubRooms.Include(x => x.Room).Find(x => x.Room.Id == room.Id && x.CanMatchmakeInto).ToList();
|
||||
if (subRooms.Count == 0)
|
||||
{
|
||||
return Ok(new { Result = DNPDKMHJGAO.SubRoomDoesNotExist });
|
||||
}
|
||||
|
||||
SubRoom subRoom = subRooms[Random.Shared.Next(subRooms.Count)];
|
||||
|
||||
|
||||
PlayerEvent playerEvent = new()
|
||||
{
|
||||
Creator = account,
|
||||
Room = room,
|
||||
SubRoom = subRoom,
|
||||
Name = request.Name,
|
||||
Description=request.Description,
|
||||
ImageName=request.ImageName ?? "",
|
||||
StartTime=request.StartTime,
|
||||
EndTime=request.EndTime,
|
||||
Accessibility=request.Accessibility,
|
||||
IsMultiInstance=request.IsMultiInstance,
|
||||
SupportMultiInstanceRoomChat=request.SupportMultiInstanceRoomChat,
|
||||
DefaultBroadcastPermissions=request.DefaultBroadcastPermissions,
|
||||
CanRequestBroadcastPermissions=request.CanRequestBroadcastPermissions
|
||||
};
|
||||
db.PlayerEvents.Insert(playerEvent);
|
||||
/*AccountPresence presence = GetOrCreatePresence(account);
|
||||
RoomInstance roomInstance = CreateNewInstance(subRoom, Enums.RoomInstanceType.MultiInstanceEvent, true, playerEvent.Id);
|
||||
playerEvent.BroadcastingRoomInstanceId = roomInstance.Id;
|
||||
db.PlayerEvents.Update(playerEvent);
|
||||
presence.Instance = roomInstance;
|
||||
await SaveAndNotifyPresenceAsync(presence);*/
|
||||
|
||||
return Ok(new { Result = DNPDKMHJGAO.Success, PlayerEvent=playerEvent.ToDictionary()});
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("v1/{eventId}")]
|
||||
public async Task<IActionResult> GetEvent(long eventId)
|
||||
{
|
||||
PlayerEvent? playerEvent = db.PlayerEvents.Include(x => x.Room).Include(x => x.SubRoom).Include(x => x.Creator).FindById(eventId);
|
||||
if (playerEvent == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return Ok(playerEvent.ToDictionary());
|
||||
}
|
||||
[HttpGet("v1/{eventId}/responses")]
|
||||
public async Task<IActionResult> GetEventResponses(long eventId)
|
||||
{
|
||||
PlayerEvent? playerEvent = db.PlayerEvents.Include(x => x.Room).Include(x => x.SubRoom).Include(x => x.Creator).FindById(eventId);
|
||||
if (playerEvent == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
|
||||
public class BroadcastRequest
|
||||
{
|
||||
public required long PlayerEventId { get; set; }
|
||||
public required long BroadcastRoomInstanceId { get; set; }
|
||||
}
|
||||
|
||||
[HttpPost("v1/broadcast")]
|
||||
public async Task<IActionResult> Broadcast([FromBody] BroadcastRequest request)
|
||||
{
|
||||
PlayerEvent? playerEvent = db.PlayerEvents.Include(x => x.Room).Include(x => x.SubRoom).Include(x => x.Creator).FindById(request.PlayerEventId);
|
||||
if (playerEvent == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
RoomInstance? instance = db.RoomInstances.Include(x => x.SubRoom).FindById(request.BroadcastRoomInstanceId);
|
||||
if (instance == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
playerEvent.BroadcastingRoomInstanceId = request.BroadcastRoomInstanceId;
|
||||
db.PlayerEvents.Update(playerEvent);
|
||||
/*instance.InstanceType = RoomInstanceType.MultiInstanceEvent;
|
||||
instance.Private = true;
|
||||
db.RoomInstances.Update(instance);
|
||||
await ws.SendToAllPlayer("RoomInstanceUpdate", instance.ToDictionary());*/
|
||||
|
||||
return Ok(new { Result = DNPDKMHJGAO.Success, PlayerEvent = playerEvent.ToDictionary() });
|
||||
}
|
||||
|
||||
private AccountPresence GetOrCreatePresence(Account account)
|
||||
{
|
||||
var presence = db.Presences
|
||||
.Include(x => x.Account)
|
||||
.Include(x => x.Instance)
|
||||
.Include(x => x.Instance!.SubRoom)
|
||||
.Include(x => x.Instance!.SubRoom!.Room)
|
||||
.Include(x => x.Instance!.SubRoom!.Room!.Creator)
|
||||
.FindOne(x => x.Account.Id == account.Id);
|
||||
|
||||
return presence ?? new AccountPresence { Account = account };
|
||||
}
|
||||
|
||||
private async Task SaveAndNotifyPresenceAsync(AccountPresence presence)
|
||||
{
|
||||
presence.LastOnline = DateTime.UtcNow;
|
||||
presence.IsOnline = true;
|
||||
db.Presences.Upsert(presence);
|
||||
await ws.SendToAllPlayer("PresenceUpdate", presence.ToDictionary());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
using DeluxeBackend.Models;
|
||||
using DeluxeBackend.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class PlayerReportingController(DiscordBotService discord, IJwtService jwt, INotificationService ws) : ControllerBase
|
||||
{
|
||||
[HttpGet("v1/moderationBlockDetails")]
|
||||
[HttpPost("v1/moderationBlockDetails")]
|
||||
public async Task<IActionResult> ModerationBlockDetails()
|
||||
{
|
||||
return Ok(new { ReportCategory =0, Duration =0, GameSessionId = 0, Message = "" });
|
||||
}
|
||||
|
||||
[Token(Token = "0x2000C9B")]
|
||||
public enum PGGOOHJPFPC
|
||||
{
|
||||
[Token(Token = "0x400315A")]
|
||||
Obscured,
|
||||
[Token(Token = "0x400315B")]
|
||||
Time,
|
||||
[Token(Token = "0x400315C")]
|
||||
Inject,
|
||||
[Token(Token = "0x400315D")]
|
||||
GiftCount,
|
||||
[Token(Token = "0x400315E")]
|
||||
Engine,
|
||||
[Token(Token = "0x400315F")]
|
||||
UnknownDll,
|
||||
[Token(Token = "0x4003160")]
|
||||
ImageSignature,
|
||||
[Token(Token = "0x4003161")]
|
||||
AvatarHack,
|
||||
[Token(Token = "0x4003162")]
|
||||
NetworkCertificatePublicKey = 100,
|
||||
[Token(Token = "0x4003163")]
|
||||
NetworkCertificateIssuer,
|
||||
[Token(Token = "0x4003164")]
|
||||
NetworkCertificateMissing,
|
||||
[Token(Token = "0x4003165")]
|
||||
NetworkCertificateMismatch,
|
||||
[Token(Token = "0x4003166")]
|
||||
AutosaveChecksumMismatch = 150,
|
||||
[Token(Token = "0x4003167")]
|
||||
AutosaveSubRoomIdMismatch,
|
||||
[Token(Token = "0x4003168")]
|
||||
AutosaveChecksumException,
|
||||
[Token(Token = "0x4003169")]
|
||||
Photon_MissingHash = 200,
|
||||
[Token(Token = "0x400316A")]
|
||||
Photon_CorruptHash,
|
||||
[Token(Token = "0x400316B")]
|
||||
Photon_DifferentHash = 203,
|
||||
[Token(Token = "0x400316C")]
|
||||
AppData_Runtime_LengthMismatch = 300,
|
||||
[Token(Token = "0x400316D")]
|
||||
AppData_Runtime_LastWriteTimeMismatch,
|
||||
[Token(Token = "0x400316E")]
|
||||
AppData_Runtime_FileModified,
|
||||
[Token(Token = "0x400316F")]
|
||||
AppData_Boot_InvalidSignature = 310,
|
||||
[Token(Token = "0x4003170")]
|
||||
AppData_Boot_UnableToVerifySignatures,
|
||||
[Token(Token = "0x4003171")]
|
||||
Config_MissingHash = 320,
|
||||
[Token(Token = "0x4003172")]
|
||||
Config_DifferentHash,
|
||||
[Token(Token = "0x4003173")]
|
||||
Photon_InstantiateTool = 400,
|
||||
[Token(Token = "0x4003174")]
|
||||
Memory_Hash_Mismatch = 500,
|
||||
[Token(Token = "0x4003175")]
|
||||
Driver_Invalid_Signature = 600,
|
||||
[Token(Token = "0x4003176")]
|
||||
Native_Memory_Hash_Mismatch = 700
|
||||
}
|
||||
|
||||
[HttpPost("v1/hile")]
|
||||
[Authorize(Roles = "gameClient")]
|
||||
public async Task<IActionResult> Hile([FromForm(Name = "Type")] PGGOOHJPFPC hileType, [FromForm(Name = "Message")] string message)
|
||||
{
|
||||
Account? account = await jwt.GetLogin(User);
|
||||
|
||||
if (hileType == PGGOOHJPFPC.UnknownDll)
|
||||
{
|
||||
return Ok(false);
|
||||
}
|
||||
if (message.Contains("main.2208069.com.AgainstGravity.RecRoom.obb"))
|
||||
{
|
||||
return Ok(false);
|
||||
}
|
||||
await discord.SendSelfReport(account, hileType, message);
|
||||
|
||||
//await ws.SendToPlayer(account.Id, PushNotification.ModerationQuitGame, new Dictionary<string, object>());
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
[HttpGet("v1/voteToKickReasons")]
|
||||
public async Task<IActionResult> VoteToKickReasons()
|
||||
{
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using static DeluxeBackend.Controllers.Api.AvatarController;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/playerReputation")]
|
||||
[ApiController]
|
||||
public class PlayerReputationController : ControllerBase
|
||||
{
|
||||
[HttpGet("v2/bulk")]
|
||||
public async Task<IActionResult> bulk([FromQuery(Name = "id")] List<long> accountIds)
|
||||
{
|
||||
List<Dictionary<string, object>> reputations = new List<Dictionary<string, object>>();
|
||||
foreach (long item in accountIds)
|
||||
{
|
||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
reputations.Add(new Dictionary<string, object>
|
||||
{
|
||||
["AccountId"] = item,
|
||||
["IsCheerful"] = true,
|
||||
["Noteriety"] = 0.0,
|
||||
["CheerCredit"] = 99,
|
||||
["CheerGeneral"] = 0,
|
||||
["CheerHelpful"] = 0,
|
||||
["CheerCreative"] = 0,
|
||||
["CheerGreatHost"] = 0,
|
||||
["CheerSportsman"] = 0
|
||||
});
|
||||
#pragma warning restore CS8625
|
||||
}
|
||||
|
||||
return Ok(reputations);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using static DeluxeBackend.Controllers.Api.AvatarController;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/players")]
|
||||
[ApiController]
|
||||
public class PlayersController : ControllerBase
|
||||
{
|
||||
[HttpGet("v2/progression/bulk")]
|
||||
public async Task<IActionResult> ProgressionBulk([FromQuery(Name = "id")] List<long> accountIds)
|
||||
{
|
||||
List<Dictionary<string, object>> reputations = [];
|
||||
foreach (long item in accountIds)
|
||||
{
|
||||
reputations.Add(new Dictionary<string, object>
|
||||
{
|
||||
["PlayerId"] = item,
|
||||
["Level"] = 1,
|
||||
["XP"] = 0
|
||||
});
|
||||
}
|
||||
return Ok(reputations);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/progressionEvents")]
|
||||
[ApiController]
|
||||
public class ProgressionEventsController : ControllerBase
|
||||
{
|
||||
[HttpGet("active")]
|
||||
public async Task<IActionResult> Active()
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
[HttpGet("event/{eventId}")]
|
||||
public async Task<IActionResult> Event(long eventId)
|
||||
{
|
||||
return NotFound();
|
||||
/*
|
||||
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
|
||||
return Ok(new
|
||||
{
|
||||
ProgressionEventId = 2,
|
||||
Name = "Coming in Hot! Progression Event Alpha",
|
||||
IsEnabled = true,
|
||||
Rewards = new[]
|
||||
{
|
||||
new {
|
||||
ProgressionEventRewardId = 1,
|
||||
ProgressionEventId = 2,
|
||||
GiftDropId = 3798,
|
||||
ImageName = "7w7xumgr5rtaouze5e5lwspea.png",
|
||||
ImageStream = (object)null,
|
||||
ImageContentType = (object)null,
|
||||
Xp = 30,
|
||||
RewardIndex = 0,
|
||||
IsBonus = false,
|
||||
IsRRPlusExclusive = false
|
||||
},
|
||||
new {
|
||||
ProgressionEventRewardId = 2,
|
||||
ProgressionEventId = 2,
|
||||
GiftDropId = 3779,
|
||||
ImageName = "eynegc0nils797wgjqz96a2ds.png",
|
||||
ImageStream = (object)null,
|
||||
ImageContentType = (object)null,
|
||||
Xp = 60,
|
||||
RewardIndex = 1,
|
||||
IsBonus = false,
|
||||
IsRRPlusExclusive = false
|
||||
},
|
||||
new {
|
||||
ProgressionEventRewardId = 3,
|
||||
ProgressionEventId = 2,
|
||||
GiftDropId = 3025,
|
||||
ImageName = "2ikt2bx6xwiyyr6s8qducxjr1.png",
|
||||
ImageStream = (object)null,
|
||||
ImageContentType = (object)null,
|
||||
Xp = 90,
|
||||
RewardIndex = 2,
|
||||
IsBonus = false,
|
||||
IsRRPlusExclusive = false
|
||||
},
|
||||
new {
|
||||
ProgressionEventRewardId = 4,
|
||||
ProgressionEventId = 2,
|
||||
GiftDropId = 4079,
|
||||
ImageName = "dziv7z4fwbejheoy7yvrjlby1.png",
|
||||
ImageStream = (object)null,
|
||||
ImageContentType = (object)null,
|
||||
Xp = 130,
|
||||
RewardIndex = 3,
|
||||
IsBonus = false,
|
||||
IsRRPlusExclusive = false
|
||||
},
|
||||
new {
|
||||
ProgressionEventRewardId = 6,
|
||||
ProgressionEventId = 2,
|
||||
GiftDropId = 4078,
|
||||
ImageName = "6fepaaug17ai3guqpazy3v86o.png",
|
||||
ImageStream = (object)null,
|
||||
ImageContentType = (object)null,
|
||||
Xp = 180,
|
||||
RewardIndex = 4,
|
||||
IsBonus = false,
|
||||
IsRRPlusExclusive = false
|
||||
},
|
||||
new {
|
||||
ProgressionEventRewardId = 7,
|
||||
ProgressionEventId = 2,
|
||||
GiftDropId = 3974,
|
||||
ImageName = "7958ooqtj2o04rkcdqtyb3rko.png",
|
||||
ImageStream = (object)null,
|
||||
ImageContentType = (object)null,
|
||||
Xp = 250,
|
||||
RewardIndex = 5,
|
||||
IsBonus = false,
|
||||
IsRRPlusExclusive = false
|
||||
}
|
||||
},
|
||||
KeepsakeRoomLists = new[]
|
||||
{
|
||||
new {
|
||||
KeepsakeRoomListId = 1,
|
||||
ProgressionEventId = 3,
|
||||
UnlockItemAvatarItemId = (object)null,
|
||||
UnlockItemGiftDropId = (object)null,
|
||||
UnlockItemLockDurationTicks = (object)null,
|
||||
KeepsakeRooms = new[] {
|
||||
new { KeepsakeRoomId = 1, RoomId = 1, KeepsakeRoomListId = 1, Type = 0, Order = 7 },
|
||||
new { KeepsakeRoomId = 2, RoomId = 2, KeepsakeRoomListId = 1, Type = 0, Order = 8 },
|
||||
new { KeepsakeRoomId = 3, RoomId = 3, KeepsakeRoomListId = 1, Type = 0, Order = 9 },
|
||||
new { KeepsakeRoomId = 4, RoomId = 4, KeepsakeRoomListId = 1, Type = 0, Order = 10 },
|
||||
new { KeepsakeRoomId = 5, RoomId = 5, KeepsakeRoomListId = 1, Type = 0, Order = 11 },
|
||||
new { KeepsakeRoomId = 6, RoomId = 6, KeepsakeRoomListId = 1, Type = 0, Order = 12 },
|
||||
new { KeepsakeRoomId = 7, RoomId = 7, KeepsakeRoomListId = 1, Type = 0, Order = 13 },
|
||||
new { KeepsakeRoomId = 8, RoomId = 8, KeepsakeRoomListId = 1, Type = 0, Order = 14 },
|
||||
new { KeepsakeRoomId = 11, RoomId = 9, KeepsakeRoomListId = 1, Type = 0, Order = 15 },
|
||||
new { KeepsakeRoomId = 12, RoomId = 10, KeepsakeRoomListId = 1, Type = 0, Order = 16 },
|
||||
new { KeepsakeRoomId = 13, RoomId = 11, KeepsakeRoomListId = 1, Type = 0, Order = 17 },
|
||||
new { KeepsakeRoomId = 14, RoomId = 12, KeepsakeRoomListId = 1, Type = 0, Order = 18 },
|
||||
new { KeepsakeRoomId = 15, RoomId = 13, KeepsakeRoomListId = 1, Type = 0, Order = 19 },
|
||||
new { KeepsakeRoomId = 22, RoomId = 14, KeepsakeRoomListId = 1, Type = 0, Order = 6 },
|
||||
new { KeepsakeRoomId = 23, RoomId = 15, KeepsakeRoomListId = 1, Type = 0, Order = 5 },
|
||||
new { KeepsakeRoomId = 24, RoomId = 16, KeepsakeRoomListId = 1, Type = 0, Order = 4 },
|
||||
new { KeepsakeRoomId = 25, RoomId = 17, KeepsakeRoomListId = 1, Type = 0, Order = 3 },
|
||||
new { KeepsakeRoomId = 26, RoomId = 18, KeepsakeRoomListId = 1, Type = 0, Order = 2 },
|
||||
new { KeepsakeRoomId = 27, RoomId = 29, KeepsakeRoomListId = 1, Type = 0, Order = 1 },
|
||||
new { KeepsakeRoomId = 28, RoomId = 20, KeepsakeRoomListId = 1, Type = 0, Order = 0 },
|
||||
new { KeepsakeRoomId = 37, RoomId = 21, KeepsakeRoomListId = 1, Type = 0, Order = 20 }
|
||||
},
|
||||
RoomUnlockStartOffsetTicks = 0,
|
||||
RoomUnlockIntervalTicks = 0,
|
||||
RoomUnlockBatchSize = 0,
|
||||
RoomType = 0,
|
||||
UnlockItemLockDuration = (object)null,
|
||||
RoomUnlockStartOffset = "00:00:00",
|
||||
RoomUnlockInterval = "00:00:00"
|
||||
},
|
||||
new {
|
||||
KeepsakeRoomListId = 2,
|
||||
ProgressionEventId = 3,
|
||||
UnlockItemAvatarItemId = (object)null,
|
||||
UnlockItemGiftDropId = (object)null,
|
||||
UnlockItemLockDurationTicks = (object)null,
|
||||
KeepsakeRooms = new[] {
|
||||
new { KeepsakeRoomId = 16, RoomId = 1, KeepsakeRoomListId = 2, Type = 1, Order = 5 },
|
||||
new { KeepsakeRoomId = 17, RoomId = 2, KeepsakeRoomListId = 2, Type = 1, Order = 6 },
|
||||
new { KeepsakeRoomId = 18, RoomId = 3, KeepsakeRoomListId = 2, Type = 1, Order = 7 },
|
||||
new { KeepsakeRoomId = 20, RoomId = 4, KeepsakeRoomListId = 2, Type = 1, Order = 8 },
|
||||
new { KeepsakeRoomId = 29, RoomId = 5, KeepsakeRoomListId = 2, Type = 1, Order = 4 },
|
||||
new { KeepsakeRoomId = 30, RoomId = 6, KeepsakeRoomListId = 2, Type = 1, Order = 3 },
|
||||
new { KeepsakeRoomId = 31, RoomId = 7, KeepsakeRoomListId = 2, Type = 1, Order = 2 },
|
||||
new { KeepsakeRoomId = 32, RoomId = 8, KeepsakeRoomListId = 2, Type = 1, Order = 1 },
|
||||
new { KeepsakeRoomId = 33, RoomId = 9, KeepsakeRoomListId = 2, Type = 1, Order = 0 },
|
||||
new { KeepsakeRoomId = 34, RoomId = 10, KeepsakeRoomListId = 2, Type = 1, Order = 9 },
|
||||
new { KeepsakeRoomId = 36, RoomId = 11, KeepsakeRoomListId = 2, Type = 1, Order = 10 }
|
||||
},
|
||||
RoomUnlockStartOffsetTicks = 0,
|
||||
RoomUnlockIntervalTicks = 0,
|
||||
RoomUnlockBatchSize = 0,
|
||||
RoomType = 1,
|
||||
UnlockItemLockDuration = (object)null,
|
||||
RoomUnlockStartOffset = "00:00:00",
|
||||
RoomUnlockInterval = "00:00:00"
|
||||
}
|
||||
},
|
||||
StartTime = "2022-09-13T23:00:00Z",
|
||||
EndTime = "9999-09-16T23:00:00Z",
|
||||
CollectionEndTime = "9999-09-17T23:00:00Z",
|
||||
UsesBoost = true,
|
||||
BoostDailyGameplayMinutesLimit = 20,
|
||||
BoostXpMultiplier = 3.0,
|
||||
PurchasableXpBoostId = (object)null,
|
||||
ActiveExperiment = (object)null,
|
||||
ChallengesIconImageName = (object)null,
|
||||
RewardsPipImageName = (object)null,
|
||||
EventInfoImageName = (object)null
|
||||
});*/
|
||||
#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type.
|
||||
}
|
||||
|
||||
[HttpGet("record/{eventId}")]
|
||||
public async Task<IActionResult> Record(long eventId)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/quickPlay")]
|
||||
[ApiController]
|
||||
public class QuickPlayController : ControllerBase
|
||||
{
|
||||
[HttpGet("v1/getandclear")]
|
||||
[Authorize(Roles = "gameClient")]
|
||||
public async Task<IActionResult> GetAndClear()
|
||||
{
|
||||
return Ok(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,364 @@
|
||||
using DeluxeBackend.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Numerics;
|
||||
using DeluxeBackend.Models;
|
||||
using System.Security.Claims;
|
||||
using static DeluxeBackend.Enums;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/relationships")]
|
||||
[ApiController]
|
||||
public class RelationshipsController : ControllerBase//this is from KittyRec https://git.tabbycluster.net/KittyRec/KittyRec-Api/src/branch/main/Controllers/relationshipsController.cs
|
||||
{
|
||||
private readonly ILiteDbService db;
|
||||
private readonly IJwtService jwt;
|
||||
private readonly INotificationService ws;
|
||||
private readonly IMessageService messageService;
|
||||
|
||||
public RelationshipsController(ILiteDbService _db, IJwtService _jwt, INotificationService _ws, IMessageService _messageService)
|
||||
{
|
||||
db = _db;
|
||||
jwt = _jwt;
|
||||
ws = _ws;
|
||||
messageService = _messageService;
|
||||
}
|
||||
|
||||
private long? GetCurrentPlayerId()
|
||||
{
|
||||
string? raw = User.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? User.FindFirst("sub")?.Value;
|
||||
if (long.TryParse(raw, out long id)) return id;
|
||||
return null;
|
||||
}
|
||||
|
||||
private Relationship? GetRelationship(long playerId, long targetId) =>
|
||||
db.Relationships
|
||||
.Include(x => x.Player)
|
||||
.Include(x => x.TargetPlayer)
|
||||
.FindOne(x => x.Player.Id == playerId && x.TargetPlayer.Id == targetId);
|
||||
|
||||
private Relationship GetOrCreate(long playerId, long targetId)
|
||||
{
|
||||
var rel = GetRelationship(playerId, targetId);
|
||||
if (rel != null) return rel;
|
||||
rel = new Relationship
|
||||
{
|
||||
Player = db.Accounts.FindById(playerId),
|
||||
TargetPlayer = db.Accounts.FindById(targetId)
|
||||
};
|
||||
db.Relationships.Insert(rel);
|
||||
return rel;
|
||||
}
|
||||
|
||||
private async Task PushRelToPlayer(long toPlayerId, long aboutPlayerId)
|
||||
{
|
||||
var rel = GetRelationship(toPlayerId, aboutPlayerId);
|
||||
await ws.SendToPlayer(toPlayerId, PushNotification.RelationshipChanged, new Dictionary<string, object>
|
||||
{
|
||||
["PlayerID"] = aboutPlayerId,
|
||||
["RelationshipType"] = (int)(rel?.RelationshipType ?? RelationshipType.None),
|
||||
["Muted"] = (int)(rel?.Muted ?? MuteState.None),
|
||||
["Ignored"] = (int)(rel?.Ignored ?? IgnoreState.None),
|
||||
["Favorited"] = rel?.Favorited ?? 0
|
||||
});
|
||||
}
|
||||
|
||||
private void DeleteFriendInvites(long fromPlayerId, long toPlayerId)
|
||||
{
|
||||
var messageToDelete = db.Messages.FindOne(m =>
|
||||
m.FromPlayer.Id == fromPlayerId &&
|
||||
m.Player.Id == toPlayerId &&
|
||||
m.Type == MessageType.FriendInvite);
|
||||
|
||||
if (messageToDelete != null)
|
||||
{
|
||||
db.Messages.Delete(messageToDelete.Id);
|
||||
|
||||
ws.SendToPlayer(toPlayerId, PushNotification.MessageDeleted, new Dictionary<string, object>
|
||||
{
|
||||
["Id"] = messageToDelete.Id
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("v2/get")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> get()
|
||||
{
|
||||
long? pid = GetCurrentPlayerId();
|
||||
if (pid == null) return Unauthorized();
|
||||
|
||||
var rels = db.Relationships
|
||||
.Query()
|
||||
.Include(x => x.Player)
|
||||
.Include(x => x.TargetPlayer)
|
||||
.Where(x => x.Player.Id == pid.Value)
|
||||
.ToList()
|
||||
.Select(r => r.ToDictionary())
|
||||
.ToList();
|
||||
|
||||
return Ok(rels);
|
||||
}
|
||||
|
||||
[HttpGet("v2/sendfriendrequest")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> SendFriendRequest([FromQuery] long id = 0)
|
||||
{
|
||||
long? pid = GetCurrentPlayerId();
|
||||
if (pid == null) return Unauthorized();
|
||||
|
||||
if (id == 0 || id == pid || db.Accounts.FindById(id) == null)
|
||||
return Ok();
|
||||
|
||||
var myRel = GetOrCreate(pid.Value, id);
|
||||
var theirRel = GetOrCreate(id, pid.Value);
|
||||
|
||||
if (myRel.RelationshipType == RelationshipType.Friend)
|
||||
return Ok();
|
||||
|
||||
// they already sent us one — auto-accept both sides
|
||||
if (theirRel.RelationshipType == RelationshipType.Sent || myRel.RelationshipType == RelationshipType.Received)
|
||||
{
|
||||
myRel.RelationshipType = RelationshipType.Friend;
|
||||
theirRel.RelationshipType = RelationshipType.Friend;
|
||||
db.Relationships.Update(myRel);
|
||||
db.Relationships.Update(theirRel);
|
||||
|
||||
DeleteFriendInvites(pid.Value, id);
|
||||
|
||||
Account me = db.Accounts.FindById(pid.Value);
|
||||
Account them = db.Accounts.FindById(id);
|
||||
await messageService.SendMessage(me, them, MessageType.FriendRequestAccepted, pid.Value.ToString());
|
||||
|
||||
await PushRelToPlayer(id, pid.Value);
|
||||
await PushRelToPlayer(pid.Value, id);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
// new outgoing request
|
||||
myRel.RelationshipType = RelationshipType.Sent;
|
||||
theirRel.RelationshipType = RelationshipType.Received;
|
||||
db.Relationships.Update(myRel);
|
||||
db.Relationships.Update(theirRel);
|
||||
|
||||
DeleteFriendInvites(id, pid.Value);
|
||||
|
||||
Account sender = db.Accounts.FindById(pid.Value);
|
||||
Account recipient = db.Accounts.FindById(id);
|
||||
await messageService.SendMessage(sender, recipient, MessageType.FriendInvite, pid.Value.ToString());
|
||||
|
||||
await PushRelToPlayer(id, pid.Value);
|
||||
await PushRelToPlayer(pid.Value, id);
|
||||
return Ok(myRel.ToDictionary());
|
||||
}
|
||||
|
||||
[HttpGet("v2/addfriend")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> AddFriend([FromQuery] long id = 0) =>
|
||||
await SendFriendRequest(id);
|
||||
|
||||
[HttpGet("v2/acceptfriendrequest")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> AcceptFriendRequest([FromQuery] long id = 0)
|
||||
{
|
||||
long? pid = GetCurrentPlayerId();
|
||||
if (pid == null) return Unauthorized();
|
||||
|
||||
if (id == 0 || id == pid)
|
||||
return Ok();
|
||||
|
||||
var myRel = GetOrCreate(pid.Value, id);
|
||||
var theirRel = GetOrCreate(id, pid.Value);
|
||||
|
||||
if (theirRel.RelationshipType != RelationshipType.Sent && myRel.RelationshipType != RelationshipType.Received)
|
||||
return Ok();
|
||||
|
||||
myRel.RelationshipType = RelationshipType.Friend;
|
||||
theirRel.RelationshipType = RelationshipType.Friend;
|
||||
db.Relationships.Update(myRel);
|
||||
db.Relationships.Update(theirRel);
|
||||
|
||||
DeleteFriendInvites(pid.Value, id);
|
||||
|
||||
Account me = db.Accounts.FindById(pid.Value);
|
||||
Account them = db.Accounts.FindById(id);
|
||||
await messageService.SendMessage(me, them, MessageType.FriendRequestAccepted, pid.Value.ToString());
|
||||
|
||||
await PushRelToPlayer(id, pid.Value);
|
||||
await PushRelToPlayer(pid.Value, id);
|
||||
return Ok(myRel.ToDictionary());
|
||||
}
|
||||
|
||||
[HttpGet("v2/removefriend")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> RemoveFriend([FromQuery] long id = 0)
|
||||
{
|
||||
long? pid = GetCurrentPlayerId();
|
||||
if (pid == null) return Unauthorized();
|
||||
|
||||
if (id != 0 && id != pid)
|
||||
{
|
||||
var myRel = GetRelationship(pid.Value, id);
|
||||
var theirRel = GetRelationship(id, pid.Value);
|
||||
|
||||
if (myRel != null) { myRel.RelationshipType = RelationshipType.None; db.Relationships.Update(myRel); }
|
||||
if (theirRel != null) { theirRel.RelationshipType = RelationshipType.None; db.Relationships.Update(theirRel); }
|
||||
|
||||
DeleteFriendInvites(pid.Value, id);
|
||||
DeleteFriendInvites(id, pid.Value);
|
||||
|
||||
await PushRelToPlayer(id, pid.Value);
|
||||
await PushRelToPlayer(pid.Value, id);
|
||||
|
||||
Dictionary<string, object> gg = new()
|
||||
{
|
||||
["PlayerID"] = pid,
|
||||
["RelationshipType"] = (int)(myRel?.RelationshipType ?? RelationshipType.None),
|
||||
["Muted"] = (int)(myRel?.Muted ?? MuteState.None),
|
||||
["Ignored"] = (int)(myRel?.Ignored ?? IgnoreState.None),
|
||||
["Favorited"] = myRel?.Favorited ?? 0
|
||||
};
|
||||
|
||||
return Ok(gg);
|
||||
}
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpGet("v1/favorite")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> Favorite([FromQuery] long id = 0)
|
||||
{
|
||||
long? pid = GetCurrentPlayerId();
|
||||
if (pid == null) return Unauthorized();
|
||||
|
||||
if (id != 0 && id != pid)
|
||||
{
|
||||
var rel = GetOrCreate(pid.Value, id);
|
||||
rel.Favorited = 1;
|
||||
db.Relationships.Update(rel);
|
||||
return Ok(rel.ToDictionary());
|
||||
}
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpGet("v1/unfavorite")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> Unfavorite([FromQuery] long id = 0)
|
||||
{
|
||||
long? pid = GetCurrentPlayerId();
|
||||
if (pid == null) return Unauthorized();
|
||||
|
||||
if (id != 0 && id != pid)
|
||||
{
|
||||
var rel = GetOrCreate(pid.Value, id);
|
||||
rel.Favorited = 0;
|
||||
db.Relationships.Update(rel);
|
||||
return Ok(rel.ToDictionary());
|
||||
}
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpPost("v1/mute")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> Mute([FromForm(Name = "PlayerId"), Required] long playerId)
|
||||
{
|
||||
long? pid = GetCurrentPlayerId();
|
||||
if (pid == null) return Unauthorized();
|
||||
|
||||
if (playerId == 0 || playerId == pid)
|
||||
return Ok();
|
||||
|
||||
var myRel = GetOrCreate(pid.Value, playerId);
|
||||
var theirRel = GetOrCreate(playerId, pid.Value);
|
||||
|
||||
myRel.Muted = MuteState.Local;
|
||||
theirRel.Muted = MuteState.Remote;
|
||||
db.Relationships.Update(myRel);
|
||||
db.Relationships.Update(theirRel);
|
||||
|
||||
await PushRelToPlayer(pid.Value, playerId);
|
||||
await PushRelToPlayer(playerId, pid.Value);
|
||||
return Ok(myRel.ToDictionary());
|
||||
}
|
||||
|
||||
[HttpPost("v1/unmute")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> Unmute([FromForm(Name = "PlayerId"), Required] long playerId)
|
||||
{
|
||||
long? pid = GetCurrentPlayerId();
|
||||
if (pid == null) return Unauthorized();
|
||||
|
||||
if (playerId == 0 || playerId == pid)
|
||||
return Ok();
|
||||
|
||||
var myRel = GetOrCreate(pid.Value, playerId);
|
||||
var theirRel = GetOrCreate(playerId, pid.Value);
|
||||
|
||||
myRel.Muted = MuteState.None;
|
||||
if (theirRel.Muted == MuteState.Remote) theirRel.Muted = MuteState.None;
|
||||
db.Relationships.Update(myRel);
|
||||
db.Relationships.Update(theirRel);
|
||||
|
||||
await PushRelToPlayer(pid.Value, playerId);
|
||||
await PushRelToPlayer(playerId, pid.Value);
|
||||
return Ok(myRel.ToDictionary());
|
||||
}
|
||||
|
||||
[HttpPost("v1/ignore")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> Ignore([FromForm(Name = "PlayerId"), Required] long playerId)
|
||||
{
|
||||
long? pid = GetCurrentPlayerId();
|
||||
if (pid == null) return Unauthorized();
|
||||
|
||||
if (playerId == 0 || playerId == pid)
|
||||
return Ok();
|
||||
|
||||
var myRel = GetOrCreate(pid.Value, playerId);
|
||||
var theirRel = GetOrCreate(playerId, pid.Value);
|
||||
|
||||
myRel.Ignored = IgnoreState.Local;
|
||||
theirRel.Ignored = IgnoreState.Remote;
|
||||
db.Relationships.Update(myRel);
|
||||
db.Relationships.Update(theirRel);
|
||||
|
||||
await PushRelToPlayer(pid.Value, playerId);
|
||||
await PushRelToPlayer(playerId, pid.Value);
|
||||
return Ok(myRel.ToDictionary());
|
||||
}
|
||||
|
||||
[HttpPost("v1/unignore")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> Unignore([FromForm(Name = "PlayerId"), Required] long playerId)
|
||||
{
|
||||
long? pid = GetCurrentPlayerId();
|
||||
if (pid == null) return Unauthorized();
|
||||
|
||||
if (playerId == 0 || playerId == pid)
|
||||
return Ok();
|
||||
|
||||
var myRel = GetOrCreate(pid.Value, playerId);
|
||||
var theirRel = GetOrCreate(playerId, pid.Value);
|
||||
|
||||
myRel.Ignored = IgnoreState.None;
|
||||
if (theirRel.Ignored == IgnoreState.Remote) theirRel.Ignored = IgnoreState.None;
|
||||
db.Relationships.Update(myRel);
|
||||
db.Relationships.Update(theirRel);
|
||||
|
||||
await PushRelToPlayer(pid.Value, playerId);
|
||||
await PushRelToPlayer(playerId, pid.Value);
|
||||
return Ok(myRel.ToDictionary());
|
||||
}
|
||||
|
||||
[HttpPost("v1/bulkignoreplatformusers")]
|
||||
public IActionResult BulkIgnorePlatformUsers() =>
|
||||
Ok();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class RoomConsumablesController : ControllerBase
|
||||
{
|
||||
[HttpGet("v1/roomConsumable/room/{roomId}")]
|
||||
public async Task<IActionResult> Saved([FromRoute] long roomId)
|
||||
{
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
[HttpGet("v1/roomConsumable/room/{roomId}/me")]
|
||||
public async Task<IActionResult> myRoomConsumables([FromRoute] long roomId)
|
||||
{
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class RoomCurrenciesController : ControllerBase
|
||||
{
|
||||
[HttpGet("v1/currencies")]
|
||||
public async Task<IActionResult> Saved([FromQuery] long roomId)
|
||||
{
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
|
||||
[HttpGet("v1/getAllBalances")]
|
||||
public async Task<IActionResult> GetAllBalances([FromQuery] long roomId)
|
||||
{
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using DeluxeBackend.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/roomkeys")]
|
||||
[ApiController]
|
||||
public class RoomKeysController : ControllerBase
|
||||
{
|
||||
[HttpGet("v1/mine")]
|
||||
[Authorize(Roles = "gameClient")]
|
||||
public async Task<IActionResult> None()
|
||||
{
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
[HttpGet("v1/room")]
|
||||
[Authorize(Roles = "gameClient")]
|
||||
public async Task<IActionResult> Room()
|
||||
{
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using DeluxeBackend.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/sanitize")]
|
||||
[ApiController]
|
||||
public class SanitizeController : ControllerBase
|
||||
{
|
||||
[HttpPost("v1/isPure")]
|
||||
[Authorize(Roles = "gameClient")]
|
||||
public async Task<IActionResult> IsPure()
|
||||
{
|
||||
return Ok(new { IsPure = true});
|
||||
}
|
||||
|
||||
public class SanitizeRequest
|
||||
{
|
||||
public string Value { get; set; } = string.Empty;
|
||||
public int ReplacementChar { get; set; } = 42;
|
||||
}
|
||||
[HttpPost("v1")]
|
||||
public async Task<IActionResult> SanitizeMessage([FromBody] SanitizeRequest request)
|
||||
{
|
||||
var sanitized = JsonSerializer.Serialize(request.Value);
|
||||
return Ok(sanitized);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using static DeluxeBackend.Enums;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/storefronts")]
|
||||
[ApiController]
|
||||
public class StorefrontsController : ControllerBase
|
||||
{
|
||||
[HttpGet("v3/giftdropstore/{type}")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> Thread([FromRoute] StorefrontType type)
|
||||
{
|
||||
return Ok(new
|
||||
{
|
||||
StorefrontType = (int)type,
|
||||
NextUpdate = DateTime.MaxValue.ToString("O"),
|
||||
StoreItems = new List<object>(),
|
||||
SubscriberDiscountPercent = 0
|
||||
});
|
||||
}
|
||||
[HttpGet("v4/balance/{type}")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> Thread([FromRoute] PMKKDOJNMGM type)
|
||||
{
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/ugcPurchasables")]
|
||||
[ApiController]
|
||||
public class UgcPurchasablesController() : ControllerBase
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace DeluxeBackend.Controllers.Api
|
||||
{
|
||||
[Route("api/versioncheck")]
|
||||
[ApiController]
|
||||
public class VersioncheckController : ControllerBase
|
||||
{
|
||||
[HttpGet("v1")]//this is for 2016 builds
|
||||
public IActionResult V1([FromHeader(Name = "X-Rec-Room-Version")] string appVersion = "")
|
||||
{
|
||||
if (appVersion != ServerConfig.AppVersion)
|
||||
{
|
||||
return StatusCode(403);
|
||||
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
[HttpGet("v2")]//this is for 2017/2018 builds
|
||||
[HttpGet("v3")]
|
||||
public IActionResult V3([FromQuery(Name = "v")] string appVersion = "")
|
||||
{
|
||||
return Ok(new
|
||||
{
|
||||
ValidVersion = appVersion == ServerConfig.AppVersion
|
||||
});
|
||||
}
|
||||
|
||||
[HttpGet("v4")]//this is for 2019 and later builds
|
||||
public IActionResult V4([FromQuery(Name = "v"), Required] string appVersion, [FromQuery(Name = "p")] int? platform = null, [FromQuery(Name = "pid")] string? platformId = null)
|
||||
{
|
||||
int versionStatus = 0;
|
||||
if (appVersion != ServerConfig.AppVersion)
|
||||
{
|
||||
versionStatus = 1;
|
||||
|
||||
}
|
||||
return Ok(new
|
||||
{
|
||||
VersionStatus = versionStatus,
|
||||
UpdateNotificationStage = 0,
|
||||
IsVersionIslanded = false,
|
||||
IsCrossPlayDisabled = false
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user