mirror of
https://github.com/CannedNet/CannedNet.git
synced 2026-10-28 00:19:05 -07:00
PROBABLY BROKEN BUT OK
This commit is contained in:
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"Hosting": {
|
|
||||||
"Url": "http://*:5000"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"Hosting": {
|
|
||||||
"Url": "http://*:5005"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"Hosting": {
|
|
||||||
"Url": "http://*:5002"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"Hosting": {
|
|
||||||
"Url": "http://*:5007"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"Hosting": {
|
|
||||||
"Url": "http://*:5003"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"Hosting": {
|
|
||||||
"Url": "http://*:5009"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"Hosting": {
|
|
||||||
"Url": "http://*:5010"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"Hosting": {
|
|
||||||
"Url": "http://*:5008"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"Hosting": {
|
|
||||||
"Url": "http://*:5004"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"Hosting": {
|
|
||||||
"Url": "http://*:5001"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"Hosting": {
|
|
||||||
"Url": "http://*:5006"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -9,11 +9,26 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.11" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.8" />
|
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.8" />
|
||||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.2.2" />
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.19.2" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<_ContentIncludedByDefault Remove="AppConfigs\appsettings.Accounts.json" />
|
||||||
|
<_ContentIncludedByDefault Remove="AppConfigs\appsettings.API.json" />
|
||||||
|
<_ContentIncludedByDefault Remove="AppConfigs\appsettings.Auth.json" />
|
||||||
|
<_ContentIncludedByDefault Remove="AppConfigs\appsettings.CDN.json" />
|
||||||
|
<_ContentIncludedByDefault Remove="AppConfigs\appsettings.Chat.json" />
|
||||||
|
<_ContentIncludedByDefault Remove="AppConfigs\appsettings.Clubs.json" />
|
||||||
|
<_ContentIncludedByDefault Remove="AppConfigs\appsettings.Commerce.json" />
|
||||||
|
<_ContentIncludedByDefault Remove="AppConfigs\appsettings.Image.json" />
|
||||||
|
<_ContentIncludedByDefault Remove="AppConfigs\appsettings.Match.json" />
|
||||||
|
<_ContentIncludedByDefault Remove="AppConfigs\appsettings.Notify.json" />
|
||||||
|
<_ContentIncludedByDefault Remove="AppConfigs\appsettings.NS.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv5tZ6wY8g3rXpMqrXnvA
|
||||||
|
eLL9dx0tk8Cqt5C3dGVsNxFvrH6isfrsQDSZ8XWC/LAx/U9l4ouOJExx9rgxr3up
|
||||||
|
XywAHZVLtFr00KbMRtKP4PrNGNfQpIou3weCJg1Gh3mtgHfwU/jJuc0UYdHLRpVv
|
||||||
|
JCtn4VLf6/UjdatN5wc4qK/yXQh6MgBFI+IuGlaMoCdn5MbzK6bX7CFzQ8Ch8Oeh
|
||||||
|
8HikSbfuHenudaE74Z04HYqGMx3Yzq+2Fd9XdNjvYgcaR9HJdfVAB2vkuNo3/Kv1
|
||||||
|
axCjouJIl3SPp+6a6Nc36Qo67VSf4AOusgepDjAacXmndn3qux1wMEugl7B6Xi4W
|
||||||
|
WQIDAQAB
|
||||||
|
-----END PUBLIC KEY-----
|
||||||
@@ -1,26 +1,38 @@
|
|||||||
{
|
{
|
||||||
"Auth": "https://auth.lapis.codes",
|
"Accounts": "https://cn-test.lapiscreates.tech/accounts",
|
||||||
"API": "https://api.lapis.codes",
|
"AI": "https://cn-test.lapiscreates.tech/ai",
|
||||||
"WWW": "https://www.lapis.codes",
|
"API": "https://cn-test.lapiscreates.tech/api",
|
||||||
"Notifications": "https://notify.lapis.codes",
|
"Auth": "https://cn-test.lapiscreates.tech/auth",
|
||||||
"Images": "https://img.lapis.codes",
|
"BugReporting": "https://cn-test.lapiscreates.tech/bugreporting",
|
||||||
"CDN": "https://cdn.lapis.codes",
|
"Cards": "https://cn-test.lapiscreates.tech/cards",
|
||||||
"Commerce": "https://commerce.lapis.codes",
|
"CDN": "https://cn-test.lapiscreates.tech/cdn",
|
||||||
"Matchmaking": "https://match.lapis.codes",
|
"Chat": "https://cn-test.lapiscreates.tech/chat",
|
||||||
"Storage": "https://cdn.lapis.codes",
|
"Clubs": "https://cn-test.lapiscreates.tech/clubs",
|
||||||
"Chat": "https://chatrr.lapis.codes",
|
"CMS": "https://cn-test.lapiscreates.tech/cms",
|
||||||
"Leaderboard": "https://leaderboard.lapis.codes",
|
"Commerce": "https://cn-test.lapiscreates.tech/commerce",
|
||||||
"Accounts": "https://accounts.lapis.codes",
|
"Data": "https://cn-test.lapiscreates.tech/data",
|
||||||
"Link": "https://link.lapis.codes",
|
"DataCollection": "https://cn-test.lapiscreates.tech/datacollection",
|
||||||
"RoomComments": "https://roomcomments.lapis.codes",
|
"Discovery": "https://cn-test.lapiscreates.tech/discovery",
|
||||||
"Clubs": "https://clubs.lapis.codes",
|
"Econ": "https://cn-test.lapiscreates.tech/econ",
|
||||||
"Rooms": "https://rooms.lapis.codes",
|
"GameLogs": "https://cn-test.lapiscreates.tech/gamelogs",
|
||||||
"PlatformNotifications": "https://api.lapis.codes",
|
"Geo": "https://cn-test.lapiscreates.tech/geo",
|
||||||
"Moderation": "https://api.lapis.codes",
|
"Images": "https://cn-test.lapiscreates.tech/img",
|
||||||
"DataCollection": "https://api.lapis.codes",
|
"Leaderboard": "https://cn-test.lapiscreates.tech/leaderboard",
|
||||||
"BugReporting": "https://api.lapis.codes",
|
"Link": "https://cn-test.lapiscreates.tech/link",
|
||||||
"Discovery": "https://api.lapis.codes",
|
"Lists": "https://cn-test.lapiscreates.tech/lists",
|
||||||
"PlayerSettings": "https://api.lapis.codes",
|
"Matchmaking": "https://cn-test.lapiscreates.tech/match",
|
||||||
"Rendering": "https://api.lapis.codes",
|
"Moderation": "https://cn-test.lapiscreates.tech/moderation",
|
||||||
"Launcher": "https://launcher.lapis.codes"
|
"Notifications": "https://cn-test.lapiscreates.tech",
|
||||||
|
"PlatformNotifications": "https://cn-test.lapiscreates.tech",
|
||||||
|
"PlayerSettings": "https://cn-test.lapiscreates.tech/playersettings",
|
||||||
|
"RoomComments": "https://cn-test.lapiscreates.tech/roomcomments",
|
||||||
|
"RoomieIntegrations": "https://cn-test.lapiscreates.tech/roomieintegrations",
|
||||||
|
"Rooms": "https://cn-test.lapiscreates.tech/rooms",
|
||||||
|
"Storage": "https://cn-test.lapiscreates.tech/storage",
|
||||||
|
"Strings": "https://cn-test.lapiscreates.tech/strings",
|
||||||
|
"StringsCDN": "https://cn-test.lapiscreates.tech/stringscdn",
|
||||||
|
"Studio": "https://cn-test.lapiscreates.tech/studio",
|
||||||
|
"Thorn": "https://cn-test.lapiscreates.tech/thorn",
|
||||||
|
"Videos": "https://cn-test.lapiscreates.tech/videos",
|
||||||
|
"WWW": "https://cn-test.lapiscreates.tech"
|
||||||
}
|
}
|
||||||
+92
-38
@@ -1,48 +1,102 @@
|
|||||||
using CannedNet;
|
using System.Security.Claims;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using CannedNet.Data;
|
||||||
|
using CannedNet.Hubs;
|
||||||
using CannedNet.Services;
|
using CannedNet.Services;
|
||||||
using CannedNet.Services.Infrastructure;
|
using CannedNet.Services.Infrastructure;
|
||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
|
||||||
var apps = new List<(WebApplication App, ServiceRegistry Service)>();
|
namespace CannedNet;
|
||||||
|
|
||||||
foreach (var service in Services.All)
|
public static class Program
|
||||||
{
|
{
|
||||||
var builder = WebApplication.CreateBuilder();
|
public static async Task Main(string[] args)
|
||||||
|
|
||||||
builder.Services.AddLogging(logging =>
|
|
||||||
{
|
{
|
||||||
logging.AddConsole();
|
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
|
||||||
logging.SetMinimumLevel(LogLevel.Debug);
|
|
||||||
});
|
|
||||||
|
|
||||||
service.ConfigureBuilder(builder);
|
string connectionString = builder.Configuration.GetConnectionString("DefaultConnection")
|
||||||
builder.WebHost.UseUrls($"http://*:{service.Port}");
|
?? "Host=localhost;Port=5432;Database=cannednet;Username=postgres;Password=postgres";
|
||||||
builder.Configuration.AddJsonFile($"AppConfigs/appsettings.{service.Name}.json", optional: true, reloadOnChange: true);
|
|
||||||
|
|
||||||
apps.Add((builder.Build(), service));
|
builder.Services.AddControllers()
|
||||||
|
.AddJsonOptions(options =>
|
||||||
|
{
|
||||||
|
options.JsonSerializerOptions.PropertyNamingPolicy = null;
|
||||||
|
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Services.AddDbContext<AppDbContext>(options => options.UseNpgsql(connectionString));
|
||||||
|
builder.Services.AddSingleton<NotificationService>();
|
||||||
|
builder.Services.AddScoped<StorefrontFillService>();
|
||||||
|
builder.Services.AddSingleton<JwtTokenService>();
|
||||||
|
builder.Services.AddSingleton<ConfigService>();
|
||||||
|
builder.Services.AddSignalR();
|
||||||
|
|
||||||
|
builder.Services.AddAuthentication(options =>
|
||||||
|
{
|
||||||
|
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
})
|
||||||
|
.AddJwtBearer(options =>
|
||||||
|
{
|
||||||
|
var rsa = JwtTokenService.GetRsaInstance();
|
||||||
|
|
||||||
|
// TODO: make validissuer and validaudiences/validaudience configurable
|
||||||
|
// TODO: make this key load from config, DO NOT USE THIS KEY IN PROD SERVERS!!!
|
||||||
|
var securityKey = new RsaSecurityKey(rsa) { KeyId = "7C2F041398671515B0862CB23FAF95B03" };
|
||||||
|
|
||||||
|
options.TokenValidationParameters = new TokenValidationParameters
|
||||||
|
{
|
||||||
|
ValidateIssuerSigningKey = true,
|
||||||
|
IssuerSigningKey = securityKey,
|
||||||
|
ValidateIssuer = false,
|
||||||
|
ValidIssuer = "https://auth.lapis.codes",
|
||||||
|
ValidateAudience = false,
|
||||||
|
ValidAudiences = new[]
|
||||||
|
{
|
||||||
|
"https://auth.lapis.codes",
|
||||||
|
"https://auth.lapis.codes/resources"
|
||||||
|
},
|
||||||
|
ValidateLifetime = true,
|
||||||
|
ClockSkew = TimeSpan.Zero,
|
||||||
|
NameClaimType = ClaimTypes.NameIdentifier,
|
||||||
|
RoleClaimType = ClaimTypes.Role
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Services.AddAuthorization();
|
||||||
|
|
||||||
|
WebApplication app = builder.Build();
|
||||||
|
|
||||||
|
app.UseRequestLogging();
|
||||||
|
app.UseAuthentication();
|
||||||
|
app.UseAuthorization();
|
||||||
|
app.MapControllers();
|
||||||
|
app.MapHub<NotificationsHub>("/hub/v1");
|
||||||
|
|
||||||
|
IHubContext<NotificationsHub> hubContext = app.Services.GetRequiredService<IHubContext<NotificationsHub>>();
|
||||||
|
NotificationService.SetHubContext(hubContext);
|
||||||
|
|
||||||
|
using IServiceScope scope = app.Services.CreateScope();
|
||||||
|
AppDbContext db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await db.Database.MigrateAsync();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await db.Database.EnsureCreatedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
StorefrontFillService seedingService = scope.ServiceProvider.GetRequiredService<StorefrontFillService>();
|
||||||
|
await seedingService.FillStorefrontsAsync();
|
||||||
|
|
||||||
|
Signatures.Init();
|
||||||
|
|
||||||
|
await app.RunAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using var scope = apps[0].App.Services.CreateScope();
|
|
||||||
var dbContext = scope.ServiceProvider.GetRequiredService<CannedNet.Data.AppDbContext>();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
dbContext.Database.Migrate();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
dbContext.Database.EnsureCreated();
|
|
||||||
}
|
|
||||||
|
|
||||||
// automatically fill out storefronts tables from the JSON's
|
|
||||||
var seedingService = scope.ServiceProvider.GetRequiredService<StorefrontFillService>();
|
|
||||||
await seedingService.FillStorefrontsAsync();
|
|
||||||
|
|
||||||
var jwtService = scope.ServiceProvider.GetRequiredService<JwtTokenService>();
|
|
||||||
|
|
||||||
foreach (var (app, service) in apps)
|
|
||||||
{
|
|
||||||
service.MapEndpoints(app, jwtService);
|
|
||||||
app.UseRequestLogging();
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.WhenAll(apps.Select(t => t.App.RunAsync()));
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
namespace CannedNet.Services;
|
||||||
|
|
||||||
|
public class ConfigService
|
||||||
|
{
|
||||||
|
public ConfigData Config { get; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ConfigData
|
||||||
|
{
|
||||||
|
public bool WhitelistOn { get; set; }
|
||||||
|
public List<string> WhitelistedPlatformIds { get; set; } = [];
|
||||||
|
public bool EnableAccountCreation { get; set; } = true;
|
||||||
|
public List<string> AdminAccountIds { get; set; } = [];
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using CannedNet;
|
using CannedNet;
|
||||||
using CannedNet.Data;
|
using CannedNet.Data;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
@@ -11,517 +12,574 @@ using CannedNet.Services.Infrastructure;
|
|||||||
|
|
||||||
namespace CannedNet.Services.Controllers;
|
namespace CannedNet.Services.Controllers;
|
||||||
|
|
||||||
public class APIController
|
[ApiController]
|
||||||
|
[Route("api")]
|
||||||
|
public class APIController : ControllerBase
|
||||||
{
|
{
|
||||||
public WebApplicationBuilder Initialize(string[]? args = null) => ServiceExtensions.CreateRecNetBuilder(args);
|
private readonly JwtTokenService _jwtService;
|
||||||
|
private readonly StorefrontFillService _storefrontService;
|
||||||
|
private readonly NotificationService _notificationService;
|
||||||
|
|
||||||
public void MapEndpoints(WebApplication app)
|
public APIController(JwtTokenService jwtService, StorefrontFillService storefrontService, NotificationService notificationService)
|
||||||
{
|
{
|
||||||
var jwtService = app.Services.GetRequiredService<JwtTokenService>();
|
_jwtService = jwtService;
|
||||||
var storefrontService = app.Services.GetRequiredService<StorefrontFillService>();
|
_storefrontService = storefrontService;
|
||||||
var notificationService = app.Services.GetRequiredService<NotificationService>();
|
_notificationService = notificationService;
|
||||||
|
}
|
||||||
|
|
||||||
app.MapGet("/api/config/v1/amplitude", () => Results.Ok(new
|
[HttpGet("config/v1/amplitude")]
|
||||||
|
public IResult GetAmplitudeConfig() => Results.Ok(new
|
||||||
|
{
|
||||||
|
AmplitudeKey = "a",
|
||||||
|
StatSigKey = "a",
|
||||||
|
RudderStackKey = "a",
|
||||||
|
UseRudderStack = false
|
||||||
|
});
|
||||||
|
|
||||||
|
[HttpGet("config/v2")]
|
||||||
|
public IResult GetConfigV2() => Results.Content(System.IO.File.ReadAllText("JSON/configv2.json"), "application/json");
|
||||||
|
|
||||||
|
[HttpGet("versioncheck/v4")]
|
||||||
|
public IResult GetVersionCheck() => Results.Content("{\"VersionStatus\":0}", "application/json");
|
||||||
|
|
||||||
|
[HttpGet("gameconfigs/v1/all")]
|
||||||
|
public IResult GetGameConfigs() => Results.Content(System.IO.File.ReadAllText("JSON/gameconfigs.json"), "application/json");
|
||||||
|
|
||||||
|
[HttpGet("relationships/v2/get")]
|
||||||
|
public IResult GetRelationships() => Results.Content("[]", "application/json");
|
||||||
|
|
||||||
|
[HttpGet("messages/v2/get")]
|
||||||
|
public IResult GetMessages() => Results.Content("[]", "application/json");
|
||||||
|
|
||||||
|
[HttpGet("playerReputation/v1/{id}")]
|
||||||
|
public IResult GetPlayerReputation(string id) =>
|
||||||
|
Results.Content($"{{\"AccountId\":{id},\"Noteriety\":0,\"CheerGeneral\":0,\"CheerHelpful\":0,\"CheerCreative\":0,\"CheerGreatHost\":0,\"CheerSportsman\":0,\"CheerCredit\":20,\"SelectedCheer\":null}}", "application/json");
|
||||||
|
|
||||||
|
[HttpGet("players/v1/progression/{id}")]
|
||||||
|
public IResult GetPlayerProgression(string id) =>
|
||||||
|
Results.Content($"{{\"PlayerId\":{id},\"Level\":1,\"XP\":0}}", "application/json");
|
||||||
|
|
||||||
|
[HttpPost("playerReputation/v1/bulk")]
|
||||||
|
public async Task<IResult> BulkPlayerReputation(HttpRequest httpRequest, AppDbContext db)
|
||||||
|
{
|
||||||
|
/*var ids = await ParseFormIds(httpRequest);
|
||||||
|
|
||||||
|
if (!ids.Any())
|
||||||
|
return Results.Json(new List<object>());
|
||||||
|
|
||||||
|
var reputations = ids.Select(id => new
|
||||||
{
|
{
|
||||||
AmplitudeKey = "a",
|
AccountId = id,
|
||||||
StatSigKey = "a",
|
Noteriety = 0,
|
||||||
RudderStackKey = "a",
|
CheerGeneral = 0,
|
||||||
UseRudderStack = false
|
CheerHelpful = 0,
|
||||||
}));
|
CheerCreative = 0,
|
||||||
|
CheerGreatHost = 0,
|
||||||
|
CheerSportsman = 0,
|
||||||
|
CheerCredit = 20,
|
||||||
|
SelectedCheer = (object?)null
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
app.MapGet("/api/config/v2", () => Results.Content(File.ReadAllText("JSON/configv2.json"), "application/json"));
|
return Results.Json(reputations);*/
|
||||||
app.MapGet("/api/versioncheck/v4", () => Results.Content("{\"VersionStatus\":0}", "application/json"));
|
|
||||||
app.MapGet("/api/gameconfigs/v1/all", () => Results.Content(File.ReadAllText("JSON/gameconfigs.json"), "application/json"));
|
|
||||||
|
|
||||||
app.MapGet("/api/relationships/v2/get", () => Results.Content("[]", "application/json"));
|
// TODO: implement real endpoint from grabbing from db
|
||||||
app.MapGet("/api/messages/v2/get", () => Results.Content("[]", "application/json"));
|
var json = System.IO.File.ReadAllText("JSON/bulkprogression.json");
|
||||||
|
return Results.Content(json, "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
app.MapGet("/api/playerReputation/v1/{id}", (string id) =>
|
[HttpPost("players/v1/progression/bulk")]
|
||||||
Results.Content($"{{\"AccountId\":{id},\"Noteriety\":0,\"CheerGeneral\":0,\"CheerHelpful\":0,\"CheerCreative\":0,\"CheerGreatHost\":0,\"CheerSportsman\":0,\"CheerCredit\":20,\"SelectedCheer\":null}}", "application/json"));
|
public async Task<IResult> BulkPlayerProgression(HttpRequest httpRequest, AppDbContext db)
|
||||||
|
{
|
||||||
|
var ids = await ParseFormIds(httpRequest);
|
||||||
|
|
||||||
app.MapGet("/api/players/v1/progression/{id}", (string id) =>
|
if (!ids.Any())
|
||||||
Results.Content($"{{\"PlayerId\":{id},\"Level\":1,\"XP\":0}}", "application/json"));
|
return Results.Json(new List<PlayerProgressionBulkResponse>());
|
||||||
|
|
||||||
app.MapPost("/api/playerReputation/v1/bulk", async (HttpRequest httpRequest, AppDbContext db) =>
|
var progressions = await db.PlayerProgressions
|
||||||
|
.Where(p => ids.Contains(p.PlayerId))
|
||||||
|
.Select(p => new PlayerProgressionBulkResponse { PlayerId = p.PlayerId, Level = p.Level, Xp = p.Xp })
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return Results.Json(progressions);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("v1/progression/bulk")]
|
||||||
|
public async Task<IResult> BulkProgression(HttpRequest httpRequest, AppDbContext db)
|
||||||
|
{
|
||||||
|
var ids = await ParseFormIds(httpRequest);
|
||||||
|
|
||||||
|
if (!ids.Any())
|
||||||
|
return Results.Json(new List<PlayerProgressionBulkResponse>());
|
||||||
|
|
||||||
|
var progressions = await db.PlayerProgressions
|
||||||
|
.Where(p => ids.Contains(p.PlayerId))
|
||||||
|
.Select(p => new PlayerProgressionBulkResponse { PlayerId = p.PlayerId, Level = p.Level, Xp = p.Xp })
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return Results.Json(progressions);
|
||||||
|
}
|
||||||
|
[HttpGet("avatar/v4/items")]
|
||||||
|
public async Task<IResult> GetAvatarItems(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
|
var accountId = _jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(accountId))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
if (!int.TryParse(accountId.AsSpan(), out var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var ownedItems = await db.AvatarItems
|
||||||
|
.Where(i => i.OwnerAccountId == id)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var defaultItems = new List<object>
|
||||||
{
|
{
|
||||||
/*var ids = await ParseFormIds(httpRequest);
|
new { AvatarItemType = 0, AvatarItemDesc = "5d13a7a2-8213-40e6-90a6-efdd76a3fdcb,,,", PlatformMask = -1, FriendlyName = "Flowing Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "1d27b674-f9e2-4ffc-9d8c-a58a1be06457,,,", PlatformMask = -1, FriendlyName = "Afro Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "d84c0ff9-8fbe-4ed8-abf3-7996e81888ab,,,", PlatformMask = -1, FriendlyName = "Large Afro Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "e5b83dfc-b2e1-4dcb-a4ab-9d3a4c8a34ae,,,", PlatformMask = -1, FriendlyName = "Long Wavy Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "7dd6f7b0-7ba0-429f-a04f-e32d3a79ee61,,,", PlatformMask = -1, FriendlyName = "Short Wavy Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "eb9611c6-bb50-41a2-93e9-7f959815a846,,,", PlatformMask = -1, FriendlyName = "Dreads Long Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "1fd69ef8-0b74-4962-af5a-67f0bf0358f2,,,", PlatformMask = -1, FriendlyName = "Ponytail Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "a12f724f-4a73-4ab8-aad4-6bfc662b4dd6,,,", PlatformMask = -1, FriendlyName = "Undercut Long Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "0753d7a4-8247-4fca-a6fc-359c26086140,,,", PlatformMask = -1, FriendlyName = "Fonzie Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "77d3c585-4928-4471-a425-89036efe7299,,,", PlatformMask = -1, FriendlyName = "Spiky Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "92302d9d-c527-418c-ac5d-1fa869727505,,,", PlatformMask = -1, FriendlyName = "Part Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "f9dd08f8-16d3-4c39-af4f-89f7bb6e80d3,,,", PlatformMask = -1, FriendlyName = "Undercut Short Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "b148cb1e-df81-442f-aea6-ab1727aad00e,,,", PlatformMask = -1, FriendlyName = "Chunky Afro Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "e36bcd98-7e85-43fa-89f8-57e4ec33823a,,,", PlatformMask = -1, FriendlyName = "Bob with Bangs Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "880a3cc0-7407-4b61-b759-f9dd890fe9e5,,,", PlatformMask = -1, FriendlyName = "Bob Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "21599b51-c50f-43d8-ac5f-62c30cd02ca5,,,", PlatformMask = -1, FriendlyName = "Lori Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "193a3bf9-abc0-4d78-8d63-92046908b1c5,,,", PlatformMask = -1, FriendlyName = "Emo Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "79b90274-6eec-4664-acfb-4a123334661e,,,", PlatformMask = -1, FriendlyName = "Pig Tails Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "da4e7b34-2095-4a9e-801e-4f409039e0dd,,,", PlatformMask = -1, FriendlyName = "Buzz Cut Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "9d9fadb6-97eb-480e-a224-4e0179082071,,,", PlatformMask = -1, FriendlyName = "Meatball Buns Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "d8280c0c-d803-4513-be10-a0ba96d8821e,,,", PlatformMask = -1, FriendlyName = "Flowhawk Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "e286863c-2967-4d00-b837-b49487b9484a,,,", PlatformMask = -1, FriendlyName = "Fauxhawk Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "2cb4f372-3372-4583-8b57-c4e3988e3c28,,,", PlatformMask = -1, FriendlyName = "Punky Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "06306723-ca20-4aa6-b7b3-917113f41ac3,,,", PlatformMask = -1, FriendlyName = "Cat-Eye Glasses (Red)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "c70005d5-6276-4a98-acb3-6a77bc19379a,,,", PlatformMask = -1, FriendlyName = "Glasses (Teal)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "8d10cc78-6b00-45f3-affb-205e9cc5b03f,,,", PlatformMask = -1, FriendlyName = "Beard (Close)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "cc96f8a5-bc5b-4f89-83b7-ecd53905ada7,,,", PlatformMask = -1, FriendlyName = "Beard (Thick)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "c6c08eb5-381a-4193-9722-80da95d62abe,,,", PlatformMask = -1, FriendlyName = "Business Tie (Black)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "4d507dfa-4a99-4ac0-8537-229e9dc0eb4a,,,", PlatformMask = -1, FriendlyName = "Rec Room Tank Top (Orange)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "d0a9262f-5504-46a7-bb10-7507503db58e,,,", PlatformMask = -1, FriendlyName = "Rec Room Shirt (Crew Neck, White)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "d0a9262f-5504-46a7-bb10-7507503db58e,95e4cc30-cb68-473d-a395-feadf5b51512,0440f08f-ef1d-49d8-942b-523056e8bb45,", PlatformMask = -1, FriendlyName = "Rec Room T-Shirt (Crew Neck, Orange)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "2e59d8d0-91a0-4449-bfdc-a5d663fd9343,,,", PlatformMask = -1, FriendlyName = "Collared Shirt (Plaid, Blue)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "7b857a8c-92ad-4028-a2c2-b3c20cdab5f2,,,", PlatformMask = -1, FriendlyName = "T-Shirt", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "8aa79563-ace1-4ba7-ad0c-f3210a78142f,,,", PlatformMask = -1, FriendlyName = "Rec Room Shirt (V-Neck, White)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "8aa79563-ace1-4ba7-ad0c-f3210a78142f,95e4cc30-cb68-473d-a395-feadf5b51512,05f0ee6e-c824-470e-9178-5ed576c6fe0c,", PlatformMask = -1, FriendlyName = "Rec Room T-Shirt (V-Neck, Orange)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "21caa68e-c3fa-474c-af5e-af1e742b7a60,,,", PlatformMask = -1, FriendlyName = "Tennis Skirt (Blue)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "21caa68e-c3fa-474c-af5e-af1e742b7a60,c5deba2a-6e35-4b13-8e94-8ba5457f39df,b75ef67d-00c3-4ac1-9b72-212032460294,", PlatformMask = -1, FriendlyName = "Tennis Skirt (Yellow)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "21caa68e-c3fa-474c-af5e-af1e742b7a60,758752bd-db2f-43d2-b580-55b3e1efffd5,b75ef67d-00c3-4ac1-9b72-212032460294,", PlatformMask = -1, FriendlyName = "Tennis Skirt (Red)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "2296ed0d-df56-4d46-b33a-aae9230a47fc,,,", PlatformMask = -1, FriendlyName = "Zipper Dress (Yellow)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,,,", PlatformMask = -1, FriendlyName = "Wristbands (White)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "71921831-ba6f-408b-a00e-2fd97663636f,,,", PlatformMask = -1, FriendlyName = "Wrist Tape (White)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "2e59d8d0-91a0-4449-bfdc-a5d663fd9343,55901f12-d5b5-4fa8-b4c8-e479689ee39d,f600037d-c9c0-43fa-b45b-02f456f9dd5f,", PlatformMask = -1, FriendlyName = "Collared Shirt (Denim)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "2e59d8d0-91a0-4449-bfdc-a5d663fd9343,bf82f2f6-9af8-431e-a296-0890dea48ba7,d015cae7-a905-49e4-8823-6dec069689a6,", PlatformMask = -1, FriendlyName = "Collared Shirt (Argyle)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "2e59d8d0-91a0-4449-bfdc-a5d663fd9343,EfdMcnfHt0mr0PQ_maaYOg,DRJcNhkqvkKFEaZpOguR6w,", PlatformMask = -1, FriendlyName = "Collared Shirt (Flowers, Green)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "7b857a8c-92ad-4028-a2c2-b3c20cdab5f2,6d703981-2734-4c45-8983-cdd5f328902f,a0271cd0-e172-4d3f-aa2f-9806f21a82d2,", PlatformMask = -1, FriendlyName = "Tank Top (Camo)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "7b857a8c-92ad-4028-a2c2-b3c20cdab5f2,5c4a2b35-0e1c-44de-8c3a-96d4a6458b1b,9c03f381-7357-4d0f-8cda-8737d4c43d25,", PlatformMask = -1, FriendlyName = "Tank Top (Rainbow)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "7b857a8c-92ad-4028-a2c2-b3c20cdab5f2,51ef8d39-2b94-4f9e-9620-07b6b0a913a5,d2a692e6-e1a9-4cfe-8154-10b52be7f8c8,", PlatformMask = -1, FriendlyName = "Jersey (Orange)", Tooltip = "", Rarity = 10 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "7b857a8c-92ad-4028-a2c2-b3c20cdab5f2,ad61c418-6d77-4a99-8ac5-9f10f5a3d42f,b292eb4b-07e3-4a48-99b5-3c6587a1e02e,", PlatformMask = -1, FriendlyName = "Tank Top (Dots)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "7b857a8c-92ad-4028-a2c2-b3c20cdab5f2,48abd952-214f-48b2-a8f1-1146f6f69aa2,b78008e8-abbd-4ece-be34-9a911f721fcc,", PlatformMask = -1, FriendlyName = "Tank Top (Zebra)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "14ef6b00-debf-4a85-9755-b4d37df496d3,8377ab96-c908-457f-9fee-b784c9a759f3,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Baseball Cap (Red)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "14ef6b00-debf-4a85-9755-b4d37df496d3,dee70c38-7a99-4c2b-9181-665f1bf75aca,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Baseball Cap (Blue)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,7d8e55fe-3c34-4b4b-9753-0021f6cc6454,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Headband (Cream)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,1b1d08f2-12ca-43dd-a44f-ea2820b919b4,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Headband (Black)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,51ef8d39-2b94-4f9e-9620-07b6b0a913a5,018a5c07-e956-457d-a540-a5e2cd68da09,", PlatformMask = -1, FriendlyName = "Headband (Orange, White)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,cbe29e9f-f2ac-47fb-97e1-8bad16abb89d,018a5c07-e956-457d-a540-a5e2cd68da09,", PlatformMask = -1, FriendlyName = "Headband (Pink, White)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,dee70c38-7a99-4c2b-9181-665f1bf75aca,018a5c07-e956-457d-a540-a5e2cd68da09,", PlatformMask = -1, FriendlyName = "Headband (Blue, White)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,6dd95046-acf8-42fe-ab78-80a334096a9d,56a92c8d-af53-413e-929e-4a9a3cfad780,", PlatformMask = -1, FriendlyName = "Headband (Red, White, Blue)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,dee70c38-7a99-4c2b-9181-665f1bf75aca,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wristbands (Blue)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,1b1d08f2-12ca-43dd-a44f-ea2820b919b4,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wristbands (Black)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,51ef8d39-2b94-4f9e-9620-07b6b0a913a5,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wristbands (Orange)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,cbe29e9f-f2ac-47fb-97e1-8bad16abb89d,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wristbands (Pink)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,8377ab96-c908-457f-9fee-b784c9a759f3,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wristbands (Red)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "fcfcaf63-deb4-45f7-b711-c051c9ea45cb,,,", PlatformMask = -1, FriendlyName = "Top Bun Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "de0ac50d-2adb-4114-bd2e-68953b13d706,,,", PlatformMask = -1, FriendlyName = "Blazer (Blue, White)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "de0ac50d-2adb-4114-bd2e-68953b13d706,6f2e74bf-1e95-463d-97db-d5d1a53b2c28,be2b9293-1d3c-4b1c-b4c5-fad3ab16cf54,", PlatformMask = -1, FriendlyName = "Blazer (Black, White)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "de0ac50d-2adb-4114-bd2e-68953b13d706,9374bf66-2ee5-493b-8439-efce4b201904,be2b9293-1d3c-4b1c-b4c5-fad3ab16cf54,", PlatformMask = -1, FriendlyName = "Blazer (Grey, Black)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "de0ac50d-2adb-4114-bd2e-68953b13d706,272fe8eb-5061-4729-a7a8-414ff667a82f,be2b9293-1d3c-4b1c-b4c5-fad3ab16cf54,", PlatformMask = -1, FriendlyName = "Blazer (Grey, White)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "de0ac50d-2adb-4114-bd2e-68953b13d706,0ffad843-d6c9-425a-8686-7217009c867e,be2b9293-1d3c-4b1c-b4c5-fad3ab16cf54,", PlatformMask = -1, FriendlyName = "Blazer (Green, Black)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "9c8fc7f0-8f99-4aad-a34f-8d979f6ae352,e0397982-c2c2-4733-9a40-46e18675b5af,dafa658e-753b-46cb-bd85-85c1de5e6ea7,", PlatformMask = -1, FriendlyName = "Button Top (Orange)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "9c8fc7f0-8f99-4aad-a34f-8d979f6ae352,,,", PlatformMask = -1, FriendlyName = "Button Top (Pink)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "9c8fc7f0-8f99-4aad-a34f-8d979f6ae352,49f5864f-9d40-497c-88c8-e87f64d41d74,dafa658e-753b-46cb-bd85-85c1de5e6ea7,", PlatformMask = -1, FriendlyName = "Button Top (Tan)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "9c8fc7f0-8f99-4aad-a34f-8d979f6ae352,c5deba2a-6e35-4b13-8e94-8ba5457f39df,dafa658e-753b-46cb-bd85-85c1de5e6ea7,", PlatformMask = -1, FriendlyName = "Button Top (Yellow)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "6d815b35-6f68-4ed4-817d-70f141e1a571,f750de46-3758-4f7d-9709-0a84b1027009,2c8924aa-68f8-4912-9759-18992f72f08a,", PlatformMask = -1, FriendlyName = "Collared Dress (Blue)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "6d815b35-6f68-4ed4-817d-70f141e1a571,d66aa400-aa5a-4539-a25d-5f8ce94dc281,2c8924aa-68f8-4912-9759-18992f72f08a,", PlatformMask = -1, FriendlyName = "Collared Dress (Green)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "6d815b35-6f68-4ed4-817d-70f141e1a571,6564acf1-4d70-4f92-92ac-08e2b76dbb6b,2c8924aa-68f8-4912-9759-18992f72f08a,", PlatformMask = -1, FriendlyName = "Collared Dress (Purple)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "6d815b35-6f68-4ed4-817d-70f141e1a571,,,", PlatformMask = -1, FriendlyName = "Collared Dress (Red)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "241506f6-bf88-4b46-b5fe-513a225421f4,,,", PlatformMask = -1, FriendlyName = "Half Up Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "6b9e022c-0b68-48fd-8eca-da8573c18900,d6edbc00-3c1d-4f49-8412-3ef8c7c5f4c2,cf119781-5bd9-4b85-9a0b-12e82e988c23,", PlatformMask = -1, FriendlyName = "Long Scarf (Blue)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "2296ed0d-df56-4d46-b33a-aae9230a47fc,6d703981-2734-4c45-8983-cdd5f328902f,cfabdefe-0890-436e-b2a3-b5c712e22955,", PlatformMask = -1, FriendlyName = "Zipper Dress (Green)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "2296ed0d-df56-4d46-b33a-aae9230a47fc,830be2fa-60a5-48cc-931f-34b670eae4bd,cfabdefe-0890-436e-b2a3-b5c712e22955,", PlatformMask = -1, FriendlyName = "Zipper Dress (Purple)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "2296ed0d-df56-4d46-b33a-aae9230a47fc,bbfa08e3-8e6b-4e0f-b264-1b398d7cd44a,cfabdefe-0890-436e-b2a3-b5c712e22955,", PlatformMask = -1, FriendlyName = "Zipper Dress (White)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,484b6c13-af22-4ad5-8c43-34c0de095d49,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wristbands (Light Blue)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,f8b0cfe8-e129-4578-8bb5-f60af5d38599,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wristbands (Green)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,67bcca75-4ab1-4964-8688-9908c464d355,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wristbands (Gold)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "7b857a8c-92ad-4028-a2c2-b3c20cdab5f2,1b1d08f2-12ca-43dd-a44f-ea2820b919b4,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Tank Top (Black)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "7b857a8c-92ad-4028-a2c2-b3c20cdab5f2,dee70c38-7a99-4c2b-9181-665f1bf75aca,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Tank Top (Blue)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "7b857a8c-92ad-4028-a2c2-b3c20cdab5f2,51ef8d39-2b94-4f9e-9620-07b6b0a913a5,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Tank Top (Orange)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "7b857a8c-92ad-4028-a2c2-b3c20cdab5f2,8377ab96-c908-457f-9fee-b784c9a759f3,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Tank Top (Red)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "6b9e022c-0b68-48fd-8eca-da8573c18900,5c4a2b35-0e1c-44de-8c3a-96d4a6458b1b,cf119781-5bd9-4b85-9a0b-12e82e988c23,", PlatformMask = -1, FriendlyName = "Long Scarf (Purple)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "6b9e022c-0b68-48fd-8eca-da8573c18900,6dd95046-acf8-42fe-ab78-80a334096a9d,cf119781-5bd9-4b85-9a0b-12e82e988c23,", PlatformMask = -1, FriendlyName = "Long Scarf (White)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,dee70c38-7a99-4c2b-9181-665f1bf75aca,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Headband (Blue)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,f8b0cfe8-e129-4578-8bb5-f60af5d38599,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Headband (Green)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,8377ab96-c908-457f-9fee-b784c9a759f3,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Headband (Red)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,,,", PlatformMask = -1, FriendlyName = "Headband (White)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,67bcca75-4ab1-4964-8688-9908c464d355,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Headband (Yellow)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "24a240f4-1574-420b-b898-a7e91f170759,,,", PlatformMask = -1, FriendlyName = "Back Bun Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "c45ed7b8-99bd-4a4b-a9ff-e16edf5d7a18,,,", PlatformMask = -1, FriendlyName = "High Pony Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "14ef6b00-debf-4a85-9755-b4d37df496d3,484b6c13-af22-4ad5-8c43-34c0de095d49,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Baseball Cap (Light Blue)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "14ef6b00-debf-4a85-9755-b4d37df496d3,1b1d08f2-12ca-43dd-a44f-ea2820b919b4,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Baseball Cap (Black)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "14ef6b00-debf-4a85-9755-b4d37df496d3,51ef8d39-2b94-4f9e-9620-07b6b0a913a5,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Baseball Cap (Orange)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "14ef6b00-debf-4a85-9755-b4d37df496d3,,,", PlatformMask = -1, FriendlyName = "Baseball Cap (White)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "14ef6b00-debf-4a85-9755-b4d37df496d3,67bcca75-4ab1-4964-8688-9908c464d355,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Baseball Cap (Yellow)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "896c2491-2f96-4986-9cbd-b3b31ef5d8c5,,,", PlatformMask = -1, FriendlyName = "Equestrian Coat (Black)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "896c2491-2f96-4986-9cbd-b3b31ef5d8c5,55901f12-d5b5-4fa8-b4c8-e479689ee39d,d344b8cc-85a8-4ace-9f92-38c84f396e99,", PlatformMask = -1, FriendlyName = "Equestrian Coat (Blue)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "896c2491-2f96-4986-9cbd-b3b31ef5d8c5,4828b50c-95b6-466a-bb25-514891d78202,d344b8cc-85a8-4ace-9f92-38c84f396e99,", PlatformMask = -1, FriendlyName = "Equestrian Coat (Grey)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "896c2491-2f96-4986-9cbd-b3b31ef5d8c5,d6823e01-69f0-4f85-b94a-74894356a2cf,d344b8cc-85a8-4ace-9f92-38c84f396e99,", PlatformMask = -1, FriendlyName = "Equestrian Coat (Maroon)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "09177621-9ecd-4f6a-b6a5-64490139141d,,,", PlatformMask = -1, FriendlyName = "Flat Top Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "95ab7a7c-c35d-4da5-9955-0921064470b6,,,", PlatformMask = -1, FriendlyName = "Gekko Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,0ecb8a2a-cffc-47db-aeda-fb0684aef1e5,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Headband (Grey)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,484b6c13-af22-4ad5-8c43-34c0de095d49,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Headband (Light Blue)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,51ef8d39-2b94-4f9e-9620-07b6b0a913a5,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Headband (Orange)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,cbe29e9f-f2ac-47fb-97e1-8bad16abb89d,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Headband (Pink)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,8377ab96-c908-457f-9fee-b784c9a759f3,018a5c07-e956-457d-a540-a5e2cd68da09,", PlatformMask = -1, FriendlyName = "Headband (Red, White)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "62ce4109-8dee-4895-bf1b-bfa143db4c7e,,,", PlatformMask = -1, FriendlyName = "Slim Blazer (Teal)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "62ce4109-8dee-4895-bf1b-bfa143db4c7e,cd5d7285-202d-42d0-b93f-04245875793e,0f36bb97-c61b-4281-929f-ff1d0d11be86,", PlatformMask = -1, FriendlyName = "Slim Blazer (Green)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "62ce4109-8dee-4895-bf1b-bfa143db4c7e,ad61c418-6d77-4a99-8ac5-9f10f5a3d42f,0f36bb97-c61b-4281-929f-ff1d0d11be86,", PlatformMask = -1, FriendlyName = "Slim Blazer (Blue)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "8b9f1413-e786-4a30-946c-9292f207875a,,,", PlatformMask = -1, FriendlyName = "Pulp Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "5cd08cfb-c729-4c30-96d9-6a99bb934d91,,,", PlatformMask = -1, FriendlyName = "Rec Room Sash", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "1a71064b-794f-40fa-9109-8ad36602b6e1,,,", PlatformMask = -1, FriendlyName = "Shagg Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "84cd594c-1cd8-4b4d-8409-85c8fd5fb02a,761a3193-60f0-4190-80c7-285b8192e794,91a451c1-b285-4c48-b14d-59ded8cc006f,", PlatformMask = -1, FriendlyName = "Stoll Dress (Blue)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "84cd594c-1cd8-4b4d-8409-85c8fd5fb02a,a819f49b-6c7a-49d3-9e6a-d9d79ef5019f,91a451c1-b285-4c48-b14d-59ded8cc006f,", PlatformMask = -1, FriendlyName = "Stoll Dress (Green)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "84cd594c-1cd8-4b4d-8409-85c8fd5fb02a,64850553-cdfe-455a-ac00-dafbe63d613e,91a451c1-b285-4c48-b14d-59ded8cc006f,", PlatformMask = -1, FriendlyName = "Stoll Dress (Orange)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "84cd594c-1cd8-4b4d-8409-85c8fd5fb02a,,,", PlatformMask = -1, FriendlyName = "Stoll Dress (Pink)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "71921831-ba6f-408b-a00e-2fd97663636f,1b1d08f2-12ca-43dd-a44f-ea2820b919b4,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wrist Tape (Black)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "71921831-ba6f-408b-a00e-2fd97663636f,7d8e55fe-3c34-4b4b-9753-0021f6cc6454,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wrist Tape (Cream)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,0ecb8a2a-cffc-47db-aeda-fb0684aef1e5,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wristbands (Grey)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,7d8e55fe-3c34-4b4b-9753-0021f6cc6454,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wristbands (Cream)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "6b9e022c-0b68-48fd-8eca-da8573c18900,,,", PlatformMask = -1, FriendlyName = "Long Scarf (Red)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "2e59d8d0-91a0-4449-bfdc-a5d663fd9343,0iSsaY-HgkmLaRHCn5vEdw,PioQ0o3yP0a6szPZ4EKs2A,", PlatformMask = -1, FriendlyName = "Collared Shirt (Blue)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "2e59d8d0-91a0-4449-bfdc-a5d663fd9343,jGj28vhq8EGwP2RuM074aQ,PioQ0o3yP0a6szPZ4EKs2A,", PlatformMask = -1, FriendlyName = "Collared Shirt (Yellow)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "2e59d8d0-91a0-4449-bfdc-a5d663fd9343,kmj5zOjcwku_WWKroCeiVQ,PioQ0o3yP0a6szPZ4EKs2A,", PlatformMask = -1, FriendlyName = "Collared Shirt (Pink)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "2e59d8d0-91a0-4449-bfdc-a5d663fd9343,FAviMCQ_EE2Mpt6QPo5OEw,PioQ0o3yP0a6szPZ4EKs2A,", PlatformMask = -1, FriendlyName = "Collared Shirt (Red)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "2e59d8d0-91a0-4449-bfdc-a5d663fd9343,MFrcSQ1DYUm8imvy4ypgvw,PioQ0o3yP0a6szPZ4EKs2A,", PlatformMask = -1, FriendlyName = "Collared Shirt (White)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "de0ac50d-2adb-4114-bd2e-68953b13d706,05ac07e1-67f0-486c-abf5-a62866475abb,be2b9293-1d3c-4b1c-b4c5-fad3ab16cf54,", PlatformMask = -1, FriendlyName = "Blazer (Black, Cream)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "0088603e-ec3b-4478-8694-e6fb1989b3f2,,,", PlatformMask = -1, FriendlyName = "Angled Bob Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "ffea7a65-613f-4835-921e-6dd15f357b7e,,,", PlatformMask = -1, FriendlyName = "Long Bangs Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "45f5e714-8a5f-4385-a97f-675066167011,,,", PlatformMask = -1, FriendlyName = "Seventies Stache", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "9bf5d259-7774-4cbe-a90f-7f188cc0dce7,,,", PlatformMask = -1, FriendlyName = "Thick Goatee", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "a6cbfe76-534a-4655-a8a8-3fed13d001c7,,,", PlatformMask = -1, FriendlyName = "Bald Top Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "CTcrvbo3OEepIV4oW8bx4w,,,", PlatformMask = -1, FriendlyName = "Receding Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "-twtjyBdQ02EAdOfBGTiEw,,,", PlatformMask = -1, FriendlyName = "Van Dyke Beard", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "45eaab67-19c2-4601-8f80-3565a4dceba4,,,", PlatformMask = -1, FriendlyName = "Pompadour Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "c855dcc3-96cb-470d-b159-d37a025a47d1,,,", PlatformMask = -1, FriendlyName = "Dutch Braid Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "d7730a9e-78a1-4356-bc09-6b066615850b,,,", PlatformMask = -1, FriendlyName = "Afro Updo Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "8c35c804-e8d5-49d2-8d5a-ea19fb70bfa6,,,", PlatformMask = -1, FriendlyName = "Pencil Bun Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "5beeb4c4-f276-4eae-87aa-9302e45b05b7,,,", PlatformMask = -1, FriendlyName = "Cornrows Hair", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "b6rLwzD4NkKV7xKn9ZYVkA,sxUE0iOSZEmezm54T7xI3Q,tlpa7195x0CkmSjpR1RArQ,", PlatformMask = -1, FriendlyName = "Rec Room Hoodie - Pride (Rainbow Pride)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "fe15ca53-c5b8-4acf-9309-ff3f4e610fc9,,,", PlatformMask = -1, FriendlyName = "Winged Hat - Pride (Rainbow Pride)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "b6rLwzD4NkKV7xKn9ZYVkA,D_Xmo0rOzkS-kgq1CYXt3g,tnCJp2eDI0SwjVfJMhk3LQ,", PlatformMask = -1, FriendlyName = "Rec Room Hoodie - Pride (Trans Pride)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "fe15ca53-c5b8-4acf-9309-ff3f4e610fc9,knXPidb-Rkayfc3kSHfZeQ,1yMyo6oTjU-VAygoeWaohQ,", PlatformMask = -1, FriendlyName = "Winged Hat - Pride (Trans Pride)", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "88b6ddeb-a455-460d-91d9-a4569ef6903c,,,", PlatformMask = -1, FriendlyName = "Square Earrings ", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "0abb6b08-20ce-444f-879e-0d1344df096c,,,", PlatformMask = -1, FriendlyName = "Round Earrings", Tooltip = "", Rarity = 0 },
|
||||||
|
new { AvatarItemType = 0, AvatarItemDesc = "9b5bde11-7408-4798-9fcb-c7ec175444df,,,", PlatformMask = -1, FriendlyName = "Hoop Earrings", Tooltip = "", Rarity = 0 }
|
||||||
|
};
|
||||||
|
|
||||||
if (!ids.Any())
|
var allItems = ownedItems.Cast<object>().Concat(defaultItems).ToList();
|
||||||
return Results.Json(new List<object>());
|
|
||||||
|
|
||||||
var reputations = ids.Select(id => new
|
return Results.Json(allItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("avatar/v2")]
|
||||||
|
public async Task<IResult> GetAvatar(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
|
var accountId = _jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(accountId))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
if (!int.TryParse(accountId.AsSpan(), out var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var avatar = await db.PlayerAvatars
|
||||||
|
.FirstOrDefaultAsync(a => a.OwnerAccountId == id);
|
||||||
|
|
||||||
|
if (avatar == null)
|
||||||
|
{
|
||||||
|
avatar = new PlayerAvatar
|
||||||
{
|
{
|
||||||
AccountId = id,
|
OwnerAccountId = id,
|
||||||
Noteriety = 0,
|
OutfitSelections = "",
|
||||||
CheerGeneral = 0,
|
FaceFeatures = "{}",
|
||||||
CheerHelpful = 0,
|
SkinColor = "",
|
||||||
CheerCreative = 0,
|
HairColor = ""
|
||||||
CheerGreatHost = 0,
|
|
||||||
CheerSportsman = 0,
|
|
||||||
CheerCredit = 20,
|
|
||||||
SelectedCheer = (object?)null
|
|
||||||
}).ToList();
|
|
||||||
|
|
||||||
return Results.Json(reputations);*/
|
|
||||||
|
|
||||||
// TODO: implement real endpoint from grabbing from db
|
|
||||||
var json = File.ReadAllText("JSON/bulkprogression.json");
|
|
||||||
return Results.Content(json, "application/json");
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapPost("/api/players/v1/progression/bulk", async (HttpRequest httpRequest, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var ids = await ParseFormIds(httpRequest);
|
|
||||||
|
|
||||||
if (!ids.Any())
|
|
||||||
return Results.Json(new List<PlayerProgressionBulkResponse>());
|
|
||||||
|
|
||||||
var progressions = await db.PlayerProgressions
|
|
||||||
.Where(p => ids.Contains(p.PlayerId))
|
|
||||||
.Select(p => new PlayerProgressionBulkResponse { PlayerId = p.PlayerId, Level = p.Level, Xp = p.Xp })
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
return Results.Json(progressions);
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapPost("/api/v1/progression/bulk", async (HttpRequest httpRequest, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var ids = await ParseFormIds(httpRequest);
|
|
||||||
|
|
||||||
if (!ids.Any())
|
|
||||||
return Results.Json(new List<PlayerProgressionBulkResponse>());
|
|
||||||
|
|
||||||
var progressions = await db.PlayerProgressions
|
|
||||||
.Where(p => ids.Contains(p.PlayerId))
|
|
||||||
.Select(p => new PlayerProgressionBulkResponse { PlayerId = p.PlayerId, Level = p.Level, Xp = p.Xp })
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
return Results.Json(progressions);
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapGet("/api/avatar/v4/items", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var ownedItems = await db.AvatarItems
|
|
||||||
.Where(i => i.OwnerAccountId == id)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
var defaultItems = new List<object>
|
|
||||||
{
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "5d13a7a2-8213-40e6-90a6-efdd76a3fdcb,,,", PlatformMask = -1, FriendlyName = "Flowing Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "1d27b674-f9e2-4ffc-9d8c-a58a1be06457,,,", PlatformMask = -1, FriendlyName = "Afro Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "d84c0ff9-8fbe-4ed8-abf3-7996e81888ab,,,", PlatformMask = -1, FriendlyName = "Large Afro Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "e5b83dfc-b2e1-4dcb-a4ab-9d3a4c8a34ae,,,", PlatformMask = -1, FriendlyName = "Long Wavy Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "7dd6f7b0-7ba0-429f-a04f-e32d3a79ee61,,,", PlatformMask = -1, FriendlyName = "Short Wavy Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "eb9611c6-bb50-41a2-93e9-7f959815a846,,,", PlatformMask = -1, FriendlyName = "Dreads Long Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "1fd69ef8-0b74-4962-af5a-67f0bf0358f2,,,", PlatformMask = -1, FriendlyName = "Ponytail Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "a12f724f-4a73-4ab8-aad4-6bfc662b4dd6,,,", PlatformMask = -1, FriendlyName = "Undercut Long Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "0753d7a4-8247-4fca-a6fc-359c26086140,,,", PlatformMask = -1, FriendlyName = "Fonzie Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "77d3c585-4928-4471-a425-89036efe7299,,,", PlatformMask = -1, FriendlyName = "Spiky Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "92302d9d-c527-418c-ac5d-1fa869727505,,,", PlatformMask = -1, FriendlyName = "Part Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "f9dd08f8-16d3-4c39-af4f-89f7bb6e80d3,,,", PlatformMask = -1, FriendlyName = "Undercut Short Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "b148cb1e-df81-442f-aea6-ab1727aad00e,,,", PlatformMask = -1, FriendlyName = "Chunky Afro Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "e36bcd98-7e85-43fa-89f8-57e4ec33823a,,,", PlatformMask = -1, FriendlyName = "Bob with Bangs Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "880a3cc0-7407-4b61-b759-f9dd890fe9e5,,,", PlatformMask = -1, FriendlyName = "Bob Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "21599b51-c50f-43d8-ac5f-62c30cd02ca5,,,", PlatformMask = -1, FriendlyName = "Lori Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "193a3bf9-abc0-4d78-8d63-92046908b1c5,,,", PlatformMask = -1, FriendlyName = "Emo Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "79b90274-6eec-4664-acfb-4a123334661e,,,", PlatformMask = -1, FriendlyName = "Pig Tails Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "da4e7b34-2095-4a9e-801e-4f409039e0dd,,,", PlatformMask = -1, FriendlyName = "Buzz Cut Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "9d9fadb6-97eb-480e-a224-4e0179082071,,,", PlatformMask = -1, FriendlyName = "Meatball Buns Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "d8280c0c-d803-4513-be10-a0ba96d8821e,,,", PlatformMask = -1, FriendlyName = "Flowhawk Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "e286863c-2967-4d00-b837-b49487b9484a,,,", PlatformMask = -1, FriendlyName = "Fauxhawk Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "2cb4f372-3372-4583-8b57-c4e3988e3c28,,,", PlatformMask = -1, FriendlyName = "Punky Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "06306723-ca20-4aa6-b7b3-917113f41ac3,,,", PlatformMask = -1, FriendlyName = "Cat-Eye Glasses (Red)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "c70005d5-6276-4a98-acb3-6a77bc19379a,,,", PlatformMask = -1, FriendlyName = "Glasses (Teal)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "8d10cc78-6b00-45f3-affb-205e9cc5b03f,,,", PlatformMask = -1, FriendlyName = "Beard (Close)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "cc96f8a5-bc5b-4f89-83b7-ecd53905ada7,,,", PlatformMask = -1, FriendlyName = "Beard (Thick)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "c6c08eb5-381a-4193-9722-80da95d62abe,,,", PlatformMask = -1, FriendlyName = "Business Tie (Black)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "4d507dfa-4a99-4ac0-8537-229e9dc0eb4a,,,", PlatformMask = -1, FriendlyName = "Rec Room Tank Top (Orange)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "d0a9262f-5504-46a7-bb10-7507503db58e,,,", PlatformMask = -1, FriendlyName = "Rec Room Shirt (Crew Neck, White)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "d0a9262f-5504-46a7-bb10-7507503db58e,95e4cc30-cb68-473d-a395-feadf5b51512,0440f08f-ef1d-49d8-942b-523056e8bb45,", PlatformMask = -1, FriendlyName = "Rec Room T-Shirt (Crew Neck, Orange)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "2e59d8d0-91a0-4449-bfdc-a5d663fd9343,,,", PlatformMask = -1, FriendlyName = "Collared Shirt (Plaid, Blue)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "7b857a8c-92ad-4028-a2c2-b3c20cdab5f2,,,", PlatformMask = -1, FriendlyName = "T-Shirt", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "8aa79563-ace1-4ba7-ad0c-f3210a78142f,,,", PlatformMask = -1, FriendlyName = "Rec Room Shirt (V-Neck, White)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "8aa79563-ace1-4ba7-ad0c-f3210a78142f,95e4cc30-cb68-473d-a395-feadf5b51512,05f0ee6e-c824-470e-9178-5ed576c6fe0c,", PlatformMask = -1, FriendlyName = "Rec Room T-Shirt (V-Neck, Orange)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "21caa68e-c3fa-474c-af5e-af1e742b7a60,,,", PlatformMask = -1, FriendlyName = "Tennis Skirt (Blue)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "21caa68e-c3fa-474c-af5e-af1e742b7a60,c5deba2a-6e35-4b13-8e94-8ba5457f39df,b75ef67d-00c3-4ac1-9b72-212032460294,", PlatformMask = -1, FriendlyName = "Tennis Skirt (Yellow)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "21caa68e-c3fa-474c-af5e-af1e742b7a60,758752bd-db2f-43d2-b580-55b3e1efffd5,b75ef67d-00c3-4ac1-9b72-212032460294,", PlatformMask = -1, FriendlyName = "Tennis Skirt (Red)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "2296ed0d-df56-4d46-b33a-aae9230a47fc,,,", PlatformMask = -1, FriendlyName = "Zipper Dress (Yellow)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,,,", PlatformMask = -1, FriendlyName = "Wristbands (White)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "71921831-ba6f-408b-a00e-2fd97663636f,,,", PlatformMask = -1, FriendlyName = "Wrist Tape (White)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "2e59d8d0-91a0-4449-bfdc-a5d663fd9343,55901f12-d5b5-4fa8-b4c8-e479689ee39d,f600037d-c9c0-43fa-b45b-02f456f9dd5f,", PlatformMask = -1, FriendlyName = "Collared Shirt (Denim)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "2e59d8d0-91a0-4449-bfdc-a5d663fd9343,bf82f2f6-9af8-431e-a296-0890dea48ba7,d015cae7-a905-49e4-8823-6dec069689a6,", PlatformMask = -1, FriendlyName = "Collared Shirt (Argyle)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "2e59d8d0-91a0-4449-bfdc-a5d663fd9343,EfdMcnfHt0mr0PQ_maaYOg,DRJcNhkqvkKFEaZpOguR6w,", PlatformMask = -1, FriendlyName = "Collared Shirt (Flowers, Green)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "7b857a8c-92ad-4028-a2c2-b3c20cdab5f2,6d703981-2734-4c45-8983-cdd5f328902f,a0271cd0-e172-4d3f-aa2f-9806f21a82d2,", PlatformMask = -1, FriendlyName = "Tank Top (Camo)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "7b857a8c-92ad-4028-a2c2-b3c20cdab5f2,5c4a2b35-0e1c-44de-8c3a-96d4a6458b1b,9c03f381-7357-4d0f-8cda-8737d4c43d25,", PlatformMask = -1, FriendlyName = "Tank Top (Rainbow)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "7b857a8c-92ad-4028-a2c2-b3c20cdab5f2,51ef8d39-2b94-4f9e-9620-07b6b0a913a5,d2a692e6-e1a9-4cfe-8154-10b52be7f8c8,", PlatformMask = -1, FriendlyName = "Jersey (Orange)", Tooltip = "", Rarity = 10 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "7b857a8c-92ad-4028-a2c2-b3c20cdab5f2,ad61c418-6d77-4a99-8ac5-9f10f5a3d42f,b292eb4b-07e3-4a48-99b5-3c6587a1e02e,", PlatformMask = -1, FriendlyName = "Tank Top (Dots)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "7b857a8c-92ad-4028-a2c2-b3c20cdab5f2,48abd952-214f-48b2-a8f1-1146f6f69aa2,b78008e8-abbd-4ece-be34-9a911f721fcc,", PlatformMask = -1, FriendlyName = "Tank Top (Zebra)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "14ef6b00-debf-4a85-9755-b4d37df496d3,8377ab96-c908-457f-9fee-b784c9a759f3,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Baseball Cap (Red)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "14ef6b00-debf-4a85-9755-b4d37df496d3,dee70c38-7a99-4c2b-9181-665f1bf75aca,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Baseball Cap (Blue)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,7d8e55fe-3c34-4b4b-9753-0021f6cc6454,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Headband (Cream)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,1b1d08f2-12ca-43dd-a44f-ea2820b919b4,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Headband (Black)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,51ef8d39-2b94-4f9e-9620-07b6b0a913a5,018a5c07-e956-457d-a540-a5e2cd68da09,", PlatformMask = -1, FriendlyName = "Headband (Orange, White)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,cbe29e9f-f2ac-47fb-97e1-8bad16abb89d,018a5c07-e956-457d-a540-a5e2cd68da09,", PlatformMask = -1, FriendlyName = "Headband (Pink, White)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,dee70c38-7a99-4c2b-9181-665f1bf75aca,018a5c07-e956-457d-a540-a5e2cd68da09,", PlatformMask = -1, FriendlyName = "Headband (Blue, White)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,6dd95046-acf8-42fe-ab78-80a334096a9d,56a92c8d-af53-413e-929e-4a9a3cfad780,", PlatformMask = -1, FriendlyName = "Headband (Red, White, Blue)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,dee70c38-7a99-4c2b-9181-665f1bf75aca,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wristbands (Blue)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,1b1d08f2-12ca-43dd-a44f-ea2820b919b4,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wristbands (Black)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,51ef8d39-2b94-4f9e-9620-07b6b0a913a5,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wristbands (Orange)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,cbe29e9f-f2ac-47fb-97e1-8bad16abb89d,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wristbands (Pink)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,8377ab96-c908-457f-9fee-b784c9a759f3,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wristbands (Red)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "fcfcaf63-deb4-45f7-b711-c051c9ea45cb,,,", PlatformMask = -1, FriendlyName = "Top Bun Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "de0ac50d-2adb-4114-bd2e-68953b13d706,,,", PlatformMask = -1, FriendlyName = "Blazer (Blue, White)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "de0ac50d-2adb-4114-bd2e-68953b13d706,6f2e74bf-1e95-463d-97db-d5d1a53b2c28,be2b9293-1d3c-4b1c-b4c5-fad3ab16cf54,", PlatformMask = -1, FriendlyName = "Blazer (Black, White)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "de0ac50d-2adb-4114-bd2e-68953b13d706,9374bf66-2ee5-493b-8439-efce4b201904,be2b9293-1d3c-4b1c-b4c5-fad3ab16cf54,", PlatformMask = -1, FriendlyName = "Blazer (Grey, Black)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "de0ac50d-2adb-4114-bd2e-68953b13d706,272fe8eb-5061-4729-a7a8-414ff667a82f,be2b9293-1d3c-4b1c-b4c5-fad3ab16cf54,", PlatformMask = -1, FriendlyName = "Blazer (Grey, White)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "de0ac50d-2adb-4114-bd2e-68953b13d706,0ffad843-d6c9-425a-8686-7217009c867e,be2b9293-1d3c-4b1c-b4c5-fad3ab16cf54,", PlatformMask = -1, FriendlyName = "Blazer (Green, Black)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "9c8fc7f0-8f99-4aad-a34f-8d979f6ae352,e0397982-c2c2-4733-9a40-46e18675b5af,dafa658e-753b-46cb-bd85-85c1de5e6ea7,", PlatformMask = -1, FriendlyName = "Button Top (Orange)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "9c8fc7f0-8f99-4aad-a34f-8d979f6ae352,,,", PlatformMask = -1, FriendlyName = "Button Top (Pink)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "9c8fc7f0-8f99-4aad-a34f-8d979f6ae352,49f5864f-9d40-497c-88c8-e87f64d41d74,dafa658e-753b-46cb-bd85-85c1de5e6ea7,", PlatformMask = -1, FriendlyName = "Button Top (Tan)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "9c8fc7f0-8f99-4aad-a34f-8d979f6ae352,c5deba2a-6e35-4b13-8e94-8ba5457f39df,dafa658e-753b-46cb-bd85-85c1de5e6ea7,", PlatformMask = -1, FriendlyName = "Button Top (Yellow)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "6d815b35-6f68-4ed4-817d-70f141e1a571,f750de46-3758-4f7d-9709-0a84b1027009,2c8924aa-68f8-4912-9759-18992f72f08a,", PlatformMask = -1, FriendlyName = "Collared Dress (Blue)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "6d815b35-6f68-4ed4-817d-70f141e1a571,d66aa400-aa5a-4539-a25d-5f8ce94dc281,2c8924aa-68f8-4912-9759-18992f72f08a,", PlatformMask = -1, FriendlyName = "Collared Dress (Green)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "6d815b35-6f68-4ed4-817d-70f141e1a571,6564acf1-4d70-4f92-92ac-08e2b76dbb6b,2c8924aa-68f8-4912-9759-18992f72f08a,", PlatformMask = -1, FriendlyName = "Collared Dress (Purple)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "6d815b35-6f68-4ed4-817d-70f141e1a571,,,", PlatformMask = -1, FriendlyName = "Collared Dress (Red)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "241506f6-bf88-4b46-b5fe-513a225421f4,,,", PlatformMask = -1, FriendlyName = "Half Up Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "6b9e022c-0b68-48fd-8eca-da8573c18900,d6edbc00-3c1d-4f49-8412-3ef8c7c5f4c2,cf119781-5bd9-4b85-9a0b-12e82e988c23,", PlatformMask = -1, FriendlyName = "Long Scarf (Blue)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "2296ed0d-df56-4d46-b33a-aae9230a47fc,6d703981-2734-4c45-8983-cdd5f328902f,cfabdefe-0890-436e-b2a3-b5c712e22955,", PlatformMask = -1, FriendlyName = "Zipper Dress (Green)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "2296ed0d-df56-4d46-b33a-aae9230a47fc,830be2fa-60a5-48cc-931f-34b670eae4bd,cfabdefe-0890-436e-b2a3-b5c712e22955,", PlatformMask = -1, FriendlyName = "Zipper Dress (Purple)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "2296ed0d-df56-4d46-b33a-aae9230a47fc,bbfa08e3-8e6b-4e0f-b264-1b398d7cd44a,cfabdefe-0890-436e-b2a3-b5c712e22955,", PlatformMask = -1, FriendlyName = "Zipper Dress (White)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,484b6c13-af22-4ad5-8c43-34c0de095d49,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wristbands (Light Blue)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,f8b0cfe8-e129-4578-8bb5-f60af5d38599,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wristbands (Green)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,67bcca75-4ab1-4964-8688-9908c464d355,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wristbands (Gold)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "7b857a8c-92ad-4028-a2c2-b3c20cdab5f2,1b1d08f2-12ca-43dd-a44f-ea2820b919b4,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Tank Top (Black)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "7b857a8c-92ad-4028-a2c2-b3c20cdab5f2,dee70c38-7a99-4c2b-9181-665f1bf75aca,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Tank Top (Blue)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "7b857a8c-92ad-4028-a2c2-b3c20cdab5f2,51ef8d39-2b94-4f9e-9620-07b6b0a913a5,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Tank Top (Orange)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "7b857a8c-92ad-4028-a2c2-b3c20cdab5f2,8377ab96-c908-457f-9fee-b784c9a759f3,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Tank Top (Red)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "6b9e022c-0b68-48fd-8eca-da8573c18900,5c4a2b35-0e1c-44de-8c3a-96d4a6458b1b,cf119781-5bd9-4b85-9a0b-12e82e988c23,", PlatformMask = -1, FriendlyName = "Long Scarf (Purple)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "6b9e022c-0b68-48fd-8eca-da8573c18900,6dd95046-acf8-42fe-ab78-80a334096a9d,cf119781-5bd9-4b85-9a0b-12e82e988c23,", PlatformMask = -1, FriendlyName = "Long Scarf (White)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,dee70c38-7a99-4c2b-9181-665f1bf75aca,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Headband (Blue)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,f8b0cfe8-e129-4578-8bb5-f60af5d38599,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Headband (Green)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,8377ab96-c908-457f-9fee-b784c9a759f3,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Headband (Red)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,,,", PlatformMask = -1, FriendlyName = "Headband (White)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,67bcca75-4ab1-4964-8688-9908c464d355,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Headband (Yellow)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "24a240f4-1574-420b-b898-a7e91f170759,,,", PlatformMask = -1, FriendlyName = "Back Bun Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "c45ed7b8-99bd-4a4b-a9ff-e16edf5d7a18,,,", PlatformMask = -1, FriendlyName = "High Pony Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "14ef6b00-debf-4a85-9755-b4d37df496d3,484b6c13-af22-4ad5-8c43-34c0de095d49,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Baseball Cap (Light Blue)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "14ef6b00-debf-4a85-9755-b4d37df496d3,1b1d08f2-12ca-43dd-a44f-ea2820b919b4,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Baseball Cap (Black)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "14ef6b00-debf-4a85-9755-b4d37df496d3,51ef8d39-2b94-4f9e-9620-07b6b0a913a5,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Baseball Cap (Orange)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "14ef6b00-debf-4a85-9755-b4d37df496d3,,,", PlatformMask = -1, FriendlyName = "Baseball Cap (White)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "14ef6b00-debf-4a85-9755-b4d37df496d3,67bcca75-4ab1-4964-8688-9908c464d355,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Baseball Cap (Yellow)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "896c2491-2f96-4986-9cbd-b3b31ef5d8c5,,,", PlatformMask = -1, FriendlyName = "Equestrian Coat (Black)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "896c2491-2f96-4986-9cbd-b3b31ef5d8c5,55901f12-d5b5-4fa8-b4c8-e479689ee39d,d344b8cc-85a8-4ace-9f92-38c84f396e99,", PlatformMask = -1, FriendlyName = "Equestrian Coat (Blue)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "896c2491-2f96-4986-9cbd-b3b31ef5d8c5,4828b50c-95b6-466a-bb25-514891d78202,d344b8cc-85a8-4ace-9f92-38c84f396e99,", PlatformMask = -1, FriendlyName = "Equestrian Coat (Grey)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "896c2491-2f96-4986-9cbd-b3b31ef5d8c5,d6823e01-69f0-4f85-b94a-74894356a2cf,d344b8cc-85a8-4ace-9f92-38c84f396e99,", PlatformMask = -1, FriendlyName = "Equestrian Coat (Maroon)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "09177621-9ecd-4f6a-b6a5-64490139141d,,,", PlatformMask = -1, FriendlyName = "Flat Top Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "95ab7a7c-c35d-4da5-9955-0921064470b6,,,", PlatformMask = -1, FriendlyName = "Gekko Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,0ecb8a2a-cffc-47db-aeda-fb0684aef1e5,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Headband (Grey)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,484b6c13-af22-4ad5-8c43-34c0de095d49,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Headband (Light Blue)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,51ef8d39-2b94-4f9e-9620-07b6b0a913a5,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Headband (Orange)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,cbe29e9f-f2ac-47fb-97e1-8bad16abb89d,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Headband (Pink)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "40528de7-38a3-4a7c-8f93-6d3bfa5573f2,8377ab96-c908-457f-9fee-b784c9a759f3,018a5c07-e956-457d-a540-a5e2cd68da09,", PlatformMask = -1, FriendlyName = "Headband (Red, White)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "62ce4109-8dee-4895-bf1b-bfa143db4c7e,,,", PlatformMask = -1, FriendlyName = "Slim Blazer (Teal)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "62ce4109-8dee-4895-bf1b-bfa143db4c7e,cd5d7285-202d-42d0-b93f-04245875793e,0f36bb97-c61b-4281-929f-ff1d0d11be86,", PlatformMask = -1, FriendlyName = "Slim Blazer (Green)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "62ce4109-8dee-4895-bf1b-bfa143db4c7e,ad61c418-6d77-4a99-8ac5-9f10f5a3d42f,0f36bb97-c61b-4281-929f-ff1d0d11be86,", PlatformMask = -1, FriendlyName = "Slim Blazer (Blue)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "8b9f1413-e786-4a30-946c-9292f207875a,,,", PlatformMask = -1, FriendlyName = "Pulp Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "5cd08cfb-c729-4c30-96d9-6a99bb934d91,,,", PlatformMask = -1, FriendlyName = "Rec Room Sash", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "1a71064b-794f-40fa-9109-8ad36602b6e1,,,", PlatformMask = -1, FriendlyName = "Shagg Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "84cd594c-1cd8-4b4d-8409-85c8fd5fb02a,761a3193-60f0-4190-80c7-285b8192e794,91a451c1-b285-4c48-b14d-59ded8cc006f,", PlatformMask = -1, FriendlyName = "Stoll Dress (Blue)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "84cd594c-1cd8-4b4d-8409-85c8fd5fb02a,a819f49b-6c7a-49d3-9e6a-d9d79ef5019f,91a451c1-b285-4c48-b14d-59ded8cc006f,", PlatformMask = -1, FriendlyName = "Stoll Dress (Green)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "84cd594c-1cd8-4b4d-8409-85c8fd5fb02a,64850553-cdfe-455a-ac00-dafbe63d613e,91a451c1-b285-4c48-b14d-59ded8cc006f,", PlatformMask = -1, FriendlyName = "Stoll Dress (Orange)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "84cd594c-1cd8-4b4d-8409-85c8fd5fb02a,,,", PlatformMask = -1, FriendlyName = "Stoll Dress (Pink)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "71921831-ba6f-408b-a00e-2fd97663636f,1b1d08f2-12ca-43dd-a44f-ea2820b919b4,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wrist Tape (Black)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "71921831-ba6f-408b-a00e-2fd97663636f,7d8e55fe-3c34-4b4b-9753-0021f6cc6454,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wrist Tape (Cream)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,0ecb8a2a-cffc-47db-aeda-fb0684aef1e5,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wristbands (Grey)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "ecc1dbe6-ca06-4564-b2a6-30956194d1e9,7d8e55fe-3c34-4b4b-9753-0021f6cc6454,0b2395e1-ebcc-47e9-aaf1-faf9e9cec4cd,", PlatformMask = -1, FriendlyName = "Wristbands (Cream)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "6b9e022c-0b68-48fd-8eca-da8573c18900,,,", PlatformMask = -1, FriendlyName = "Long Scarf (Red)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "2e59d8d0-91a0-4449-bfdc-a5d663fd9343,0iSsaY-HgkmLaRHCn5vEdw,PioQ0o3yP0a6szPZ4EKs2A,", PlatformMask = -1, FriendlyName = "Collared Shirt (Blue)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "2e59d8d0-91a0-4449-bfdc-a5d663fd9343,jGj28vhq8EGwP2RuM074aQ,PioQ0o3yP0a6szPZ4EKs2A,", PlatformMask = -1, FriendlyName = "Collared Shirt (Yellow)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "2e59d8d0-91a0-4449-bfdc-a5d663fd9343,kmj5zOjcwku_WWKroCeiVQ,PioQ0o3yP0a6szPZ4EKs2A,", PlatformMask = -1, FriendlyName = "Collared Shirt (Pink)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "2e59d8d0-91a0-4449-bfdc-a5d663fd9343,FAviMCQ_EE2Mpt6QPo5OEw,PioQ0o3yP0a6szPZ4EKs2A,", PlatformMask = -1, FriendlyName = "Collared Shirt (Red)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "2e59d8d0-91a0-4449-bfdc-a5d663fd9343,MFrcSQ1DYUm8imvy4ypgvw,PioQ0o3yP0a6szPZ4EKs2A,", PlatformMask = -1, FriendlyName = "Collared Shirt (White)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "de0ac50d-2adb-4114-bd2e-68953b13d706,05ac07e1-67f0-486c-abf5-a62866475abb,be2b9293-1d3c-4b1c-b4c5-fad3ab16cf54,", PlatformMask = -1, FriendlyName = "Blazer (Black, Cream)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "0088603e-ec3b-4478-8694-e6fb1989b3f2,,,", PlatformMask = -1, FriendlyName = "Angled Bob Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "ffea7a65-613f-4835-921e-6dd15f357b7e,,,", PlatformMask = -1, FriendlyName = "Long Bangs Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "45f5e714-8a5f-4385-a97f-675066167011,,,", PlatformMask = -1, FriendlyName = "Seventies Stache", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "9bf5d259-7774-4cbe-a90f-7f188cc0dce7,,,", PlatformMask = -1, FriendlyName = "Thick Goatee", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "a6cbfe76-534a-4655-a8a8-3fed13d001c7,,,", PlatformMask = -1, FriendlyName = "Bald Top Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "CTcrvbo3OEepIV4oW8bx4w,,,", PlatformMask = -1, FriendlyName = "Receding Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "-twtjyBdQ02EAdOfBGTiEw,,,", PlatformMask = -1, FriendlyName = "Van Dyke Beard", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "45eaab67-19c2-4601-8f80-3565a4dceba4,,,", PlatformMask = -1, FriendlyName = "Pompadour Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "c855dcc3-96cb-470d-b159-d37a025a47d1,,,", PlatformMask = -1, FriendlyName = "Dutch Braid Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "d7730a9e-78a1-4356-bc09-6b066615850b,,,", PlatformMask = -1, FriendlyName = "Afro Updo Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "8c35c804-e8d5-49d2-8d5a-ea19fb70bfa6,,,", PlatformMask = -1, FriendlyName = "Pencil Bun Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "5beeb4c4-f276-4eae-87aa-9302e45b05b7,,,", PlatformMask = -1, FriendlyName = "Cornrows Hair", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "b6rLwzD4NkKV7xKn9ZYVkA,sxUE0iOSZEmezm54T7xI3Q,tlpa7195x0CkmSjpR1RArQ,", PlatformMask = -1, FriendlyName = "Rec Room Hoodie - Pride (Rainbow Pride)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "fe15ca53-c5b8-4acf-9309-ff3f4e610fc9,,,", PlatformMask = -1, FriendlyName = "Winged Hat - Pride (Rainbow Pride)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "b6rLwzD4NkKV7xKn9ZYVkA,D_Xmo0rOzkS-kgq1CYXt3g,tnCJp2eDI0SwjVfJMhk3LQ,", PlatformMask = -1, FriendlyName = "Rec Room Hoodie - Pride (Trans Pride)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "fe15ca53-c5b8-4acf-9309-ff3f4e610fc9,knXPidb-Rkayfc3kSHfZeQ,1yMyo6oTjU-VAygoeWaohQ,", PlatformMask = -1, FriendlyName = "Winged Hat - Pride (Trans Pride)", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "88b6ddeb-a455-460d-91d9-a4569ef6903c,,,", PlatformMask = -1, FriendlyName = "Square Earrings ", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "0abb6b08-20ce-444f-879e-0d1344df096c,,,", PlatformMask = -1, FriendlyName = "Round Earrings", Tooltip = "", Rarity = 0 },
|
|
||||||
new { AvatarItemType = 0, AvatarItemDesc = "9b5bde11-7408-4798-9fcb-c7ec175444df,,,", PlatformMask = -1, FriendlyName = "Hoop Earrings", Tooltip = "", Rarity = 0 }
|
|
||||||
};
|
};
|
||||||
|
db.PlayerAvatars.Add(avatar);
|
||||||
var allItems = ownedItems.Cast<object>().Concat(defaultItems).ToList();
|
|
||||||
|
|
||||||
return Results.Json(allItems);
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapGet("/api/avatar/v2", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var avatar = await db.PlayerAvatars
|
|
||||||
.FirstOrDefaultAsync(a => a.OwnerAccountId == id);
|
|
||||||
|
|
||||||
if (avatar == null)
|
|
||||||
{
|
|
||||||
avatar = new PlayerAvatar
|
|
||||||
{
|
|
||||||
OwnerAccountId = id,
|
|
||||||
OutfitSelections = "",
|
|
||||||
FaceFeatures = "{}",
|
|
||||||
SkinColor = "",
|
|
||||||
HairColor = ""
|
|
||||||
};
|
|
||||||
db.PlayerAvatars.Add(avatar);
|
|
||||||
await db.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Results.Json(new
|
|
||||||
{
|
|
||||||
OutfitSelections = avatar.OutfitSelections,
|
|
||||||
FaceFeatures = avatar.FaceFeatures,
|
|
||||||
SkinColor = avatar.SkinColor,
|
|
||||||
HairColor = avatar.HairColor
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapPost("/api/avatar/v2/set", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
request.EnableBuffering();
|
|
||||||
var avatarUpdate = await System.Text.Json.JsonSerializer.DeserializeAsync<PlayerAvatar>(request.Body);
|
|
||||||
|
|
||||||
if (avatarUpdate == null)
|
|
||||||
return Results.BadRequest();
|
|
||||||
|
|
||||||
var avatar = await db.PlayerAvatars
|
|
||||||
.FirstOrDefaultAsync(a => a.OwnerAccountId == id);
|
|
||||||
|
|
||||||
if (avatar == null)
|
|
||||||
{
|
|
||||||
avatar = new PlayerAvatar { OwnerAccountId = id };
|
|
||||||
db.PlayerAvatars.Add(avatar);
|
|
||||||
}
|
|
||||||
|
|
||||||
avatar.OutfitSelections = avatarUpdate.OutfitSelections;
|
|
||||||
avatar.FaceFeatures = avatarUpdate.FaceFeatures;
|
|
||||||
avatar.SkinColor = avatarUpdate.SkinColor;
|
|
||||||
avatar.HairColor = avatarUpdate.HairColor;
|
|
||||||
|
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
return Results.Ok(avatar);
|
}
|
||||||
});
|
|
||||||
|
|
||||||
app.MapGet("/api/avatar/v3/saved", async (HttpRequest request, AppDbContext db) =>
|
return Results.Json(new
|
||||||
{
|
{
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
OutfitSelections = avatar.OutfitSelections,
|
||||||
|
FaceFeatures = avatar.FaceFeatures,
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
SkinColor = avatar.SkinColor,
|
||||||
return Results.Unauthorized();
|
HairColor = avatar.HairColor
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
request.EnableBuffering();
|
|
||||||
|
|
||||||
var items = await db.SavedOutfits
|
|
||||||
.Where(i => i.OwnerAccountId == id)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
return Results.Json(items);
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
app.MapGet("/api/PlayerReporting/v1/moderationBlockDetails", () =>
|
[HttpPost("avatar/v2/set")]
|
||||||
Results.Content("{\"ReportCategory\":0,\"Duration\":0,\"GameSessionId\":0,\"IsHostKick\":false,\"Message\":\"\",\"PlayerIdReporter\":null,\"IsBan\":false}", "application/json"));
|
public async Task<IResult> SetAvatar(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
app.MapGet("/api/PlayerReporting/v1/voteToKickReasons", async (HttpRequest request, AppDbContext db) =>
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
|
var accountId = _jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(accountId))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
if (!int.TryParse(accountId.AsSpan(), out var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
request.EnableBuffering();
|
||||||
|
var avatarUpdate = await System.Text.Json.JsonSerializer.DeserializeAsync<PlayerAvatar>(request.Body);
|
||||||
|
|
||||||
|
if (avatarUpdate == null)
|
||||||
|
return Results.BadRequest();
|
||||||
|
|
||||||
|
var avatar = await db.PlayerAvatars
|
||||||
|
.FirstOrDefaultAsync(a => a.OwnerAccountId == id);
|
||||||
|
|
||||||
|
if (avatar == null)
|
||||||
{
|
{
|
||||||
var json = File.ReadAllText("JSON/vtkreasons.json");
|
avatar = new PlayerAvatar { OwnerAccountId = id };
|
||||||
return Results.Content(json, "application/json");
|
db.PlayerAvatars.Add(avatar);
|
||||||
});
|
}
|
||||||
|
|
||||||
app.MapGet("/api/settings/v2" +
|
avatar.OutfitSelections = avatarUpdate.OutfitSelections;
|
||||||
"", async (HttpRequest request, AppDbContext db) =>
|
avatar.FaceFeatures = avatarUpdate.FaceFeatures;
|
||||||
|
avatar.SkinColor = avatarUpdate.SkinColor;
|
||||||
|
avatar.HairColor = avatarUpdate.HairColor;
|
||||||
|
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
return Results.Ok(avatar);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("avatar/v3/saved")]
|
||||||
|
public async Task<IResult> GetSavedOutfits(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
|
var accountId = _jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(accountId))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
if (!int.TryParse(accountId.AsSpan(), out var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
request.EnableBuffering();
|
||||||
|
|
||||||
|
var items = await db.SavedOutfits
|
||||||
|
.Where(i => i.OwnerAccountId == id)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return Results.Json(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("PlayerReporting/v1/moderationBlockDetails")]
|
||||||
|
public IResult GetModerationBlockDetails() =>
|
||||||
|
Results.Content("{\"ReportCategory\":0,\"Duration\":0,\"GameSessionId\":0,\"IsHostKick\":false,\"Message\":\"\",\"PlayerIdReporter\":null,\"IsBan\":false}", "application/json");
|
||||||
|
|
||||||
|
[HttpGet("PlayerReporting/v1/voteToKickReasons")]
|
||||||
|
public async Task<IResult> GetVoteToKickReasons(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
var json = System.IO.File.ReadAllText("JSON/vtkreasons.json");
|
||||||
|
return Results.Content(json, "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("settings/v2")]
|
||||||
|
public async Task<IResult> GetSettings(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
|
var accountId = _jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(accountId))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
if (!int.TryParse(accountId.AsSpan(), out var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var settings = await db.PlayerSettings
|
||||||
|
.Where(s => s.PlayerId == id)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
if (!settings.Any())
|
||||||
{
|
{
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
var defaults = new List<PlayerSetting>
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var settings = await db.PlayerSettings
|
|
||||||
.Where(s => s.PlayerId == id)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
if (!settings.Any())
|
|
||||||
{
|
{
|
||||||
var defaults = new List<PlayerSetting>
|
new() { PlayerId = id, Key = "Recroom.OOBE", Value = "77" },
|
||||||
{
|
new() { PlayerId = id, Key = "SplitTestAssignedSegments", Value = "1|{\"SplitTesting+PhotonMaxDatagrams_2021_01_11\":\"Off\",\"SplitTesting+Curated_Rooms_2020_08_06\":\"Off\",\"SplitTesting+RoomRecommendationsType_2020_08_14\":\"Aug14MinVisitors35000\"}" },
|
||||||
new() { PlayerId = id, Key = "Recroom.OOBE", Value = "77" },
|
new() { PlayerId = id, Key = "PlayerSessionCount", Value = "13" },
|
||||||
new() { PlayerId = id, Key = "SplitTestAssignedSegments", Value = "1|{\"SplitTesting+PhotonMaxDatagrams_2021_01_11\":\"Off\",\"SplitTesting+Curated_Rooms_2020_08_06\":\"Off\",\"SplitTesting+RoomRecommendationsType_2020_08_14\":\"Aug14MinVisitors35000\"}" },
|
new() { PlayerId = id, Key = "TUTORIAL_COMPLETE_MASK", Value = "11" },
|
||||||
new() { PlayerId = id, Key = "PlayerSessionCount", Value = "13" },
|
new() { PlayerId = id, Key = "BACKPACK_FAVORITE_TOOL", Value = "1" },
|
||||||
new() { PlayerId = id, Key = "TUTORIAL_COMPLETE_MASK", Value = "11" },
|
new() { PlayerId = id, Key = "VoiceChat", Value = "2" },
|
||||||
new() { PlayerId = id, Key = "BACKPACK_FAVORITE_TOOL", Value = "1" },
|
new() { PlayerId = id, Key = "VRAUTOSPRINT", Value = "1" },
|
||||||
new() { PlayerId = id, Key = "VoiceChat", Value = "2" },
|
new() { PlayerId = id, Key = "VR_MOVEMENT_MODE", Value = "0" },
|
||||||
new() { PlayerId = id, Key = "VRAUTOSPRINT", Value = "1" },
|
new() { PlayerId = id, Key = "COMFORT_SPRINT", Value = "0" },
|
||||||
new() { PlayerId = id, Key = "VR_MOVEMENT_MODE", Value = "0" },
|
new() { PlayerId = id, Key = "COMFORT_WALK", Value = "0" },
|
||||||
new() { PlayerId = id, Key = "COMFORT_SPRINT", Value = "0" },
|
new() { PlayerId = id, Key = "COMFORT_VEHICLES", Value = "0" },
|
||||||
new() { PlayerId = id, Key = "COMFORT_WALK", Value = "0" },
|
new() { PlayerId = id, Key = "COMFORT_FLY", Value = "0" },
|
||||||
new() { PlayerId = id, Key = "COMFORT_VEHICLES", Value = "0" },
|
new() { PlayerId = id, Key = "COMFORT_ROTATE", Value = "0" },
|
||||||
new() { PlayerId = id, Key = "COMFORT_FLY", Value = "0" },
|
new() { PlayerId = id, Key = "COMFORT_FORCES", Value = "0" },
|
||||||
new() { PlayerId = id, Key = "COMFORT_ROTATE", Value = "0" },
|
new() { PlayerId = id, Key = "COMFORT_FALL", Value = "0" },
|
||||||
new() { PlayerId = id, Key = "COMFORT_FORCES", Value = "0" },
|
new() { PlayerId = id, Key = "COMFORT_TELEPORT", Value = "0" },
|
||||||
new() { PlayerId = id, Key = "COMFORT_FALL", Value = "0" },
|
new() { PlayerId = id, Key = "ROTATE_IN_PLACE_ENABLED", Value = "1" },
|
||||||
new() { PlayerId = id, Key = "COMFORT_TELEPORT", Value = "0" },
|
new() { PlayerId = id, Key = "ROTATION_INCREMENT", Value = "2" },
|
||||||
new() { PlayerId = id, Key = "ROTATE_IN_PLACE_ENABLED", Value = "1" },
|
new() { PlayerId = id, Key = "CONTINUOUS_ROTATION_MODE", Value = "1" },
|
||||||
new() { PlayerId = id, Key = "ROTATION_INCREMENT", Value = "2" },
|
new() { PlayerId = id, Key = "DONT_LOCK_TOOLS_TO_HAND", Value = "0" },
|
||||||
new() { PlayerId = id, Key = "CONTINUOUS_ROTATION_MODE", Value = "1" },
|
new() { PlayerId = id, Key = "QualitySettings", Value = "2" },
|
||||||
new() { PlayerId = id, Key = "DONT_LOCK_TOOLS_TO_HAND", Value = "0" },
|
new() { PlayerId = id, Key = "TeleportBuffer", Value = "0" },
|
||||||
new() { PlayerId = id, Key = "QualitySettings", Value = "2" },
|
new() { PlayerId = id, Key = "IgnoreBuffer", Value = "1" },
|
||||||
new() { PlayerId = id, Key = "TeleportBuffer", Value = "0" },
|
new() { PlayerId = id, Key = "FIRST_TIME_IN_FLAGS", Value = "0" },
|
||||||
new() { PlayerId = id, Key = "IgnoreBuffer", Value = "1" },
|
new() { PlayerId = id, Key = "ShowRoomCenter", Value = "1" },
|
||||||
new() { PlayerId = id, Key = "FIRST_TIME_IN_FLAGS", Value = "0" },
|
new() { PlayerId = id, Key = "USER_TRACKING", Value = "1" },
|
||||||
new() { PlayerId = id, Key = "ShowRoomCenter", Value = "1" },
|
new() { PlayerId = id, Key = "STABILIZE_HANDS", Value = "0" },
|
||||||
new() { PlayerId = id, Key = "USER_TRACKING", Value = "1" },
|
new() { PlayerId = id, Key = "MakerPen_SnappingMode", Value = "2" },
|
||||||
new() { PlayerId = id, Key = "STABILIZE_HANDS", Value = "0" },
|
new() { PlayerId = id, Key = "Recroom.ChallengeMap", Value = "17" },
|
||||||
new() { PlayerId = id, Key = "MakerPen_SnappingMode", Value = "2" },
|
new() { PlayerId = id, Key = "VoiceFilter2", Value = "1" },
|
||||||
new() { PlayerId = id, Key = "Recroom.ChallengeMap", Value = "17" },
|
new() { PlayerId = id, Key = "SFX_VOLUME_PERCENT_PREF", Value = "1" },
|
||||||
new() { PlayerId = id, Key = "VoiceFilter2", Value = "1" },
|
};
|
||||||
new() { PlayerId = id, Key = "SFX_VOLUME_PERCENT_PREF", Value = "1" },
|
db.PlayerSettings.AddRange(defaults);
|
||||||
};
|
|
||||||
db.PlayerSettings.AddRange(defaults);
|
|
||||||
await db.SaveChangesAsync();
|
|
||||||
settings = defaults;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Results.Json(settings);
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapPost("/api/settings/v2/set", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
request.EnableBuffering();
|
|
||||||
request.Body.Position = 0;
|
|
||||||
using var reader = new StreamReader(request.Body);
|
|
||||||
var body = await reader.ReadToEndAsync();
|
|
||||||
|
|
||||||
Console.WriteLine($"Settings request body: {body}");
|
|
||||||
|
|
||||||
var settings = new List<PlayerSetting>();
|
|
||||||
|
|
||||||
if (body.TrimStart().StartsWith("["))
|
|
||||||
{
|
|
||||||
settings = System.Text.Json.JsonSerializer.Deserialize<List<PlayerSetting>>(body) ?? [];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var single = System.Text.Json.JsonSerializer.Deserialize<PlayerSetting>(body);
|
|
||||||
if (single != null) settings.Add(single);
|
|
||||||
}
|
|
||||||
|
|
||||||
settings = settings.Where(s => !string.IsNullOrEmpty(s.Key)).ToList();
|
|
||||||
|
|
||||||
if (!settings.Any())
|
|
||||||
return Results.Ok();
|
|
||||||
|
|
||||||
db.PlayerSettings.RemoveRange(db.PlayerSettings.Where(s => s.PlayerId == id));
|
|
||||||
|
|
||||||
foreach (var setting in settings)
|
|
||||||
{
|
|
||||||
setting.PlayerId = id;
|
|
||||||
setting.Key = setting.Key ?? "";
|
|
||||||
setting.Value = setting.Value ?? "";
|
|
||||||
db.PlayerSettings.Add(setting);
|
|
||||||
}
|
|
||||||
|
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
settings = defaults;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Results.Json(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("settings/v2/set")]
|
||||||
|
public async Task<IResult> SetSettings(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
|
var accountId = _jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(accountId))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
if (!int.TryParse(accountId.AsSpan(), out var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
request.EnableBuffering();
|
||||||
|
request.Body.Position = 0;
|
||||||
|
using var reader = new StreamReader(request.Body);
|
||||||
|
var body = await reader.ReadToEndAsync();
|
||||||
|
|
||||||
|
Console.WriteLine($"Settings request body: {body}");
|
||||||
|
|
||||||
|
var settings = new List<PlayerSetting>();
|
||||||
|
|
||||||
|
if (body.TrimStart().StartsWith("["))
|
||||||
|
{
|
||||||
|
settings = System.Text.Json.JsonSerializer.Deserialize<List<PlayerSetting>>(body) ?? [];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var single = System.Text.Json.JsonSerializer.Deserialize<PlayerSetting>(body);
|
||||||
|
if (single != null) settings.Add(single);
|
||||||
|
}
|
||||||
|
|
||||||
|
settings = settings.Where(s => !string.IsNullOrEmpty(s.Key)).ToList();
|
||||||
|
|
||||||
|
if (!settings.Any())
|
||||||
return Results.Ok();
|
return Results.Ok();
|
||||||
});
|
|
||||||
|
|
||||||
app.MapGet("/api/equipment/v2/getUnlocked", async (HttpRequest request, AppDbContext db) =>
|
db.PlayerSettings.RemoveRange(db.PlayerSettings.Where(s => s.PlayerId == id));
|
||||||
|
|
||||||
|
foreach (var setting in settings)
|
||||||
{
|
{
|
||||||
// TODO ADD FUNCTIONALITY
|
setting.PlayerId = id;
|
||||||
return "[]";
|
setting.Key = setting.Key ?? "";
|
||||||
});
|
setting.Value = setting.Value ?? "";
|
||||||
app.MapGet("/api/consumables/v2/getUnlocked", async (HttpRequest request, AppDbContext db, JwtTokenService jwtService) =>
|
db.PlayerSettings.Add(setting);
|
||||||
|
}
|
||||||
|
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
return Results.Ok();
|
||||||
|
}
|
||||||
|
[HttpGet("equipment/v2/getUnlocked")]
|
||||||
|
public async Task<IResult> GetUnlockedEquipment(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
// TODO ADD FUNCTIONALITY
|
||||||
|
return Results.Content("[]", "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("consumables/v2/getUnlocked")]
|
||||||
|
public async Task<IResult> GetUnlockedConsumables(HttpRequest request, AppDbContext db, JwtTokenService jwtService)
|
||||||
|
{
|
||||||
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
|
var accountId = jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var consumables = await db.ConsumableItems
|
||||||
|
.Where(c => c.OwnerAccountId == id)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return Results.Json(consumables);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("objectives/v1/myprogress")]
|
||||||
|
public async Task<IResult> GetMyProgress(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
// TODO ADD FUNCTIONALITY
|
||||||
|
var json = System.IO.File.ReadAllText("JSON/tempmyprogress.json");
|
||||||
|
return Results.Content(json, "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("avatar/v2/gifts")]
|
||||||
|
public async Task<IResult> GetAvatarGifts(HttpRequest request, AppDbContext db, JwtTokenService jwtService)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
@@ -533,573 +591,363 @@ public class APIController
|
|||||||
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out var id))
|
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out var id))
|
||||||
return Results.Unauthorized();
|
return Results.Unauthorized();
|
||||||
|
|
||||||
var consumables = await db.ConsumableItems
|
// Get all pending (unconsumed) gifts for this player
|
||||||
.Where(c => c.OwnerAccountId == id)
|
var pendingGifts = await db.ReceivedGifts
|
||||||
|
.Where(rg => rg.ReceiverAccountId == id && !rg.IsConsumed)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
return Results.Json(consumables);
|
return Results.Json(pendingGifts);
|
||||||
});
|
}
|
||||||
app.MapGet("/api/objectives/v1/myprogress", async (HttpRequest request, AppDbContext db) =>
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// TODO ADD FUNCTIONALITY
|
return Results.Problem($"Error retrieving gifts: {ex.Message}");
|
||||||
var json = File.ReadAllText("JSON/tempmyprogress.json");
|
}
|
||||||
return Results.Content(json, "application/json");
|
}
|
||||||
});
|
|
||||||
app.MapGet("/api/avatar/v2/gifts", async (HttpRequest request, AppDbContext db, JwtTokenService jwtService) =>
|
[HttpGet("gamerewards/v1/pending")]
|
||||||
|
public async Task<IResult> GetPendingGameRewards(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
// TODO ADD FUNCTIONALITY
|
||||||
|
return Results.Content("[]", "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("communityboard/v2/current")]
|
||||||
|
public async Task<IResult> GetCommunityBoard(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
var json = System.IO.File.ReadAllText("JSON/communityboard.json");
|
||||||
|
return Results.Content(json, "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("playerevents/v1/all")]
|
||||||
|
public async Task<IResult> GetPlayerEvents(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
// TODO ADD FUNCTIONALITY
|
||||||
|
return Results.Content("{\"Created\":[],\"Responses\":[]}", "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("CampusCard/v1/UpdateAndGetSubscription")]
|
||||||
|
public async Task<IResult> UpdateAndGetSubscription(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
return Results.Json(new { subscription = (object?)null, platformAccountSubscribedPlayerId = (object?)null });
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("storefronts/v4/balance/2")]
|
||||||
|
public async Task<IResult> GetBalance(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
|
var accountId = _jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(accountId))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
if (!int.TryParse(accountId.AsSpan(), out var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var balance = await db.TokenBalances
|
||||||
|
.Where(s => s.Id == id)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return Results.Json(balance);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("storefronts/v1/p2p/betaEnabled")]
|
||||||
|
public async Task<IResult> GetP2PBetaEnabled(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
return Results.Content("false", "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("announcement/v1/get")]
|
||||||
|
public async Task<IResult> GetAnnouncement(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
var json = System.IO.File.ReadAllText("JSON/announcements.json");
|
||||||
|
return Results.Content(json, "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("roomkeys/v1/mine")]
|
||||||
|
public async Task<IResult> GetMyRoomKeys(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
// TODO ADD FUNCTIONALITY
|
||||||
|
return Results.Content("[]", "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("quickPlay/v1/getandclear")]
|
||||||
|
public async Task<IResult> GetQuickPlay(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
// TODO ADD FUNCTIONALITY
|
||||||
|
return Results.Content("{\"RoomName\":null,\"ActionCode\":null,\"TargetPlayerId\":null}", "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("roomkeys/v1/room")]
|
||||||
|
public async Task<IResult> GetRoomKeys(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
// TODO ADD FUNCTIONALITY
|
||||||
|
var roomid = request.Query["roomId"];
|
||||||
|
return Results.Content("[]", "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("accounts/v1/getBio")]
|
||||||
|
public async Task<IResult> GetBio(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
|
var accountId = _jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var bio = await db.PlayerBios
|
||||||
|
.Where(s => accountId == accountId)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return Results.Json(bio);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("accounts/v1/forplatformids")]
|
||||||
|
public async Task<IResult> ForPlatformIds(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
request.EnableBuffering();
|
||||||
|
request.Body.Position = 0;
|
||||||
|
using var reader = new StreamReader(request.Body);
|
||||||
|
var body = await reader.ReadToEndAsync();
|
||||||
|
|
||||||
|
var ids = new List<string>();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(body))
|
||||||
{
|
{
|
||||||
try
|
foreach (var pair in body.Split('&'))
|
||||||
{
|
{
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
var keyValue = pair.Split('=');
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
if (keyValue.Length == 2 && keyValue[0] == "Ids")
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
// Get all pending (unconsumed) gifts for this player
|
|
||||||
var pendingGifts = await db.ReceivedGifts
|
|
||||||
.Where(rg => rg.ReceiverAccountId == id && !rg.IsConsumed)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
return Results.Json(pendingGifts);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return Results.Problem($"Error retrieving gifts: {ex.Message}");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
app.MapGet("/api/gamerewards/v1/pending", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
// TODO ADD FUNCTIONALITY
|
|
||||||
return "[]";
|
|
||||||
});
|
|
||||||
app.MapGet("/api/communityboard/v2/current", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var json = File.ReadAllText("JSON/communityboard.json");
|
|
||||||
return Results.Content(json, "application/json");
|
|
||||||
});
|
|
||||||
app.MapGet("/api/playerevents/v1/all", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
// TODO ADD FUNCTIONALITY
|
|
||||||
return Results.Content("{\"Created\":[],\"Responses\":[]}", "application/json");
|
|
||||||
});
|
|
||||||
app.MapPost("/api/CampusCard/v1/UpdateAndGetSubscription", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
return Results.Json(new { subscription = (object?)null, platformAccountSubscribedPlayerId = (object?)null });
|
|
||||||
});
|
|
||||||
app.MapGet("/api/storefronts/v4/balance/2", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var balance = await db.TokenBalances
|
|
||||||
.Where(s => s.Id == id)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
return Results.Json(balance);
|
|
||||||
});
|
|
||||||
app.MapGet("/api/storefronts/v1/p2p/betaEnabled", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
return "false";
|
|
||||||
});
|
|
||||||
app.MapGet("/api/announcement/v1/get", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var json = File.ReadAllText("JSON/announcements.json");
|
|
||||||
return Results.Content(json, "application/json");
|
|
||||||
});
|
|
||||||
app.MapGet("/api/roomkeys/v1/mine", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
// TODO ADD FUNCTIONALITY
|
|
||||||
return "[]";
|
|
||||||
});
|
|
||||||
app.MapGet("/api/quickPlay/v1/getandclear", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
// TODO ADD FUNCTIONALITY
|
|
||||||
return Results.Content("{\"RoomName\":null,\"ActionCode\":null,\"TargetPlayerId\":null}", "application/json");
|
|
||||||
});
|
|
||||||
app.MapGet("/api/roomkeys/v1/room", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
// TODO ADD FUNCTIONALITY
|
|
||||||
var roomid = request.Query["roomId"];
|
|
||||||
return "[]";
|
|
||||||
});
|
|
||||||
app.MapGet("/api/accounts/v1/getBio", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var bio = await db.PlayerBios
|
|
||||||
.Where(s => accountId == accountId)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
return Results.Json(bio);
|
|
||||||
});
|
|
||||||
app.MapPost("/api/accounts/v1/forplatformids", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
request.EnableBuffering();
|
|
||||||
request.Body.Position = 0;
|
|
||||||
using var reader = new StreamReader(request.Body);
|
|
||||||
var body = await reader.ReadToEndAsync();
|
|
||||||
|
|
||||||
var ids = new List<string>();
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(body))
|
|
||||||
{
|
|
||||||
foreach (var pair in body.Split('&'))
|
|
||||||
{
|
{
|
||||||
var keyValue = pair.Split('=');
|
var idString = Uri.UnescapeDataString(keyValue[1]);
|
||||||
if (keyValue.Length == 2 && keyValue[0] == "Ids")
|
ids = idString.Split(',').ToList();
|
||||||
{
|
break;
|
||||||
var idString = Uri.UnescapeDataString(keyValue[1]);
|
|
||||||
ids = idString.Split(',').ToList();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var results = new List<object>();
|
var results = new List<object>();
|
||||||
foreach (var platformId in ids)
|
foreach (var platformId in ids)
|
||||||
|
{
|
||||||
|
var cachedLogin = await db.CachedLogins.FirstOrDefaultAsync(c => c.PlatformID == platformId);
|
||||||
|
if (cachedLogin != null)
|
||||||
{
|
{
|
||||||
var cachedLogin = await db.CachedLogins.FirstOrDefaultAsync(c => c.PlatformID == platformId);
|
results.Add(new { accountId = cachedLogin.AccountId, platformId = platformId });
|
||||||
if (cachedLogin != null)
|
|
||||||
{
|
|
||||||
results.Add(new { accountId = cachedLogin.AccountId, platformId = platformId });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Results.Json(results);
|
return Results.Json(results);
|
||||||
});
|
}
|
||||||
app.MapGet("/api/storefronts/v3/giftdropstore/3", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
|
[HttpGet("storefronts/v3/giftdropstore/3")]
|
||||||
|
public async Task<IResult> GetGiftDropStore3(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
var storefronts = await _storefrontService.GetStorefrontsAsync();
|
||||||
|
var storefront = storefronts.FirstOrDefault(s => s.StorefrontType == 2 && s.Name == "watch_store");
|
||||||
|
if (storefront == null)
|
||||||
{
|
{
|
||||||
var storefronts = await storefrontService.GetStorefrontsAsync();
|
var json = System.IO.File.ReadAllText("JSON/storefront3.json");
|
||||||
var storefront = storefronts.FirstOrDefault(s => s.StorefrontType == 2 && s.Name == "watch_store");
|
|
||||||
if (storefront == null)
|
|
||||||
{
|
|
||||||
var json = File.ReadAllText("JSON/storefront3.json");
|
|
||||||
return Results.Content(json, "application/json");
|
|
||||||
}
|
|
||||||
var storeItems = storefront.Items.Select(item => new
|
|
||||||
{
|
|
||||||
item.Id,
|
|
||||||
item.StorefrontId,
|
|
||||||
item.PurchasableItemId,
|
|
||||||
item.Type,
|
|
||||||
item.IsFeatured,
|
|
||||||
item.NewUntil,
|
|
||||||
GiftDrops = item.GiftDrops.Select(gd => new
|
|
||||||
{
|
|
||||||
gd.Id,
|
|
||||||
gd.StorefrontItemId,
|
|
||||||
gd.GiftDropId,
|
|
||||||
gd.FriendlyName,
|
|
||||||
gd.Tooltip,
|
|
||||||
gd.ConsumableItemDesc,
|
|
||||||
gd.AvatarItemDesc,
|
|
||||||
gd.AvatarItemType,
|
|
||||||
gd.EquipmentPrefabName,
|
|
||||||
gd.EquipmentModificationGuid,
|
|
||||||
gd.IsQuery,
|
|
||||||
gd.Unique,
|
|
||||||
gd.SubscribersOnly,
|
|
||||||
gd.Level,
|
|
||||||
gd.Rarity,
|
|
||||||
gd.CurrencyType,
|
|
||||||
gd.Currency,
|
|
||||||
gd.Context,
|
|
||||||
gd.ItemSetId,
|
|
||||||
gd.ItemSetFriendlyName
|
|
||||||
}).ToList(),
|
|
||||||
Prices = item.Prices.Select(p => new
|
|
||||||
{
|
|
||||||
p.Id,
|
|
||||||
p.StorefrontItemId,
|
|
||||||
p.CurrencyType,
|
|
||||||
p.Price
|
|
||||||
}).ToList()
|
|
||||||
}).ToList();
|
|
||||||
var response = new { storefront.Id, storefront.Name, storefront.StorefrontType, storefront.NextUpdate, StoreItems = storeItems };
|
|
||||||
return Results.Ok(response);
|
|
||||||
});
|
|
||||||
app.MapGet("/api/challenge/v2/getCurrent", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var json = File.ReadAllText("JSON/weeklychallenge.json");
|
|
||||||
return Results.Content(json, "application/json");
|
return Results.Content(json, "application/json");
|
||||||
//return "{}";
|
}
|
||||||
});
|
var storeItems = storefront.Items.Select(item => new
|
||||||
app.MapGet("/roomserver/rooms/bulk", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
{
|
||||||
var idParam = request.Query["id"].FirstOrDefault();
|
item.Id,
|
||||||
var nameParam = request.Query["name"].FirstOrDefault();
|
item.StorefrontId,
|
||||||
|
item.PurchasableItemId,
|
||||||
if (string.IsNullOrEmpty(idParam) && string.IsNullOrEmpty(nameParam))
|
item.Type,
|
||||||
return Results.BadRequest("Either 'id' or 'name' query parameter is required");
|
item.IsFeatured,
|
||||||
|
item.NewUntil,
|
||||||
List<Room> results = new();
|
GiftDrops = item.GiftDrops.Select(gd => new
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(idParam))
|
|
||||||
{
|
{
|
||||||
var ids = idParam.Split(',').Select(s => int.TryParse(s.Trim(), out var i) ? i : -1).Where(i => i != -1);
|
gd.Id,
|
||||||
results.AddRange(db.Rooms.Where(r => ids.Contains(r.RoomId)).ToList());
|
gd.StorefrontItemId,
|
||||||
}
|
gd.GiftDropId,
|
||||||
|
gd.FriendlyName,
|
||||||
if (!string.IsNullOrEmpty(nameParam))
|
gd.Tooltip,
|
||||||
|
gd.ConsumableItemDesc,
|
||||||
|
gd.AvatarItemDesc,
|
||||||
|
gd.AvatarItemType,
|
||||||
|
gd.EquipmentPrefabName,
|
||||||
|
gd.EquipmentModificationGuid,
|
||||||
|
gd.IsQuery,
|
||||||
|
gd.Unique,
|
||||||
|
gd.SubscribersOnly,
|
||||||
|
gd.Level,
|
||||||
|
gd.Rarity,
|
||||||
|
gd.CurrencyType,
|
||||||
|
gd.Currency,
|
||||||
|
gd.Context,
|
||||||
|
gd.ItemSetId,
|
||||||
|
gd.ItemSetFriendlyName
|
||||||
|
}).ToList(),
|
||||||
|
Prices = item.Prices.Select(p => new
|
||||||
{
|
{
|
||||||
var names = nameParam.Split(',').Select(s => s.Trim().ToLower()).Where(s => !string.IsNullOrEmpty(s));
|
p.Id,
|
||||||
results.AddRange(db.Rooms.Where(r => names.Any(n => r.Name.ToLower().Contains(n))).ToList());
|
p.StorefrontItemId,
|
||||||
}
|
p.CurrencyType,
|
||||||
|
p.Price
|
||||||
|
}).ToList()
|
||||||
|
}).ToList();
|
||||||
|
var response = new { storefront.Id, storefront.Name, storefront.StorefrontType, storefront.NextUpdate, StoreItems = storeItems };
|
||||||
|
return Results.Ok(response);
|
||||||
|
}
|
||||||
|
|
||||||
var roomIds = results.Select(r => r.RoomId).ToList();
|
[HttpGet("challenge/v2/getCurrent")]
|
||||||
|
public async Task<IResult> GetCurrentChallenge(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
var json = System.IO.File.ReadAllText("JSON/weeklychallenge.json");
|
||||||
|
return Results.Content(json, "application/json");
|
||||||
|
//return "{}";
|
||||||
|
}
|
||||||
|
|
||||||
if (roomIds.Count == 0)
|
[HttpGet("/roomserver/rooms/bulk")]
|
||||||
|
public async Task<IResult> GetBulkRooms(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
var idParam = request.Query["id"].FirstOrDefault();
|
||||||
|
var nameParam = request.Query["name"].FirstOrDefault();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(idParam) && string.IsNullOrEmpty(nameParam))
|
||||||
|
return Results.BadRequest("Either 'id' or 'name' query parameter is required");
|
||||||
|
|
||||||
|
List<Room> results = new();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(idParam))
|
||||||
|
{
|
||||||
|
var ids = idParam.Split(',').Select(s => int.TryParse(s.Trim(), out var i) ? i : -1).Where(i => i != -1);
|
||||||
|
results.AddRange(db.Rooms.Where(r => ids.Contains(r.RoomId)).ToList());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(nameParam))
|
||||||
|
{
|
||||||
|
var names = nameParam.Split(',').Select(s => s.Trim().ToLower()).Where(s => !string.IsNullOrEmpty(s));
|
||||||
|
results.AddRange(db.Rooms.Where(r => names.Any(n => r.Name.ToLower().Contains(n))).ToList());
|
||||||
|
}
|
||||||
|
|
||||||
|
var roomIds = results.Select(r => r.RoomId).ToList();
|
||||||
|
|
||||||
|
if (roomIds.Count == 0)
|
||||||
|
{
|
||||||
|
return Results.Json(new object[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
var subRooms = db.SubRooms.Where(s => roomIds.Contains(s.RoomId)).ToList();
|
||||||
|
var roles = db.RoomRoles.Where(r => roomIds.Contains(r.RoomId)).ToList();
|
||||||
|
var loadScreens = db.LoadScreens.Where(l => roomIds.Contains(l.RoomId)).ToList();
|
||||||
|
var promoImages = db.PromoImages.Where(p => roomIds.Contains(p.RoomId)).ToList();
|
||||||
|
var promoExternalContents = db.PromoExternalContents.Where(p => roomIds.Contains(p.RoomId)).ToList();
|
||||||
|
|
||||||
|
var response = results.Distinct().Select(r => new
|
||||||
|
{
|
||||||
|
r.RoomId,
|
||||||
|
r.Name,
|
||||||
|
r.Description,
|
||||||
|
r.CreatorAccountId,
|
||||||
|
r.ImageName,
|
||||||
|
r.State,
|
||||||
|
r.Accessibility,
|
||||||
|
r.SupportsLevelVoting,
|
||||||
|
r.IsRRO,
|
||||||
|
r.IsDorm,
|
||||||
|
r.CloningAllowed,
|
||||||
|
r.SupportsVRLow,
|
||||||
|
r.SupportsQuest2,
|
||||||
|
r.SupportsMobile,
|
||||||
|
r.SupportsScreens,
|
||||||
|
r.SupportsWalkVR,
|
||||||
|
r.SupportsTeleportVR,
|
||||||
|
r.SupportsJuniors,
|
||||||
|
r.MinLevel,
|
||||||
|
r.WarningMask,
|
||||||
|
r.CustomWarning,
|
||||||
|
r.DisableMicAutoMute,
|
||||||
|
r.DisableRoomComments,
|
||||||
|
r.EncryptVoiceChat,
|
||||||
|
r.CreatedAt,
|
||||||
|
Stats = new { CheerCount = 0, FavoriteCount = 0, VisitorCount = 0, VisitCount = 0 },
|
||||||
|
SubRooms = subRooms.Where(s => s.RoomId == r.RoomId).Select(s => new
|
||||||
{
|
{
|
||||||
return Results.Json(new object[0]);
|
s.SubRoomId,
|
||||||
}
|
s.Name,
|
||||||
|
s.DataBlob,
|
||||||
var subRooms = db.SubRooms.Where(s => roomIds.Contains(s.RoomId)).ToList();
|
s.IsSandbox,
|
||||||
var roles = db.RoomRoles.Where(r => roomIds.Contains(r.RoomId)).ToList();
|
s.MaxPlayers,
|
||||||
var loadScreens = db.LoadScreens.Where(l => roomIds.Contains(l.RoomId)).ToList();
|
s.Accessibility,
|
||||||
var promoImages = db.PromoImages.Where(p => roomIds.Contains(p.RoomId)).ToList();
|
s.UnitySceneId,
|
||||||
var promoExternalContents = db.PromoExternalContents.Where(p => roomIds.Contains(p.RoomId)).ToList();
|
DataSavedAt = s.DataSavedAt
|
||||||
|
}).ToList(),
|
||||||
var response = results.Distinct().Select(r => new
|
Roles = roles.Where(ro => ro.RoomId == r.RoomId).Select(ro => new
|
||||||
{
|
{
|
||||||
r.RoomId,
|
ro.AccountId,
|
||||||
r.Name,
|
ro.Role,
|
||||||
r.Description,
|
ro.InvitedRole
|
||||||
r.CreatorAccountId,
|
}).ToList(),
|
||||||
r.ImageName,
|
LoadScreens = loadScreens.Where(l => l.RoomId == r.RoomId).Select(l => new
|
||||||
r.State,
|
{
|
||||||
r.Accessibility,
|
l.ImageUrl,
|
||||||
r.SupportsLevelVoting,
|
l.Tooltip,
|
||||||
r.IsRRO,
|
l.IsThumbnail
|
||||||
r.IsDorm,
|
}).ToList(),
|
||||||
r.CloningAllowed,
|
PromoImages = promoImages.Where(p => p.RoomId == r.RoomId).Select(p => new
|
||||||
r.SupportsVRLow,
|
{
|
||||||
r.SupportsQuest2,
|
p.ImageUrl,
|
||||||
r.SupportsMobile,
|
p.Tooltip,
|
||||||
r.SupportsScreens,
|
p.SortOrder
|
||||||
r.SupportsWalkVR,
|
}).ToList(),
|
||||||
r.SupportsTeleportVR,
|
PromoExternalContent = promoExternalContents.Where(p => p.RoomId == r.RoomId).Select(p => new
|
||||||
r.SupportsJuniors,
|
{
|
||||||
r.MinLevel,
|
p.Type,
|
||||||
r.WarningMask,
|
p.Url,
|
||||||
r.CustomWarning,
|
p.Tooltip
|
||||||
r.DisableMicAutoMute,
|
}).ToList(),
|
||||||
r.DisableRoomComments,
|
Tags = new object[0]
|
||||||
r.EncryptVoiceChat,
|
}).ToList();
|
||||||
r.CreatedAt,
|
|
||||||
Stats = new { CheerCount = 0, FavoriteCount = 0, VisitorCount = 0, VisitCount = 0 },
|
return Results.Json(response);
|
||||||
SubRooms = subRooms.Where(s => s.RoomId == r.RoomId).Select(s => new
|
}
|
||||||
{
|
|
||||||
s.SubRoomId,
|
[HttpGet("/roomserver/rooms/hot")]
|
||||||
s.Name,
|
public async Task<IResult> GetHotRooms(HttpRequest request, AppDbContext db)
|
||||||
s.DataBlob,
|
{
|
||||||
s.IsSandbox,
|
var tagFilter = request.Query["tag"].FirstOrDefault()?.ToLower();
|
||||||
s.MaxPlayers,
|
|
||||||
s.Accessibility,
|
var allRooms = await db.Rooms.ToListAsync();
|
||||||
s.UnitySceneId,
|
|
||||||
DataSavedAt = s.DataSavedAt
|
if (!string.IsNullOrEmpty(tagFilter))
|
||||||
}).ToList(),
|
{
|
||||||
Roles = roles.Where(ro => ro.RoomId == r.RoomId).Select(ro => new
|
allRooms = allRooms.Where(r =>
|
||||||
{
|
{
|
||||||
ro.AccountId,
|
var roomTags = TryDeserializeRoomTags(r.Tags);
|
||||||
ro.Role,
|
if (roomTags == null || roomTags.Length == 0) return false;
|
||||||
ro.InvitedRole
|
|
||||||
}).ToList(),
|
return roomTags.Any(t => t.Tag.Equals(tagFilter, StringComparison.OrdinalIgnoreCase));
|
||||||
LoadScreens = loadScreens.Where(l => l.RoomId == r.RoomId).Select(l => new
|
|
||||||
{
|
|
||||||
l.ImageUrl,
|
|
||||||
l.Tooltip,
|
|
||||||
l.IsThumbnail
|
|
||||||
}).ToList(),
|
|
||||||
PromoImages = promoImages.Where(p => p.RoomId == r.RoomId).Select(p => new
|
|
||||||
{
|
|
||||||
p.ImageUrl,
|
|
||||||
p.Tooltip,
|
|
||||||
p.SortOrder
|
|
||||||
}).ToList(),
|
|
||||||
PromoExternalContent = promoExternalContents.Where(p => p.RoomId == r.RoomId).Select(p => new
|
|
||||||
{
|
|
||||||
p.Type,
|
|
||||||
p.Url,
|
|
||||||
p.Tooltip
|
|
||||||
}).ToList(),
|
|
||||||
Tags = new object[0]
|
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
return Results.Json(response);
|
var hotRooms = allRooms
|
||||||
});
|
.OrderByDescending(r => r.Id)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
app.MapGet("/roomserver/rooms/hot", async (HttpRequest request, AppDbContext db) =>
|
var results = new List<object>();
|
||||||
|
|
||||||
|
foreach (var room in hotRooms)
|
||||||
{
|
{
|
||||||
var tagFilter = request.Query["tag"].FirstOrDefault()?.ToLower();
|
var subRooms = await db.SubRooms.Where(x => x.RoomId == room.RoomId).ToListAsync();
|
||||||
|
var roles = await db.RoomRoles.Where(x => x.RoomId == room.RoomId).ToListAsync();
|
||||||
var allRooms = await db.Rooms.ToListAsync();
|
var loadScreens = await db.LoadScreens.Where(x => x.RoomId == room.RoomId).ToListAsync();
|
||||||
|
var promoImages = await db.PromoImages.Where(x => x.RoomId == room.RoomId).ToListAsync();
|
||||||
if (!string.IsNullOrEmpty(tagFilter))
|
var external = await db.PromoExternalContents.Where(x => x.RoomId == room.RoomId).ToListAsync();
|
||||||
{
|
|
||||||
allRooms = allRooms.Where(r =>
|
|
||||||
{
|
|
||||||
var roomTags = TryDeserializeRoomTags(r.Tags);
|
|
||||||
if (roomTags == null || roomTags.Length == 0) return false;
|
|
||||||
|
|
||||||
return roomTags.Any(t => t.Tag.Equals(tagFilter, StringComparison.OrdinalIgnoreCase));
|
|
||||||
}).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
var hotRooms = allRooms
|
|
||||||
.OrderByDescending(r => r.Id)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var results = new List<object>();
|
|
||||||
|
|
||||||
foreach (var room in hotRooms)
|
|
||||||
{
|
|
||||||
var subRooms = await db.SubRooms.Where(x => x.RoomId == room.RoomId).ToListAsync();
|
|
||||||
var roles = await db.RoomRoles.Where(x => x.RoomId == room.RoomId).ToListAsync();
|
|
||||||
var loadScreens = await db.LoadScreens.Where(x => x.RoomId == room.RoomId).ToListAsync();
|
|
||||||
var promoImages = await db.PromoImages.Where(x => x.RoomId == room.RoomId).ToListAsync();
|
|
||||||
var external = await db.PromoExternalContents.Where(x => x.RoomId == room.RoomId).ToListAsync();
|
|
||||||
var tags = TryDeserializeTags(room.Tags) ?? new object[0];
|
|
||||||
|
|
||||||
var roomResponse = new
|
|
||||||
{
|
|
||||||
room.RoomId,
|
|
||||||
room.Name,
|
|
||||||
room.Description,
|
|
||||||
room.CreatorAccountId,
|
|
||||||
room.ImageName,
|
|
||||||
room.State,
|
|
||||||
room.Accessibility,
|
|
||||||
room.SupportsLevelVoting,
|
|
||||||
room.IsRRO,
|
|
||||||
room.IsDorm,
|
|
||||||
room.CloningAllowed,
|
|
||||||
room.SupportsVRLow,
|
|
||||||
room.SupportsQuest2,
|
|
||||||
room.SupportsMobile,
|
|
||||||
room.SupportsScreens,
|
|
||||||
room.SupportsWalkVR,
|
|
||||||
room.SupportsTeleportVR,
|
|
||||||
room.SupportsJuniors,
|
|
||||||
room.MinLevel,
|
|
||||||
room.WarningMask,
|
|
||||||
room.CustomWarning,
|
|
||||||
room.DisableMicAutoMute,
|
|
||||||
room.DisableRoomComments,
|
|
||||||
room.EncryptVoiceChat,
|
|
||||||
room.CreatedAt,
|
|
||||||
Stats = (object?)null,
|
|
||||||
SubRooms = subRooms.Select(s => new
|
|
||||||
{
|
|
||||||
s.SubRoomId,
|
|
||||||
s.RoomId,
|
|
||||||
s.Name,
|
|
||||||
s.DataBlob,
|
|
||||||
s.IsSandbox,
|
|
||||||
s.MaxPlayers,
|
|
||||||
s.Accessibility,
|
|
||||||
s.UnitySceneId,
|
|
||||||
s.DataSavedAt
|
|
||||||
}),
|
|
||||||
Roles = roles.Select(r => new
|
|
||||||
{
|
|
||||||
r.AccountId,
|
|
||||||
r.Role,
|
|
||||||
r.InvitedRole
|
|
||||||
}),
|
|
||||||
LoadScreens = loadScreens.Select(ls => new
|
|
||||||
{
|
|
||||||
ls.ImageUrl,
|
|
||||||
ls.Tooltip,
|
|
||||||
ls.IsThumbnail
|
|
||||||
}),
|
|
||||||
PromoImages = promoImages.Select(pi => new
|
|
||||||
{
|
|
||||||
pi.ImageUrl,
|
|
||||||
pi.Tooltip,
|
|
||||||
pi.SortOrder
|
|
||||||
}),
|
|
||||||
PromoExternalContent = external.Select(ec => new
|
|
||||||
{
|
|
||||||
ec.Type,
|
|
||||||
ec.Url,
|
|
||||||
ec.Tooltip
|
|
||||||
}),
|
|
||||||
Tags = tags
|
|
||||||
};
|
|
||||||
results.Add(roomResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
var response = new
|
|
||||||
{
|
|
||||||
Results = results,
|
|
||||||
TotalResults = results.Count
|
|
||||||
};
|
|
||||||
|
|
||||||
return Results.Json(response);
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapGet("/roomserver/roomsandplaylists/hot", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
// should sort by popularity but idk how to yet so we just d it by id order
|
|
||||||
var allRooms = await db.Rooms
|
|
||||||
.Where(r => !r.IsDorm)
|
|
||||||
.OrderByDescending(r => r.Id)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
var results = new List<object>();
|
|
||||||
|
|
||||||
foreach (var room in allRooms)
|
|
||||||
{
|
|
||||||
var subRooms = await db.SubRooms.Where(x => x.RoomId == room.RoomId).ToListAsync();
|
|
||||||
var roles = await db.RoomRoles.Where(x => x.RoomId == room.RoomId).ToListAsync();
|
|
||||||
var loadScreens = await db.LoadScreens.Where(x => x.RoomId == room.RoomId).ToListAsync();
|
|
||||||
var promoImages = await db.PromoImages.Where(x => x.RoomId == room.RoomId).ToListAsync();
|
|
||||||
var external = await db.PromoExternalContents.Where(x => x.RoomId == room.RoomId).ToListAsync();
|
|
||||||
var tags = TryDeserializeTags(room.Tags) ?? new object[0];
|
|
||||||
|
|
||||||
var roomResponse = new
|
|
||||||
{
|
|
||||||
room.RoomId,
|
|
||||||
room.Name,
|
|
||||||
room.Description,
|
|
||||||
room.CreatorAccountId,
|
|
||||||
room.ImageName,
|
|
||||||
room.State,
|
|
||||||
room.Accessibility,
|
|
||||||
room.SupportsLevelVoting,
|
|
||||||
room.IsRRO,
|
|
||||||
room.IsDorm,
|
|
||||||
room.CloningAllowed,
|
|
||||||
room.SupportsVRLow,
|
|
||||||
room.SupportsQuest2,
|
|
||||||
room.SupportsMobile,
|
|
||||||
room.SupportsScreens,
|
|
||||||
room.SupportsWalkVR,
|
|
||||||
room.SupportsTeleportVR,
|
|
||||||
room.SupportsJuniors,
|
|
||||||
room.MinLevel,
|
|
||||||
room.WarningMask,
|
|
||||||
room.CustomWarning,
|
|
||||||
room.DisableMicAutoMute,
|
|
||||||
room.DisableRoomComments,
|
|
||||||
room.EncryptVoiceChat,
|
|
||||||
room.CreatedAt,
|
|
||||||
Stats = (object?)null,
|
|
||||||
SubRooms = subRooms.Select(s => new
|
|
||||||
{
|
|
||||||
s.SubRoomId,
|
|
||||||
s.RoomId,
|
|
||||||
s.Name,
|
|
||||||
s.DataBlob,
|
|
||||||
s.IsSandbox,
|
|
||||||
s.MaxPlayers,
|
|
||||||
s.Accessibility,
|
|
||||||
s.UnitySceneId,
|
|
||||||
s.DataSavedAt
|
|
||||||
}),
|
|
||||||
Roles = roles.Select(r => new
|
|
||||||
{
|
|
||||||
r.AccountId,
|
|
||||||
r.Role,
|
|
||||||
r.InvitedRole
|
|
||||||
}),
|
|
||||||
LoadScreens = loadScreens.Select(ls => new
|
|
||||||
{
|
|
||||||
ls.ImageUrl,
|
|
||||||
ls.Tooltip,
|
|
||||||
ls.IsThumbnail
|
|
||||||
}),
|
|
||||||
PromoImages = promoImages.Select(pi => new
|
|
||||||
{
|
|
||||||
pi.ImageUrl,
|
|
||||||
pi.Tooltip,
|
|
||||||
pi.SortOrder
|
|
||||||
}),
|
|
||||||
PromoExternalContent = external.Select(ec => new
|
|
||||||
{
|
|
||||||
ec.Type,
|
|
||||||
ec.Url,
|
|
||||||
ec.Tooltip
|
|
||||||
}),
|
|
||||||
Tags = tags
|
|
||||||
};
|
|
||||||
results.Add(roomResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
var response = new
|
|
||||||
{
|
|
||||||
Results = results,
|
|
||||||
TotalResults = results.Count
|
|
||||||
};
|
|
||||||
|
|
||||||
return Results.Json(response);
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapGet("/roomserver/rooms/createdby/me", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
// TODO ADD FUNCTIONALITY
|
|
||||||
var json = File.ReadAllText("JSON/ownedrooms.json");
|
|
||||||
return Results.Content(json, "application/json");
|
|
||||||
});
|
|
||||||
app.MapGet("/roomserver/rooms/{id}", async (HttpRequest request, AppDbContext db, string id) =>
|
|
||||||
{
|
|
||||||
// this sucked to do
|
|
||||||
if (!int.TryParse(id, out var roomId))
|
|
||||||
return Results.NotFound();
|
|
||||||
|
|
||||||
var room = await db.Rooms
|
|
||||||
.FirstOrDefaultAsync(r => r.RoomId == roomId);
|
|
||||||
|
|
||||||
if (room == null)
|
|
||||||
return Results.NotFound();
|
|
||||||
|
|
||||||
var subRooms = true
|
|
||||||
? await db.SubRooms.Where(x => x.RoomId == room.RoomId).ToListAsync()
|
|
||||||
: new List<SubRoom>();
|
|
||||||
|
|
||||||
var roles = true
|
|
||||||
? await db.RoomRoles.Where(x => x.RoomId == room.RoomId).ToListAsync()
|
|
||||||
: new List<RoomRole>();
|
|
||||||
|
|
||||||
var loadScreens = true
|
|
||||||
? await db.LoadScreens.Where(x => x.RoomId == room.RoomId).ToListAsync()
|
|
||||||
: new List<LoadScreen>();
|
|
||||||
|
|
||||||
var promoImages = true
|
|
||||||
? await db.PromoImages.Where(x => x.RoomId == room.RoomId).ToListAsync()
|
|
||||||
: new List<PromoImage>();
|
|
||||||
|
|
||||||
var external = true
|
|
||||||
? await db.PromoExternalContents.Where(x => x.RoomId == room.RoomId).ToListAsync()
|
|
||||||
: new List<PromoExternalContent>();
|
|
||||||
|
|
||||||
var tags = TryDeserializeTags(room.Tags) ?? new object[0];
|
var tags = TryDeserializeTags(room.Tags) ?? new object[0];
|
||||||
|
|
||||||
var response = new
|
var roomResponse = new
|
||||||
{
|
{
|
||||||
room.RoomId,
|
room.RoomId,
|
||||||
room.Name,
|
room.Name,
|
||||||
@@ -1108,12 +956,10 @@ public class APIController
|
|||||||
room.ImageName,
|
room.ImageName,
|
||||||
room.State,
|
room.State,
|
||||||
room.Accessibility,
|
room.Accessibility,
|
||||||
|
|
||||||
room.SupportsLevelVoting,
|
room.SupportsLevelVoting,
|
||||||
room.IsRRO,
|
room.IsRRO,
|
||||||
room.IsDorm,
|
room.IsDorm,
|
||||||
room.CloningAllowed,
|
room.CloningAllowed,
|
||||||
|
|
||||||
room.SupportsVRLow,
|
room.SupportsVRLow,
|
||||||
room.SupportsQuest2,
|
room.SupportsQuest2,
|
||||||
room.SupportsMobile,
|
room.SupportsMobile,
|
||||||
@@ -1121,25 +967,14 @@ public class APIController
|
|||||||
room.SupportsWalkVR,
|
room.SupportsWalkVR,
|
||||||
room.SupportsTeleportVR,
|
room.SupportsTeleportVR,
|
||||||
room.SupportsJuniors,
|
room.SupportsJuniors,
|
||||||
|
|
||||||
room.MinLevel,
|
room.MinLevel,
|
||||||
room.WarningMask,
|
room.WarningMask,
|
||||||
room.CustomWarning,
|
room.CustomWarning,
|
||||||
|
|
||||||
room.DisableMicAutoMute,
|
room.DisableMicAutoMute,
|
||||||
room.DisableRoomComments,
|
room.DisableRoomComments,
|
||||||
room.EncryptVoiceChat,
|
room.EncryptVoiceChat,
|
||||||
|
|
||||||
room.CreatedAt,
|
room.CreatedAt,
|
||||||
|
Stats = (object?)null,
|
||||||
Stats = new RoomStats
|
|
||||||
{
|
|
||||||
CheerCount = 0,
|
|
||||||
FavoriteCount = 0,
|
|
||||||
VisitorCount = 1,
|
|
||||||
VisitCount = 1
|
|
||||||
},
|
|
||||||
|
|
||||||
SubRooms = subRooms.Select(s => new
|
SubRooms = subRooms.Select(s => new
|
||||||
{
|
{
|
||||||
s.SubRoomId,
|
s.SubRoomId,
|
||||||
@@ -1151,657 +986,908 @@ public class APIController
|
|||||||
s.Accessibility,
|
s.Accessibility,
|
||||||
s.UnitySceneId,
|
s.UnitySceneId,
|
||||||
s.DataSavedAt
|
s.DataSavedAt
|
||||||
}).ToList(),
|
}),
|
||||||
|
|
||||||
Roles = roles.Select(r => new
|
Roles = roles.Select(r => new
|
||||||
{
|
{
|
||||||
r.AccountId,
|
r.AccountId,
|
||||||
r.Role,
|
r.Role,
|
||||||
r.InvitedRole
|
r.InvitedRole
|
||||||
}).ToList(),
|
}),
|
||||||
|
LoadScreens = loadScreens.Select(ls => new
|
||||||
LoadScreens = loadScreens.Select(l => new
|
|
||||||
{
|
{
|
||||||
l.ImageUrl,
|
ls.ImageUrl,
|
||||||
l.Tooltip,
|
ls.Tooltip,
|
||||||
l.IsThumbnail
|
ls.IsThumbnail
|
||||||
}).ToList(),
|
}),
|
||||||
|
PromoImages = promoImages.Select(pi => new
|
||||||
PromoImages = promoImages.Select(p => new
|
|
||||||
{
|
{
|
||||||
p.ImageUrl,
|
pi.ImageUrl,
|
||||||
p.Tooltip,
|
pi.Tooltip,
|
||||||
p.SortOrder
|
pi.SortOrder
|
||||||
}).ToList(),
|
}),
|
||||||
|
PromoExternalContent = external.Select(ec => new
|
||||||
PromoExternalContent = external.Select(e => new
|
|
||||||
{
|
{
|
||||||
e.Type,
|
ec.Type,
|
||||||
e.Url,
|
ec.Url,
|
||||||
e.Tooltip
|
ec.Tooltip
|
||||||
}).ToList(),
|
}),
|
||||||
|
|
||||||
Tags = tags
|
Tags = tags
|
||||||
};
|
};
|
||||||
|
results.Add(roomResponse);
|
||||||
|
}
|
||||||
|
|
||||||
return Results.Json(response);
|
var response = new
|
||||||
});
|
|
||||||
app.MapGet("/api/images/v2/named", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
{
|
||||||
var json = File.ReadAllText("JSON/namedimages.json");
|
Results = results,
|
||||||
|
TotalResults = results.Count
|
||||||
|
};
|
||||||
|
|
||||||
|
return Results.Json(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("/roomserver/roomsandplaylists/hot")]
|
||||||
|
public async Task<IResult> GetHotRoomsAndPlaylists(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
// should sort by popularity but idk how to yet so we just d it by id order
|
||||||
|
var allRooms = await db.Rooms
|
||||||
|
.Where(r => !r.IsDorm)
|
||||||
|
.OrderByDescending(r => r.Id)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var results = new List<object>();
|
||||||
|
|
||||||
|
foreach (var room in allRooms)
|
||||||
|
{
|
||||||
|
var subRooms = await db.SubRooms.Where(x => x.RoomId == room.RoomId).ToListAsync();
|
||||||
|
var roles = await db.RoomRoles.Where(x => x.RoomId == room.RoomId).ToListAsync();
|
||||||
|
var loadScreens = await db.LoadScreens.Where(x => x.RoomId == room.RoomId).ToListAsync();
|
||||||
|
var promoImages = await db.PromoImages.Where(x => x.RoomId == room.RoomId).ToListAsync();
|
||||||
|
var external = await db.PromoExternalContents.Where(x => x.RoomId == room.RoomId).ToListAsync();
|
||||||
|
var tags = TryDeserializeTags(room.Tags) ?? new object[0];
|
||||||
|
|
||||||
|
var roomResponse = new
|
||||||
|
{
|
||||||
|
room.RoomId,
|
||||||
|
room.Name,
|
||||||
|
room.Description,
|
||||||
|
room.CreatorAccountId,
|
||||||
|
room.ImageName,
|
||||||
|
room.State,
|
||||||
|
room.Accessibility,
|
||||||
|
room.SupportsLevelVoting,
|
||||||
|
room.IsRRO,
|
||||||
|
room.IsDorm,
|
||||||
|
room.CloningAllowed,
|
||||||
|
room.SupportsVRLow,
|
||||||
|
room.SupportsQuest2,
|
||||||
|
room.SupportsMobile,
|
||||||
|
room.SupportsScreens,
|
||||||
|
room.SupportsWalkVR,
|
||||||
|
room.SupportsTeleportVR,
|
||||||
|
room.SupportsJuniors,
|
||||||
|
room.MinLevel,
|
||||||
|
room.WarningMask,
|
||||||
|
room.CustomWarning,
|
||||||
|
room.DisableMicAutoMute,
|
||||||
|
room.DisableRoomComments,
|
||||||
|
room.EncryptVoiceChat,
|
||||||
|
room.CreatedAt,
|
||||||
|
Stats = (object?)null,
|
||||||
|
SubRooms = subRooms.Select(s => new
|
||||||
|
{
|
||||||
|
s.SubRoomId,
|
||||||
|
s.RoomId,
|
||||||
|
s.Name,
|
||||||
|
s.DataBlob,
|
||||||
|
s.IsSandbox,
|
||||||
|
s.MaxPlayers,
|
||||||
|
s.Accessibility,
|
||||||
|
s.UnitySceneId,
|
||||||
|
s.DataSavedAt
|
||||||
|
}),
|
||||||
|
Roles = roles.Select(r => new
|
||||||
|
{
|
||||||
|
r.AccountId,
|
||||||
|
r.Role,
|
||||||
|
r.InvitedRole
|
||||||
|
}),
|
||||||
|
LoadScreens = loadScreens.Select(ls => new
|
||||||
|
{
|
||||||
|
ls.ImageUrl,
|
||||||
|
ls.Tooltip,
|
||||||
|
ls.IsThumbnail
|
||||||
|
}),
|
||||||
|
PromoImages = promoImages.Select(pi => new
|
||||||
|
{
|
||||||
|
pi.ImageUrl,
|
||||||
|
pi.Tooltip,
|
||||||
|
pi.SortOrder
|
||||||
|
}),
|
||||||
|
PromoExternalContent = external.Select(ec => new
|
||||||
|
{
|
||||||
|
ec.Type,
|
||||||
|
ec.Url,
|
||||||
|
ec.Tooltip
|
||||||
|
}),
|
||||||
|
Tags = tags
|
||||||
|
};
|
||||||
|
results.Add(roomResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = new
|
||||||
|
{
|
||||||
|
Results = results,
|
||||||
|
TotalResults = results.Count
|
||||||
|
};
|
||||||
|
|
||||||
|
return Results.Json(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("/roomserver/rooms/createdby/me")]
|
||||||
|
public async Task<IResult> GetMyCreatedRooms(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
// TODO ADD FUNCTIONALITY
|
||||||
|
var json = System.IO.File.ReadAllText("JSON/ownedrooms.json");
|
||||||
|
return Results.Content(json, "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("/roomserver/rooms/{id}")]
|
||||||
|
public async Task<IResult> GetRoom(HttpRequest request, AppDbContext db, string id)
|
||||||
|
{
|
||||||
|
// this sucked to do
|
||||||
|
if (!int.TryParse(id, out var roomId))
|
||||||
|
return Results.NotFound();
|
||||||
|
|
||||||
|
var room = await db.Rooms
|
||||||
|
.FirstOrDefaultAsync(r => r.RoomId == roomId);
|
||||||
|
|
||||||
|
if (room == null)
|
||||||
|
return Results.NotFound();
|
||||||
|
|
||||||
|
var subRooms = true
|
||||||
|
? await db.SubRooms.Where(x => x.RoomId == room.RoomId).ToListAsync()
|
||||||
|
: new List<SubRoom>();
|
||||||
|
|
||||||
|
var roles = true
|
||||||
|
? await db.RoomRoles.Where(x => x.RoomId == room.RoomId).ToListAsync()
|
||||||
|
: new List<RoomRole>();
|
||||||
|
|
||||||
|
var loadScreens = true
|
||||||
|
? await db.LoadScreens.Where(x => x.RoomId == room.RoomId).ToListAsync()
|
||||||
|
: new List<LoadScreen>();
|
||||||
|
|
||||||
|
var promoImages = true
|
||||||
|
? await db.PromoImages.Where(x => x.RoomId == room.RoomId).ToListAsync()
|
||||||
|
: new List<PromoImage>();
|
||||||
|
|
||||||
|
var external = true
|
||||||
|
? await db.PromoExternalContents.Where(x => x.RoomId == room.RoomId).ToListAsync()
|
||||||
|
: new List<PromoExternalContent>();
|
||||||
|
|
||||||
|
var tags = TryDeserializeTags(room.Tags) ?? new object[0];
|
||||||
|
|
||||||
|
var response = new
|
||||||
|
{
|
||||||
|
room.RoomId,
|
||||||
|
room.Name,
|
||||||
|
room.Description,
|
||||||
|
room.CreatorAccountId,
|
||||||
|
room.ImageName,
|
||||||
|
room.State,
|
||||||
|
room.Accessibility,
|
||||||
|
|
||||||
|
room.SupportsLevelVoting,
|
||||||
|
room.IsRRO,
|
||||||
|
room.IsDorm,
|
||||||
|
room.CloningAllowed,
|
||||||
|
|
||||||
|
room.SupportsVRLow,
|
||||||
|
room.SupportsQuest2,
|
||||||
|
room.SupportsMobile,
|
||||||
|
room.SupportsScreens,
|
||||||
|
room.SupportsWalkVR,
|
||||||
|
room.SupportsTeleportVR,
|
||||||
|
room.SupportsJuniors,
|
||||||
|
|
||||||
|
room.MinLevel,
|
||||||
|
room.WarningMask,
|
||||||
|
room.CustomWarning,
|
||||||
|
|
||||||
|
room.DisableMicAutoMute,
|
||||||
|
room.DisableRoomComments,
|
||||||
|
room.EncryptVoiceChat,
|
||||||
|
|
||||||
|
room.CreatedAt,
|
||||||
|
|
||||||
|
Stats = new RoomStats
|
||||||
|
{
|
||||||
|
CheerCount = 0,
|
||||||
|
FavoriteCount = 0,
|
||||||
|
VisitorCount = 1,
|
||||||
|
VisitCount = 1
|
||||||
|
},
|
||||||
|
|
||||||
|
SubRooms = subRooms.Select(s => new
|
||||||
|
{
|
||||||
|
s.SubRoomId,
|
||||||
|
s.RoomId,
|
||||||
|
s.Name,
|
||||||
|
s.DataBlob,
|
||||||
|
s.IsSandbox,
|
||||||
|
s.MaxPlayers,
|
||||||
|
s.Accessibility,
|
||||||
|
s.UnitySceneId,
|
||||||
|
s.DataSavedAt
|
||||||
|
}).ToList(),
|
||||||
|
|
||||||
|
Roles = roles.Select(r => new
|
||||||
|
{
|
||||||
|
r.AccountId,
|
||||||
|
r.Role,
|
||||||
|
r.InvitedRole
|
||||||
|
}).ToList(),
|
||||||
|
|
||||||
|
LoadScreens = loadScreens.Select(l => new
|
||||||
|
{
|
||||||
|
l.ImageUrl,
|
||||||
|
l.Tooltip,
|
||||||
|
l.IsThumbnail
|
||||||
|
}).ToList(),
|
||||||
|
|
||||||
|
PromoImages = promoImages.Select(p => new
|
||||||
|
{
|
||||||
|
p.ImageUrl,
|
||||||
|
p.Tooltip,
|
||||||
|
p.SortOrder
|
||||||
|
}).ToList(),
|
||||||
|
|
||||||
|
PromoExternalContent = external.Select(e => new
|
||||||
|
{
|
||||||
|
e.Type,
|
||||||
|
e.Url,
|
||||||
|
e.Tooltip
|
||||||
|
}).ToList(),
|
||||||
|
|
||||||
|
Tags = tags
|
||||||
|
};
|
||||||
|
|
||||||
|
return Results.Json(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("images/v2/named")]
|
||||||
|
public async Task<IResult> GetNamedImages(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
var json = System.IO.File.ReadAllText("JSON/namedimages.json");
|
||||||
|
return Results.Content(json, "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("objectives/v1/updateobjective")]
|
||||||
|
public async Task<IResult> UpdateObjective(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
// TODO: implement saving daily
|
||||||
|
return Results.Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("PlayerReporting/v1/hile")]
|
||||||
|
public async Task<IResult> Hile(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
// stops crashing the game due to bepinex winhttp.dll (or melonloader version.dll)
|
||||||
|
return Results.Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("storefronts/v3/giftdropstore/300")]
|
||||||
|
public async Task<IResult> GetGiftDropStore300(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
var storefronts = await _storefrontService.GetStorefrontsAsync();
|
||||||
|
var storefront = storefronts.FirstOrDefault(s => s.StorefrontType == 300 && s.Name == "rc_cafe_storefront");
|
||||||
|
if (storefront == null)
|
||||||
|
{
|
||||||
|
var json = System.IO.File.ReadAllText("JSON/cafestorefront.json");
|
||||||
return Results.Content(json, "application/json");
|
return Results.Content(json, "application/json");
|
||||||
});
|
}
|
||||||
app.MapPost("/api/objectives/v1/updateobjective", async (HttpRequest request, AppDbContext db) =>
|
var storeItems = storefront.Items.Select(item => new
|
||||||
{
|
{
|
||||||
// TODO: implement saving daily
|
item.Id,
|
||||||
return Results.Ok();
|
item.StorefrontId,
|
||||||
});
|
item.PurchasableItemId,
|
||||||
app.MapPost("/api/PlayerReporting/v1/hile", async (HttpRequest request, AppDbContext db) =>
|
item.Type,
|
||||||
{
|
item.IsFeatured,
|
||||||
// stops crashing the game due to bepinex winhttp.dll (or melonloader version.dll)
|
item.NewUntil,
|
||||||
return Results.Ok();
|
GiftDrops = item.GiftDrops.Select(gd => new
|
||||||
});
|
|
||||||
app.MapGet("/api/storefronts/v3/giftdropstore/300", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var storefronts = await storefrontService.GetStorefrontsAsync();
|
|
||||||
var storefront = storefronts.FirstOrDefault(s => s.StorefrontType == 300 && s.Name == "rc_cafe_storefront");
|
|
||||||
if (storefront == null)
|
|
||||||
{
|
{
|
||||||
var json = File.ReadAllText("JSON/cafestorefront.json");
|
gd.Id,
|
||||||
return Results.Content(json, "application/json");
|
gd.StorefrontItemId,
|
||||||
|
gd.GiftDropId,
|
||||||
|
gd.FriendlyName,
|
||||||
|
gd.Tooltip,
|
||||||
|
gd.ConsumableItemDesc,
|
||||||
|
gd.AvatarItemDesc,
|
||||||
|
gd.AvatarItemType,
|
||||||
|
gd.EquipmentPrefabName,
|
||||||
|
gd.EquipmentModificationGuid,
|
||||||
|
gd.IsQuery,
|
||||||
|
gd.Unique,
|
||||||
|
gd.SubscribersOnly,
|
||||||
|
gd.Level,
|
||||||
|
gd.Rarity,
|
||||||
|
gd.CurrencyType,
|
||||||
|
gd.Currency,
|
||||||
|
gd.Context,
|
||||||
|
gd.ItemSetId,
|
||||||
|
gd.ItemSetFriendlyName
|
||||||
|
}).ToList(),
|
||||||
|
Prices = item.Prices.Select(p => new
|
||||||
|
{
|
||||||
|
p.Id,
|
||||||
|
p.StorefrontItemId,
|
||||||
|
p.CurrencyType,
|
||||||
|
p.Price
|
||||||
|
}).ToList()
|
||||||
|
}).ToList();
|
||||||
|
var response = new { storefront.Id, storefront.Name, storefront.StorefrontType, storefront.NextUpdate, StoreItems = storeItems };
|
||||||
|
return Results.Ok(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("storefronts/v3/giftdropstore/2")]
|
||||||
|
public async Task<IResult> GetGiftDropStore2(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
var storefronts = await _storefrontService.GetStorefrontsAsync();
|
||||||
|
var storefront = storefronts.FirstOrDefault(s => s.StorefrontType == 2 && s.Name == "rec_center_store");
|
||||||
|
if (storefront == null)
|
||||||
|
{
|
||||||
|
var json = System.IO.File.ReadAllText("JSON/storefront12.json");
|
||||||
|
return Results.Content(json, "application/json");
|
||||||
|
}
|
||||||
|
var storeItems = storefront.Items.Select(item => new
|
||||||
|
{
|
||||||
|
item.Id,
|
||||||
|
item.StorefrontId,
|
||||||
|
item.PurchasableItemId,
|
||||||
|
item.Type,
|
||||||
|
item.IsFeatured,
|
||||||
|
item.NewUntil,
|
||||||
|
GiftDrops = item.GiftDrops.Select(gd => new
|
||||||
|
{
|
||||||
|
gd.Id,
|
||||||
|
gd.StorefrontItemId,
|
||||||
|
gd.GiftDropId,
|
||||||
|
gd.FriendlyName,
|
||||||
|
gd.Tooltip,
|
||||||
|
gd.ConsumableItemDesc,
|
||||||
|
gd.AvatarItemDesc,
|
||||||
|
gd.AvatarItemType,
|
||||||
|
gd.EquipmentPrefabName,
|
||||||
|
gd.EquipmentModificationGuid,
|
||||||
|
gd.IsQuery,
|
||||||
|
gd.Unique,
|
||||||
|
gd.SubscribersOnly,
|
||||||
|
gd.Level,
|
||||||
|
gd.Rarity,
|
||||||
|
gd.CurrencyType,
|
||||||
|
gd.Currency,
|
||||||
|
gd.Context,
|
||||||
|
gd.ItemSetId,
|
||||||
|
gd.ItemSetFriendlyName
|
||||||
|
}).ToList(),
|
||||||
|
Prices = item.Prices.Select(p => new
|
||||||
|
{
|
||||||
|
p.Id,
|
||||||
|
p.StorefrontItemId,
|
||||||
|
p.CurrencyType,
|
||||||
|
p.Price
|
||||||
|
}).ToList()
|
||||||
|
}).ToList();
|
||||||
|
var response = new { storefront.Id, storefront.Name, storefront.StorefrontType, storefront.NextUpdate, StoreItems = storeItems };
|
||||||
|
return Results.Ok(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("storefronts/v2/buyItem")]
|
||||||
|
public async Task<IResult> BuyItem(HttpRequest request, [FromBody] BuyItemRequest buyRequest, AppDbContext db, JwtTokenService jwtService)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
|
var accountId = jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var storefrontItem = await db.StorefrontItems
|
||||||
|
.Include(si => si.Prices)
|
||||||
|
.Include(si => si.GiftDrops)
|
||||||
|
.FirstOrDefaultAsync(si => si.PurchasableItemId == buyRequest.PurchasableItemId);
|
||||||
|
|
||||||
|
if (storefrontItem == null)
|
||||||
|
{
|
||||||
|
return Results.NotFound(new { error = "Item not found" });
|
||||||
}
|
}
|
||||||
var storeItems = storefront.Items.Select(item => new
|
|
||||||
|
var price = storefrontItem.Prices.FirstOrDefault(p => p.CurrencyType == buyRequest.CurrencyType);
|
||||||
|
if (price == null)
|
||||||
{
|
{
|
||||||
item.Id,
|
return Results.BadRequest(new { error = "Currency type not available for this item" });
|
||||||
item.StorefrontId,
|
|
||||||
item.PurchasableItemId,
|
|
||||||
item.Type,
|
|
||||||
item.IsFeatured,
|
|
||||||
item.NewUntil,
|
|
||||||
GiftDrops = item.GiftDrops.Select(gd => new
|
|
||||||
{
|
|
||||||
gd.Id,
|
|
||||||
gd.StorefrontItemId,
|
|
||||||
gd.GiftDropId,
|
|
||||||
gd.FriendlyName,
|
|
||||||
gd.Tooltip,
|
|
||||||
gd.ConsumableItemDesc,
|
|
||||||
gd.AvatarItemDesc,
|
|
||||||
gd.AvatarItemType,
|
|
||||||
gd.EquipmentPrefabName,
|
|
||||||
gd.EquipmentModificationGuid,
|
|
||||||
gd.IsQuery,
|
|
||||||
gd.Unique,
|
|
||||||
gd.SubscribersOnly,
|
|
||||||
gd.Level,
|
|
||||||
gd.Rarity,
|
|
||||||
gd.CurrencyType,
|
|
||||||
gd.Currency,
|
|
||||||
gd.Context,
|
|
||||||
gd.ItemSetId,
|
|
||||||
gd.ItemSetFriendlyName
|
|
||||||
}).ToList(),
|
|
||||||
Prices = item.Prices.Select(p => new
|
|
||||||
{
|
|
||||||
p.Id,
|
|
||||||
p.StorefrontItemId,
|
|
||||||
p.CurrencyType,
|
|
||||||
p.Price
|
|
||||||
}).ToList()
|
|
||||||
}).ToList();
|
|
||||||
var response = new { storefront.Id, storefront.Name, storefront.StorefrontType, storefront.NextUpdate, StoreItems = storeItems };
|
|
||||||
return Results.Ok(response);
|
|
||||||
});
|
|
||||||
app.MapGet("/api/storefronts/v3/giftdropstore/2", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var storefronts = await storefrontService.GetStorefrontsAsync();
|
|
||||||
var storefront = storefronts.FirstOrDefault(s => s.StorefrontType == 2 && s.Name == "rec_center_store");
|
|
||||||
if (storefront == null)
|
|
||||||
{
|
|
||||||
var json = File.ReadAllText("JSON/storefront12.json");
|
|
||||||
return Results.Content(json, "application/json");
|
|
||||||
}
|
}
|
||||||
var storeItems = storefront.Items.Select(item => new
|
|
||||||
|
var tokenBalance = await db.TokenBalances
|
||||||
|
.FirstOrDefaultAsync(tb => tb.Id == id &&
|
||||||
|
tb.CurrencyType == buyRequest.CurrencyType &&
|
||||||
|
tb.BalanceType == -1);
|
||||||
|
|
||||||
|
if (tokenBalance == null)
|
||||||
{
|
{
|
||||||
item.Id,
|
return Results.BadRequest(new { error = "Account has no token balance" });
|
||||||
item.StorefrontId,
|
}
|
||||||
item.PurchasableItemId,
|
|
||||||
item.Type,
|
if (tokenBalance.Balance < price.Price)
|
||||||
item.IsFeatured,
|
|
||||||
item.NewUntil,
|
|
||||||
GiftDrops = item.GiftDrops.Select(gd => new
|
|
||||||
{
|
|
||||||
gd.Id,
|
|
||||||
gd.StorefrontItemId,
|
|
||||||
gd.GiftDropId,
|
|
||||||
gd.FriendlyName,
|
|
||||||
gd.Tooltip,
|
|
||||||
gd.ConsumableItemDesc,
|
|
||||||
gd.AvatarItemDesc,
|
|
||||||
gd.AvatarItemType,
|
|
||||||
gd.EquipmentPrefabName,
|
|
||||||
gd.EquipmentModificationGuid,
|
|
||||||
gd.IsQuery,
|
|
||||||
gd.Unique,
|
|
||||||
gd.SubscribersOnly,
|
|
||||||
gd.Level,
|
|
||||||
gd.Rarity,
|
|
||||||
gd.CurrencyType,
|
|
||||||
gd.Currency,
|
|
||||||
gd.Context,
|
|
||||||
gd.ItemSetId,
|
|
||||||
gd.ItemSetFriendlyName
|
|
||||||
}).ToList(),
|
|
||||||
Prices = item.Prices.Select(p => new
|
|
||||||
{
|
|
||||||
p.Id,
|
|
||||||
p.StorefrontItemId,
|
|
||||||
p.CurrencyType,
|
|
||||||
p.Price
|
|
||||||
}).ToList()
|
|
||||||
}).ToList();
|
|
||||||
var response = new { storefront.Id, storefront.Name, storefront.StorefrontType, storefront.NextUpdate, StoreItems = storeItems };
|
|
||||||
return Results.Ok(response);
|
|
||||||
});
|
|
||||||
app.MapPost("/api/storefronts/v2/buyItem", async (HttpRequest request, BuyItemRequest buyRequest, AppDbContext db, JwtTokenService jwtService) =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
return Results.BadRequest(new { error = "Insufficient balance" });
|
||||||
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
tokenBalance.Balance -= price.Price;
|
||||||
return Results.Unauthorized();
|
db.TokenBalances.Update(tokenBalance);
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
var receiverAccountId = id;
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
int? senderPlayerId = null;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out var id))
|
if (buyRequest.Gift != null)
|
||||||
return Results.Unauthorized();
|
{
|
||||||
|
receiverAccountId = buyRequest.Gift.ToPlayerId;
|
||||||
var storefrontItem = await db.StorefrontItems
|
if (!buyRequest.Gift.Anonymous)
|
||||||
.Include(si => si.Prices)
|
|
||||||
.Include(si => si.GiftDrops)
|
|
||||||
.FirstOrDefaultAsync(si => si.PurchasableItemId == buyRequest.PurchasableItemId);
|
|
||||||
|
|
||||||
if (storefrontItem == null)
|
|
||||||
{
|
{
|
||||||
return Results.NotFound(new { error = "Item not found" });
|
senderPlayerId = id;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var price = storefrontItem.Prices.FirstOrDefault(p => p.CurrencyType == buyRequest.CurrencyType);
|
var storedGifts = new List<ReceivedGift>();
|
||||||
if (price == null)
|
foreach (var giftDrop in storefrontItem.GiftDrops)
|
||||||
|
{
|
||||||
|
var receivedGift = new ReceivedGift
|
||||||
{
|
{
|
||||||
return Results.BadRequest(new { error = "Currency type not available for this item" });
|
ReceiverAccountId = receiverAccountId,
|
||||||
}
|
FromPlayerId = 1,
|
||||||
|
Message = buyRequest.Gift?.Message ?? "A gift for you <3",
|
||||||
var tokenBalance = await db.TokenBalances
|
ConsumableItemDesc = giftDrop.ConsumableItemDesc ?? string.Empty,
|
||||||
.FirstOrDefaultAsync(tb => tb.Id == id &&
|
AvatarItemDesc = giftDrop.AvatarItemDesc ?? string.Empty,
|
||||||
tb.CurrencyType == buyRequest.CurrencyType &&
|
// FriendlyName = giftDrop.FriendlyName ?? string.Empty,
|
||||||
tb.BalanceType == -1);
|
AvatarItemType = giftDrop.AvatarItemType,
|
||||||
|
EquipmentPrefabName = giftDrop.EquipmentPrefabName ?? string.Empty,
|
||||||
if (tokenBalance == null)
|
EquipmentModificationGuid = giftDrop.EquipmentModificationGuid ?? string.Empty,
|
||||||
{
|
CurrencyType = giftDrop.CurrencyType,
|
||||||
return Results.BadRequest(new { error = "Account has no token balance" });
|
Currency = giftDrop.Currency,
|
||||||
}
|
Xp = 0,
|
||||||
|
Level = giftDrop.Level,
|
||||||
if (tokenBalance.Balance < price.Price)
|
Platform = -1,
|
||||||
{
|
PlatformsToSpawnOn = -1,
|
||||||
return Results.BadRequest(new { error = "Insufficient balance" });
|
BalanceType = 0,
|
||||||
}
|
GiftContext = buyRequest.Gift?.GiftContext ?? giftDrop.Context,
|
||||||
|
GiftRarity = giftDrop.Rarity,
|
||||||
tokenBalance.Balance -= price.Price;
|
ReceivedAt = DateTime.UtcNow,
|
||||||
db.TokenBalances.Update(tokenBalance);
|
IsConsumed = false
|
||||||
await db.SaveChangesAsync();
|
|
||||||
|
|
||||||
var receiverAccountId = id;
|
|
||||||
int? senderPlayerId = null;
|
|
||||||
|
|
||||||
if (buyRequest.Gift != null)
|
|
||||||
{
|
|
||||||
receiverAccountId = buyRequest.Gift.ToPlayerId;
|
|
||||||
if (!buyRequest.Gift.Anonymous)
|
|
||||||
{
|
|
||||||
senderPlayerId = id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var storedGifts = new List<ReceivedGift>();
|
|
||||||
foreach (var giftDrop in storefrontItem.GiftDrops)
|
|
||||||
{
|
|
||||||
var receivedGift = new ReceivedGift
|
|
||||||
{
|
|
||||||
ReceiverAccountId = receiverAccountId,
|
|
||||||
FromPlayerId = 1,
|
|
||||||
Message = buyRequest.Gift?.Message ?? "A gift for you <3",
|
|
||||||
ConsumableItemDesc = giftDrop.ConsumableItemDesc ?? string.Empty,
|
|
||||||
AvatarItemDesc = giftDrop.AvatarItemDesc ?? string.Empty,
|
|
||||||
// FriendlyName = giftDrop.FriendlyName ?? string.Empty,
|
|
||||||
AvatarItemType = giftDrop.AvatarItemType,
|
|
||||||
EquipmentPrefabName = giftDrop.EquipmentPrefabName ?? string.Empty,
|
|
||||||
EquipmentModificationGuid = giftDrop.EquipmentModificationGuid ?? string.Empty,
|
|
||||||
CurrencyType = giftDrop.CurrencyType,
|
|
||||||
Currency = giftDrop.Currency,
|
|
||||||
Xp = 0,
|
|
||||||
Level = giftDrop.Level,
|
|
||||||
Platform = -1,
|
|
||||||
PlatformsToSpawnOn = -1,
|
|
||||||
BalanceType = 0,
|
|
||||||
GiftContext = buyRequest.Gift?.GiftContext ?? giftDrop.Context,
|
|
||||||
GiftRarity = giftDrop.Rarity,
|
|
||||||
ReceivedAt = DateTime.UtcNow,
|
|
||||||
IsConsumed = false
|
|
||||||
};
|
|
||||||
|
|
||||||
db.ReceivedGifts.Add(receivedGift);
|
|
||||||
storedGifts.Add(receivedGift);
|
|
||||||
}
|
|
||||||
await db.SaveChangesAsync();
|
|
||||||
|
|
||||||
var giftData = storedGifts.Select(rg => new GiftData
|
|
||||||
{
|
|
||||||
Id = rg.Id,
|
|
||||||
FromPlayerId = null,
|
|
||||||
ConsumableItemDesc = rg.ConsumableItemDesc,
|
|
||||||
AvatarItemDesc = rg.AvatarItemDesc,
|
|
||||||
FriendlyName = rg.FriendlyName,
|
|
||||||
AvatarItemType = rg.AvatarItemType,
|
|
||||||
EquipmentPrefabName = rg.EquipmentPrefabName,
|
|
||||||
EquipmentModificationGuid = rg.EquipmentModificationGuid,
|
|
||||||
CurrencyType = rg.CurrencyType,
|
|
||||||
Currency = rg.Currency,
|
|
||||||
Xp = rg.Xp,
|
|
||||||
Level = rg.Level,
|
|
||||||
Platform = rg.Platform,
|
|
||||||
PlatformsToSpawnOn = rg.PlatformsToSpawnOn,
|
|
||||||
BalanceType = rg.BalanceType,
|
|
||||||
GiftContext = rg.GiftContext,
|
|
||||||
GiftRarity = rg.GiftRarity,
|
|
||||||
Message = rg.Message
|
|
||||||
}).ToList();
|
|
||||||
|
|
||||||
var balanceUpdate = new BalanceUpdate
|
|
||||||
{
|
|
||||||
UpdateResponse = 0,
|
|
||||||
Data = giftData
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var response = new BuyItemResponse
|
db.ReceivedGifts.Add(receivedGift);
|
||||||
{
|
storedGifts.Add(receivedGift);
|
||||||
BalanceUpdates = new List<BalanceUpdate> { balanceUpdate },
|
|
||||||
Balance = tokenBalance.Balance,
|
|
||||||
CurrencyType = buyRequest.CurrencyType,
|
|
||||||
BalanceType = -1,
|
|
||||||
Platform = -1
|
|
||||||
};
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var purchaseNotification = notificationService.CreateNotification(
|
|
||||||
PushNotificationId.StorefrontBalancePurchase,
|
|
||||||
id: storefrontItem.Id,
|
|
||||||
toAccountId: id,
|
|
||||||
data: new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "BalanceAddType", 1400 },
|
|
||||||
{ "Delta", -price.Price },
|
|
||||||
{ "Balance", tokenBalance.Balance },
|
|
||||||
{ "CurrencyType", buyRequest.CurrencyType }
|
|
||||||
}
|
|
||||||
);
|
|
||||||
await notificationService.SendNotificationToPlayer(id, purchaseNotification);
|
|
||||||
}
|
|
||||||
catch (Exception notifEx)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Error sending purchase notification: {notifEx.Message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return Results.Ok(response);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
|
var giftData = storedGifts.Select(rg => new GiftData
|
||||||
{
|
{
|
||||||
return Results.Problem($"Error processing purchase: {ex.Message}");
|
Id = rg.Id,
|
||||||
}
|
FromPlayerId = null,
|
||||||
});
|
ConsumableItemDesc = rg.ConsumableItemDesc,
|
||||||
|
AvatarItemDesc = rg.AvatarItemDesc,
|
||||||
|
FriendlyName = rg.FriendlyName,
|
||||||
|
AvatarItemType = rg.AvatarItemType,
|
||||||
|
EquipmentPrefabName = rg.EquipmentPrefabName,
|
||||||
|
EquipmentModificationGuid = rg.EquipmentModificationGuid,
|
||||||
|
CurrencyType = rg.CurrencyType,
|
||||||
|
Currency = rg.Currency,
|
||||||
|
Xp = rg.Xp,
|
||||||
|
Level = rg.Level,
|
||||||
|
Platform = rg.Platform,
|
||||||
|
PlatformsToSpawnOn = rg.PlatformsToSpawnOn,
|
||||||
|
BalanceType = rg.BalanceType,
|
||||||
|
GiftContext = rg.GiftContext,
|
||||||
|
GiftRarity = rg.GiftRarity,
|
||||||
|
Message = rg.Message
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
var balanceUpdate = new BalanceUpdate
|
||||||
|
{
|
||||||
|
UpdateResponse = 0,
|
||||||
|
Data = giftData
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = new BuyItemResponse
|
||||||
|
{
|
||||||
|
BalanceUpdates = new List<BalanceUpdate> { balanceUpdate },
|
||||||
|
Balance = tokenBalance.Balance,
|
||||||
|
CurrencyType = buyRequest.CurrencyType,
|
||||||
|
BalanceType = -1,
|
||||||
|
Platform = -1
|
||||||
|
};
|
||||||
|
|
||||||
app.MapPost("/api/avatar/v2/gifts/generate", async (HttpRequest request, AppDbContext db, JwtTokenService jwtService) =>
|
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
var purchaseNotification = _notificationService.CreateNotification(
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
PushNotificationId.StorefrontBalancePurchase,
|
||||||
return Results.Unauthorized();
|
id: storefrontItem.Id,
|
||||||
|
toAccountId: id,
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
data: new Dictionary<string, object>
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
request.EnableBuffering();
|
|
||||||
request.Body.Position = 0;
|
|
||||||
using var reader = new StreamReader(request.Body);
|
|
||||||
var body = await reader.ReadToEndAsync();
|
|
||||||
|
|
||||||
int giftContext = 0;
|
|
||||||
bool isGameGift = false;
|
|
||||||
string message = "";
|
|
||||||
int xp = 0;
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(body))
|
|
||||||
{
|
|
||||||
foreach (var pair in body.Split('&'))
|
|
||||||
{
|
{
|
||||||
var keyValue = pair.Split('=');
|
{ "BalanceAddType", 1400 },
|
||||||
if (keyValue.Length == 2)
|
{ "Delta", -price.Price },
|
||||||
{
|
{ "Balance", tokenBalance.Balance },
|
||||||
var key = Uri.UnescapeDataString(keyValue[0]);
|
{ "CurrencyType", buyRequest.CurrencyType }
|
||||||
var value = Uri.UnescapeDataString(keyValue[1]);
|
}
|
||||||
|
);
|
||||||
|
await _notificationService.SendNotificationToPlayer(id, purchaseNotification);
|
||||||
|
}
|
||||||
|
catch (Exception notifEx)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error sending purchase notification: {notifEx.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
if (key == "GiftContext" && int.TryParse(value, out var context))
|
|
||||||
giftContext = context;
|
return Results.Ok(response);
|
||||||
else if (key == "IsGameGift")
|
}
|
||||||
isGameGift = value.Equals("true", StringComparison.OrdinalIgnoreCase);
|
catch (Exception ex)
|
||||||
else if (key == "Message")
|
{
|
||||||
message = value;
|
return Results.Problem($"Error processing purchase: {ex.Message}");
|
||||||
else if (key == "Xp" && int.TryParse(value, out var xpVal))
|
}
|
||||||
xp = xpVal;
|
}
|
||||||
}
|
|
||||||
|
[HttpPost("avatar/v2/gifts/generate")]
|
||||||
|
public async Task<IResult> GenerateGift(HttpRequest request, AppDbContext db, JwtTokenService jwtService)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
|
var accountId = jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
request.EnableBuffering();
|
||||||
|
request.Body.Position = 0;
|
||||||
|
using var reader = new StreamReader(request.Body);
|
||||||
|
var body = await reader.ReadToEndAsync();
|
||||||
|
|
||||||
|
int giftContext = 0;
|
||||||
|
bool isGameGift = false;
|
||||||
|
string message = "";
|
||||||
|
int xp = 0;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(body))
|
||||||
|
{
|
||||||
|
foreach (var pair in body.Split('&'))
|
||||||
|
{
|
||||||
|
var keyValue = pair.Split('=');
|
||||||
|
if (keyValue.Length == 2)
|
||||||
|
{
|
||||||
|
var key = Uri.UnescapeDataString(keyValue[0]);
|
||||||
|
var value = Uri.UnescapeDataString(keyValue[1]);
|
||||||
|
|
||||||
|
if (key == "GiftContext" && int.TryParse(value, out var context))
|
||||||
|
giftContext = context;
|
||||||
|
else if (key == "IsGameGift")
|
||||||
|
isGameGift = value.Equals("true", StringComparison.OrdinalIgnoreCase);
|
||||||
|
else if (key == "Message")
|
||||||
|
message = value;
|
||||||
|
else if (key == "Xp" && int.TryParse(value, out var xpVal))
|
||||||
|
xp = xpVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var earnableRewards = await db.EarnableRewards
|
var earnableRewards = await db.EarnableRewards
|
||||||
.Where(er => er.RewardContext == giftContext)
|
.Where(er => er.RewardContext == giftContext)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
var random = new Random();
|
var random = new Random();
|
||||||
string avatarItemDesc = "";
|
string avatarItemDesc = "";
|
||||||
string friendlyName = "";
|
string friendlyName = "";
|
||||||
int avatarItemType = 0;
|
int avatarItemType = 0;
|
||||||
int currencyType = 0;
|
int currencyType = 0;
|
||||||
int currency = 0;
|
int currency = 0;
|
||||||
int giftRarity = 0;
|
int giftRarity = 0;
|
||||||
string consumableItemDesc = "";
|
string consumableItemDesc = "";
|
||||||
|
|
||||||
bool isEarnableItem = random.Next(0, 100) < 60;
|
bool isEarnableItem = random.Next(0, 100) < 60;
|
||||||
|
|
||||||
if (isEarnableItem && earnableRewards.Any())
|
if (isEarnableItem && earnableRewards.Any())
|
||||||
|
{
|
||||||
|
var avatarRewards = earnableRewards.Where(er => !string.IsNullOrEmpty(er.AvatarItemDesc)).ToList();
|
||||||
|
|
||||||
|
if (avatarRewards.Any())
|
||||||
{
|
{
|
||||||
var avatarRewards = earnableRewards.Where(er => !string.IsNullOrEmpty(er.AvatarItemDesc)).ToList();
|
var ownedAvatarItems = await db.AvatarItems
|
||||||
|
.Where(ai => ai.OwnerAccountId == id)
|
||||||
|
.Select(ai => ai.AvatarItemDesc)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
if (avatarRewards.Any())
|
var unownedRewards = avatarRewards
|
||||||
|
.Where(ar => !ownedAvatarItems.Contains(ar.AvatarItemDesc))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (unownedRewards.Any())
|
||||||
{
|
{
|
||||||
var ownedAvatarItems = await db.AvatarItems
|
var selectedReward = unownedRewards[random.Next(unownedRewards.Count)];
|
||||||
.Where(ai => ai.OwnerAccountId == id)
|
avatarItemDesc = selectedReward.AvatarItemDesc;
|
||||||
.Select(ai => ai.AvatarItemDesc)
|
friendlyName = selectedReward.FriendlyName;
|
||||||
.ToListAsync();
|
avatarItemType = selectedReward.AvatarItemType;
|
||||||
|
giftRarity = selectedReward.GiftRarity;
|
||||||
var unownedRewards = avatarRewards
|
|
||||||
.Where(ar => !ownedAvatarItems.Contains(ar.AvatarItemDesc))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (unownedRewards.Any())
|
|
||||||
{
|
|
||||||
var selectedReward = unownedRewards[random.Next(unownedRewards.Count)];
|
|
||||||
avatarItemDesc = selectedReward.AvatarItemDesc;
|
|
||||||
friendlyName = selectedReward.FriendlyName;
|
|
||||||
avatarItemType = selectedReward.AvatarItemType;
|
|
||||||
giftRarity = selectedReward.GiftRarity;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isEarnableItem = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
isEarnableItem = false;
|
isEarnableItem = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (!isEarnableItem)
|
|
||||||
{
|
{
|
||||||
int[] tokenAmounts = {10, 25, 50, 100, 250, 500};
|
isEarnableItem = false;
|
||||||
currency = tokenAmounts[random.Next(tokenAmounts.Length)];
|
|
||||||
currencyType = 2;
|
|
||||||
giftRarity = 20;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var receivedGift = new ReceivedGift
|
|
||||||
{
|
|
||||||
ReceiverAccountId = id,
|
|
||||||
FromPlayerId = 1,
|
|
||||||
Message = message,
|
|
||||||
ConsumableItemDesc = consumableItemDesc,
|
|
||||||
AvatarItemDesc = avatarItemDesc,
|
|
||||||
FriendlyName = friendlyName,
|
|
||||||
AvatarItemType = avatarItemType,
|
|
||||||
EquipmentPrefabName = "",
|
|
||||||
EquipmentModificationGuid = "",
|
|
||||||
CurrencyType = currencyType,
|
|
||||||
Currency = currency,
|
|
||||||
Xp = xp,
|
|
||||||
Level = 0,
|
|
||||||
Platform = -1,
|
|
||||||
PlatformsToSpawnOn = -1,
|
|
||||||
BalanceType = 0,
|
|
||||||
GiftContext = giftContext,
|
|
||||||
GiftRarity = giftRarity,
|
|
||||||
ReceivedAt = DateTime.UtcNow,
|
|
||||||
IsConsumed = false
|
|
||||||
};
|
|
||||||
|
|
||||||
db.ReceivedGifts.Add(receivedGift);
|
|
||||||
await db.SaveChangesAsync();
|
|
||||||
|
|
||||||
var giftData = new
|
|
||||||
{
|
|
||||||
Id = receivedGift.Id,
|
|
||||||
FromPlayerId = 1,
|
|
||||||
ConsumableItemDesc = consumableItemDesc,
|
|
||||||
AvatarItemDesc = avatarItemDesc,
|
|
||||||
FriendlyName = friendlyName,
|
|
||||||
AvatarItemType = avatarItemType,
|
|
||||||
EquipmentPrefabName = "",
|
|
||||||
EquipmentModificationGuid = "",
|
|
||||||
CurrencyType = currencyType,
|
|
||||||
Currency = currency,
|
|
||||||
Xp = xp,
|
|
||||||
Level = 0,
|
|
||||||
Platform = -1,
|
|
||||||
PlatformsToSpawnOn = -1,
|
|
||||||
BalanceType = 0,
|
|
||||||
GiftContext = giftContext,
|
|
||||||
GiftRarity = giftRarity,
|
|
||||||
Message = message
|
|
||||||
};
|
|
||||||
|
|
||||||
return Results.Ok(giftData);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
|
if (!isEarnableItem)
|
||||||
{
|
{
|
||||||
return Results.Problem($"Error generating gift: {ex.Message}");
|
int[] tokenAmounts = {10, 25, 50, 100, 250, 500};
|
||||||
|
currency = tokenAmounts[random.Next(tokenAmounts.Length)];
|
||||||
|
currencyType = 2;
|
||||||
|
giftRarity = 20;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
app.MapPost("/api/avatar/v2/gifts/consume/", async (HttpRequest request, AppDbContext db, JwtTokenService jwtService) =>
|
var receivedGift = new ReceivedGift
|
||||||
|
{
|
||||||
|
ReceiverAccountId = id,
|
||||||
|
FromPlayerId = 1,
|
||||||
|
Message = message,
|
||||||
|
ConsumableItemDesc = consumableItemDesc,
|
||||||
|
AvatarItemDesc = avatarItemDesc,
|
||||||
|
FriendlyName = friendlyName,
|
||||||
|
AvatarItemType = avatarItemType,
|
||||||
|
EquipmentPrefabName = "",
|
||||||
|
EquipmentModificationGuid = "",
|
||||||
|
CurrencyType = currencyType,
|
||||||
|
Currency = currency,
|
||||||
|
Xp = xp,
|
||||||
|
Level = 0,
|
||||||
|
Platform = -1,
|
||||||
|
PlatformsToSpawnOn = -1,
|
||||||
|
BalanceType = 0,
|
||||||
|
GiftContext = giftContext,
|
||||||
|
GiftRarity = giftRarity,
|
||||||
|
ReceivedAt = DateTime.UtcNow,
|
||||||
|
IsConsumed = false
|
||||||
|
};
|
||||||
|
|
||||||
|
db.ReceivedGifts.Add(receivedGift);
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
|
var giftData = new
|
||||||
|
{
|
||||||
|
Id = receivedGift.Id,
|
||||||
|
FromPlayerId = 1,
|
||||||
|
ConsumableItemDesc = consumableItemDesc,
|
||||||
|
AvatarItemDesc = avatarItemDesc,
|
||||||
|
FriendlyName = friendlyName,
|
||||||
|
AvatarItemType = avatarItemType,
|
||||||
|
EquipmentPrefabName = "",
|
||||||
|
EquipmentModificationGuid = "",
|
||||||
|
CurrencyType = currencyType,
|
||||||
|
Currency = currency,
|
||||||
|
Xp = xp,
|
||||||
|
Level = 0,
|
||||||
|
Platform = -1,
|
||||||
|
PlatformsToSpawnOn = -1,
|
||||||
|
BalanceType = 0,
|
||||||
|
GiftContext = giftContext,
|
||||||
|
GiftRarity = giftRarity,
|
||||||
|
Message = message
|
||||||
|
};
|
||||||
|
|
||||||
|
return Results.Ok(giftData);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
try
|
return Results.Problem($"Error generating gift: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("avatar/v2/gifts/consume/")]
|
||||||
|
public async Task<IResult> ConsumeGift(HttpRequest request, AppDbContext db, JwtTokenService jwtService)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
|
var accountId = jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
request.EnableBuffering();
|
||||||
|
request.Body.Position = 0;
|
||||||
|
using var reader = new StreamReader(request.Body);
|
||||||
|
var body = await reader.ReadToEndAsync();
|
||||||
|
|
||||||
|
var giftId = 0;
|
||||||
|
var unlockedLevel = 0;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(body))
|
||||||
{
|
{
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
foreach (var pair in body.Split('&'))
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
request.EnableBuffering();
|
|
||||||
request.Body.Position = 0;
|
|
||||||
using var reader = new StreamReader(request.Body);
|
|
||||||
var body = await reader.ReadToEndAsync();
|
|
||||||
|
|
||||||
var giftId = 0;
|
|
||||||
var unlockedLevel = 0;
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(body))
|
|
||||||
{
|
{
|
||||||
foreach (var pair in body.Split('&'))
|
var keyValue = pair.Split('=');
|
||||||
|
if (keyValue.Length == 2)
|
||||||
{
|
{
|
||||||
var keyValue = pair.Split('=');
|
if (keyValue[0] == "Id")
|
||||||
if (keyValue.Length == 2)
|
int.TryParse(Uri.UnescapeDataString(keyValue[1]), out giftId);
|
||||||
{
|
else if (keyValue[0] == "UnlockedLevel")
|
||||||
if (keyValue[0] == "Id")
|
int.TryParse(Uri.UnescapeDataString(keyValue[1]), out unlockedLevel);
|
||||||
int.TryParse(Uri.UnescapeDataString(keyValue[1]), out giftId);
|
|
||||||
else if (keyValue[0] == "UnlockedLevel")
|
|
||||||
int.TryParse(Uri.UnescapeDataString(keyValue[1]), out unlockedLevel);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (giftId == 0)
|
if (giftId == 0)
|
||||||
|
{
|
||||||
|
return Results.BadRequest(new { success = false, error = "Invalid gift ID" });
|
||||||
|
}
|
||||||
|
|
||||||
|
var receivedGift = await db.ReceivedGifts
|
||||||
|
.FirstOrDefaultAsync(rg => rg.Id == giftId && rg.ReceiverAccountId == id);
|
||||||
|
|
||||||
|
if (receivedGift == null)
|
||||||
|
{
|
||||||
|
return Results.NotFound(new { success = false, error = "Gift not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(receivedGift.ConsumableItemDesc))
|
||||||
|
{
|
||||||
|
var existingConsumable = await db.ConsumableItems
|
||||||
|
.FirstOrDefaultAsync(c => c.OwnerAccountId == id && c.ConsumableItemDesc == receivedGift.ConsumableItemDesc);
|
||||||
|
|
||||||
|
if (existingConsumable == null)
|
||||||
{
|
{
|
||||||
return Results.BadRequest(new { success = false, error = "Invalid gift ID" });
|
var newConsumable = new ConsumableItem
|
||||||
}
|
|
||||||
|
|
||||||
var receivedGift = await db.ReceivedGifts
|
|
||||||
.FirstOrDefaultAsync(rg => rg.Id == giftId && rg.ReceiverAccountId == id);
|
|
||||||
|
|
||||||
if (receivedGift == null)
|
|
||||||
{
|
|
||||||
return Results.NotFound(new { success = false, error = "Gift not found" });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(receivedGift.ConsumableItemDesc))
|
|
||||||
{
|
|
||||||
var existingConsumable = await db.ConsumableItems
|
|
||||||
.FirstOrDefaultAsync(c => c.OwnerAccountId == id && c.ConsumableItemDesc == receivedGift.ConsumableItemDesc);
|
|
||||||
|
|
||||||
if (existingConsumable == null)
|
|
||||||
{
|
|
||||||
var newConsumable = new ConsumableItem
|
|
||||||
{
|
|
||||||
OwnerAccountId = id,
|
|
||||||
Ids = new List<int> { giftId },
|
|
||||||
CreatedAts = new List<DateTime> { DateTime.UtcNow },
|
|
||||||
ConsumableItemDesc = receivedGift.ConsumableItemDesc,
|
|
||||||
Count = 1,
|
|
||||||
InitialCount = 1,
|
|
||||||
IsActive = false,
|
|
||||||
ActiveDurationMinutes = 0,
|
|
||||||
IsTransferable = false
|
|
||||||
};
|
|
||||||
db.ConsumableItems.Add(newConsumable);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
existingConsumable.Ids.Add(giftId);
|
|
||||||
existingConsumable.CreatedAts.Add(DateTime.UtcNow);
|
|
||||||
existingConsumable.Count += 1;
|
|
||||||
db.ConsumableItems.Update(existingConsumable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(receivedGift.AvatarItemDesc))
|
|
||||||
{
|
|
||||||
var avatarItem = new AvatarItem
|
|
||||||
{
|
{
|
||||||
OwnerAccountId = id,
|
OwnerAccountId = id,
|
||||||
AvatarItemDesc = receivedGift.AvatarItemDesc,
|
Ids = new List<int> { giftId },
|
||||||
FriendlyName = receivedGift.FriendlyName ?? ""
|
CreatedAts = new List<DateTime> { DateTime.UtcNow },
|
||||||
|
ConsumableItemDesc = receivedGift.ConsumableItemDesc,
|
||||||
|
Count = 1,
|
||||||
|
InitialCount = 1,
|
||||||
|
IsActive = false,
|
||||||
|
ActiveDurationMinutes = 0,
|
||||||
|
IsTransferable = false
|
||||||
};
|
};
|
||||||
db.AvatarItems.Add(avatarItem);
|
db.ConsumableItems.Add(newConsumable);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (!string.IsNullOrEmpty(receivedGift.Currency.ToString()) && receivedGift.CurrencyType == 2)
|
|
||||||
{
|
{
|
||||||
var tokenBalance = await db.TokenBalances
|
existingConsumable.Ids.Add(giftId);
|
||||||
.FirstOrDefaultAsync(tb => tb.Id == id &&
|
existingConsumable.CreatedAts.Add(DateTime.UtcNow);
|
||||||
tb.CurrencyType == receivedGift.CurrencyType &&
|
existingConsumable.Count += 1;
|
||||||
tb.BalanceType == -1);
|
db.ConsumableItems.Update(existingConsumable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (tokenBalance == null)
|
if (!string.IsNullOrEmpty(receivedGift.AvatarItemDesc))
|
||||||
|
{
|
||||||
|
var avatarItem = new AvatarItem
|
||||||
|
{
|
||||||
|
OwnerAccountId = id,
|
||||||
|
AvatarItemDesc = receivedGift.AvatarItemDesc,
|
||||||
|
FriendlyName = receivedGift.FriendlyName ?? ""
|
||||||
|
};
|
||||||
|
db.AvatarItems.Add(avatarItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(receivedGift.Currency.ToString()) && receivedGift.CurrencyType == 2)
|
||||||
|
{
|
||||||
|
var tokenBalance = await db.TokenBalances
|
||||||
|
.FirstOrDefaultAsync(tb => tb.Id == id &&
|
||||||
|
tb.CurrencyType == receivedGift.CurrencyType &&
|
||||||
|
tb.BalanceType == -1);
|
||||||
|
|
||||||
|
if (tokenBalance == null)
|
||||||
|
{
|
||||||
|
tokenBalance = new TokenBalance
|
||||||
{
|
{
|
||||||
tokenBalance = new TokenBalance
|
Id = id,
|
||||||
{
|
CurrencyType = receivedGift.CurrencyType,
|
||||||
Id = id,
|
BalanceType = -1,
|
||||||
CurrencyType = receivedGift.CurrencyType,
|
Balance = receivedGift.Currency
|
||||||
BalanceType = -1,
|
};
|
||||||
Balance = receivedGift.Currency
|
db.TokenBalances.Add(tokenBalance);
|
||||||
};
|
}
|
||||||
db.TokenBalances.Add(tokenBalance);
|
else
|
||||||
}
|
{
|
||||||
else
|
tokenBalance.Balance += receivedGift.Currency;
|
||||||
{
|
db.TokenBalances.Update(tokenBalance);
|
||||||
tokenBalance.Balance += receivedGift.Currency;
|
|
||||||
db.TokenBalances.Update(tokenBalance);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
receivedGift.IsConsumed = true;
|
|
||||||
receivedGift.ConsumedAt = DateTime.UtcNow;
|
|
||||||
db.ReceivedGifts.Update(receivedGift);
|
|
||||||
|
|
||||||
await db.SaveChangesAsync();
|
|
||||||
|
|
||||||
return Results.Ok(RecNetResult.Ok());
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
receivedGift.IsConsumed = true;
|
||||||
return Results.Problem($"Error consuming gift: {ex.Message}");
|
receivedGift.ConsumedAt = DateTime.UtcNow;
|
||||||
}
|
db.ReceivedGifts.Update(receivedGift);
|
||||||
});
|
|
||||||
app.MapGet("/api/rooms/v1/filters", async (HttpRequest request, AppDbContext db) =>
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
|
return Results.Ok(RecNetResult.Ok());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
var json = File.ReadAllText("JSON/roomfilters.json");
|
return Results.Problem($"Error consuming gift: {ex.Message}");
|
||||||
return Results.Content(json, "application/json");
|
}
|
||||||
});
|
}
|
||||||
app.MapGet("/roomserver/rooms/{id}/interactionby/me", async (HttpRequest request, AppDbContext db, string id) =>
|
|
||||||
|
[HttpGet("rooms/v1/filters")]
|
||||||
|
public async Task<IResult> GetRoomFilters(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
var json = System.IO.File.ReadAllText("JSON/roomfilters.json");
|
||||||
|
return Results.Content(json, "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("/roomserver/rooms/{id}/interactionby/me")]
|
||||||
|
public async Task<IResult> GetInteractionByMe(HttpRequest request, AppDbContext db, string id)
|
||||||
|
{
|
||||||
|
// TODO: implement
|
||||||
|
return Results.Content("{\"Cheered\":false,\"Favorited\":false}", "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("images/v4/uploadsaved")]
|
||||||
|
public async Task<IResult> UploadSavedImage()
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
// TODO: implement
|
var form = await Request.ReadFormAsync();
|
||||||
return Results.Content("{\"Cheered\":false,\"Favorited\":false}", "application/json");
|
var file = form.Files.FirstOrDefault();
|
||||||
});
|
|
||||||
app.MapPost("/api/images/v4/uploadsaved", async (HttpContext context) =>
|
if (file == null)
|
||||||
|
{
|
||||||
|
return Results.BadRequest(new { error = "No file found in request" });
|
||||||
|
}
|
||||||
|
|
||||||
|
var imageId = Guid.NewGuid().ToString("N");
|
||||||
|
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
|
||||||
|
|
||||||
|
var validExtensions = new[] { ".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp" };
|
||||||
|
if (string.IsNullOrEmpty(extension) || !validExtensions.Contains(extension))
|
||||||
|
{
|
||||||
|
extension = ".png";
|
||||||
|
}
|
||||||
|
|
||||||
|
var savedFileName = imageId + extension;
|
||||||
|
var filePath = Path.Combine(ImagesDir, savedFileName);
|
||||||
|
|
||||||
|
using (var fileStream = System.IO.File.Create(filePath))
|
||||||
|
{
|
||||||
|
await file.CopyToAsync(fileStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Results.Ok(new
|
||||||
|
{
|
||||||
|
ImageName = savedFileName
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
try
|
return Results.Problem($"Error uploading image: {ex.Message}");
|
||||||
{
|
}
|
||||||
var form = await context.Request.ReadFormAsync();
|
|
||||||
var file = form.Files.FirstOrDefault();
|
|
||||||
|
|
||||||
if (file == null)
|
|
||||||
{
|
|
||||||
return Results.BadRequest(new { error = "No file found in request" });
|
|
||||||
}
|
|
||||||
|
|
||||||
var imageId = Guid.NewGuid().ToString("N");
|
|
||||||
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
|
|
||||||
|
|
||||||
var validExtensions = new[] { ".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp" };
|
|
||||||
if (string.IsNullOrEmpty(extension) || !validExtensions.Contains(extension))
|
|
||||||
{
|
|
||||||
extension = ".png";
|
|
||||||
}
|
|
||||||
|
|
||||||
var savedFileName = imageId + extension;
|
|
||||||
var filePath = Path.Combine(ImagesDir, savedFileName);
|
|
||||||
|
|
||||||
using (var fileStream = File.Create(filePath))
|
|
||||||
{
|
|
||||||
await file.CopyToAsync(fileStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Results.Ok(new
|
|
||||||
{
|
|
||||||
ImageName = savedFileName
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return Results.Problem($"Error uploading image: {ex.Message}");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static object[]? TryDeserializeTags(string json)
|
private static object[]? TryDeserializeTags(string json)
|
||||||
@@ -1874,3 +1960,5 @@ public class APIController
|
|||||||
ImagesDir = dir;
|
ImagesDir = dir;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,512 +1,507 @@
|
|||||||
using CannedNet.Data;
|
using CannedNet.Data;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using CannedNet.Services;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using CannedNet.Services.Infrastructure;
|
|
||||||
|
|
||||||
namespace CannedNet.Services.Controllers;
|
namespace CannedNet.Services.Controllers;
|
||||||
|
|
||||||
public class AccountsController
|
[ApiController]
|
||||||
|
public class AccountsController : ControllerBase
|
||||||
{
|
{
|
||||||
public WebApplicationBuilder Initialize(string[]? args = null) => ServiceExtensions.CreateRecNetBuilder(args);
|
[HttpGet("/account/me")]
|
||||||
|
public async Task<IResult> AccountMe(HttpRequest request, AppDbContext db, JwtTokenService jwtService)
|
||||||
public void MapEndpoints(WebApplication app, JwtTokenService jwtService)
|
|
||||||
{
|
{
|
||||||
app.MapGet("/", (HttpRequest request) =>
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
|
var accountId = jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(accountId))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
if (!int.TryParse(accountId.AsSpan(), out var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var account = await db.Accounts.FindAsync(id);
|
||||||
|
if (account == null)
|
||||||
|
return Results.NotFound();
|
||||||
|
|
||||||
|
var selfAccount = new SelfAccount
|
||||||
{
|
{
|
||||||
return Results.Ok("FUCKL MYSJDIOJD");
|
AccountId = id,
|
||||||
});
|
ProfileImage = account.ProfileImage ?? "hdqeamlcmatc6qzoi2ybgf0ddijjcf.jpg",
|
||||||
|
IsJunior = account.IsJunior,
|
||||||
|
Platforms = account.Platforms ?? 0,
|
||||||
|
PersonalPronouns = account.PersonalPronouns ?? 0,
|
||||||
|
IdentityFlags = account.IdentityFlags ?? 0,
|
||||||
|
Username = account.Username ?? $"Player{id}",
|
||||||
|
DisplayName = account.DisplayName ?? $"Player{id}",
|
||||||
|
CreatedAt = account.CreatedAt,
|
||||||
|
Email = null,
|
||||||
|
Phone = null,
|
||||||
|
JuniorState = null,
|
||||||
|
Birthday = null,
|
||||||
|
ParentAccountId = null,
|
||||||
|
AvailableUsernameChanges = 1
|
||||||
|
};
|
||||||
|
|
||||||
app.MapGet("/account/me", async (HttpRequest request, AppDbContext db) =>
|
return Results.Ok(selfAccount);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("/account/bulk")]
|
||||||
|
public async Task<IResult> AccountBulk(HttpRequest request, AppDbContext db)
|
||||||
|
{
|
||||||
|
var ids = request.Query["id"];
|
||||||
|
var accountIds = new List<int>();
|
||||||
|
|
||||||
|
foreach (var id in ids)
|
||||||
{
|
{
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
if (int.TryParse(id, out var accountId))
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var account = await db.Accounts.FindAsync(id);
|
|
||||||
if (account == null)
|
|
||||||
return Results.NotFound();
|
|
||||||
|
|
||||||
var selfAccount = new SelfAccount
|
|
||||||
{
|
{
|
||||||
AccountId = id,
|
accountIds.Add(accountId);
|
||||||
ProfileImage = account.ProfileImage ?? "hdqeamlcmatc6qzoi2ybgf0ddijjcf.jpg",
|
|
||||||
IsJunior = account.IsJunior,
|
|
||||||
Platforms = account.Platforms ?? 0,
|
|
||||||
PersonalPronouns = account.PersonalPronouns ?? 0,
|
|
||||||
IdentityFlags = account.IdentityFlags ?? 0,
|
|
||||||
Username = account.Username ?? $"Player{id}",
|
|
||||||
DisplayName = account.DisplayName ?? $"Player{id}",
|
|
||||||
CreatedAt = account.CreatedAt,
|
|
||||||
Email = null,
|
|
||||||
Phone = null,
|
|
||||||
JuniorState = null,
|
|
||||||
Birthday = null,
|
|
||||||
ParentAccountId = null,
|
|
||||||
AvailableUsernameChanges = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
return Results.Ok(selfAccount);
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapGet("/account/bulk", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var ids = request.Query["id"];
|
|
||||||
var accountIds = new List<int>();
|
|
||||||
|
|
||||||
foreach (var id in ids)
|
|
||||||
{
|
|
||||||
if (int.TryParse(id, out var accountId))
|
|
||||||
{
|
|
||||||
accountIds.Add(accountId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var accounts = await db.Accounts
|
var accounts = await db.Accounts
|
||||||
.Where(a => accountIds.Contains(a.AccountId.Value))
|
.Where(a => accountIds.Contains(a.AccountId.Value))
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
var result = accounts.Select(a => new Account
|
var result = accounts.Select(a => new Account
|
||||||
{
|
|
||||||
AccountId = a.AccountId,
|
|
||||||
ProfileImage = a.ProfileImage ?? "DefaultProfileImage.jpg",
|
|
||||||
IsJunior = a.IsJunior,
|
|
||||||
Platforms = a.Platforms ?? 0,
|
|
||||||
PersonalPronouns = a.PersonalPronouns ?? 0,
|
|
||||||
IdentityFlags = a.IdentityFlags ?? 0,
|
|
||||||
Username = a.Username ?? $"Player{a.AccountId}",
|
|
||||||
DisplayName = a.DisplayName ?? $"Player{a.AccountId}",
|
|
||||||
CreatedAt = a.CreatedAt
|
|
||||||
}).ToList();
|
|
||||||
|
|
||||||
return Results.Json(result);
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapGet("/account/{id}", async (HttpRequest request, string id, AppDbContext db) =>
|
|
||||||
{
|
{
|
||||||
if (!int.TryParse(id, out var accountId))
|
AccountId = a.AccountId,
|
||||||
return Results.BadRequest();
|
ProfileImage = a.ProfileImage ?? "DefaultProfileImage.jpg",
|
||||||
|
IsJunior = a.IsJunior,
|
||||||
|
Platforms = a.Platforms ?? 0,
|
||||||
|
PersonalPronouns = a.PersonalPronouns ?? 0,
|
||||||
|
IdentityFlags = a.IdentityFlags ?? 0,
|
||||||
|
Username = a.Username ?? $"Player{a.AccountId}",
|
||||||
|
DisplayName = a.DisplayName ?? $"Player{a.AccountId}",
|
||||||
|
CreatedAt = a.CreatedAt
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
var account = await db.Accounts.FindAsync(accountId);
|
return Results.Json(result);
|
||||||
if (account == null)
|
}
|
||||||
return Results.NotFound();
|
|
||||||
|
|
||||||
var result = new Account
|
[HttpGet("/account/{id}")]
|
||||||
{
|
public async Task<IResult> AccountById(string id, AppDbContext db)
|
||||||
AccountId = account.AccountId,
|
{
|
||||||
ProfileImage = account.ProfileImage ?? "DefaultProfileImage.jpg",
|
if (!int.TryParse(id, out var accountId))
|
||||||
IsJunior = account.IsJunior,
|
return Results.BadRequest();
|
||||||
Platforms = account.Platforms ?? 0,
|
|
||||||
PersonalPronouns = account.PersonalPronouns ?? 0,
|
|
||||||
IdentityFlags = account.IdentityFlags ?? 0,
|
|
||||||
Username = account.Username ?? $"Player{account.AccountId}",
|
|
||||||
DisplayName = account.DisplayName ?? $"Player{account.AccountId}",
|
|
||||||
CreatedAt = account.CreatedAt
|
|
||||||
};
|
|
||||||
|
|
||||||
return Results.Json(result);
|
var account = await db.Accounts.FindAsync(accountId);
|
||||||
});
|
if (account == null)
|
||||||
|
return Results.NotFound();
|
||||||
|
|
||||||
app.MapPost("/account/create", async (HttpRequest httpRequest, AppDbContext db) =>
|
var result = new Account
|
||||||
{
|
{
|
||||||
int platform = 0;
|
AccountId = account.AccountId,
|
||||||
string platformId = "";
|
ProfileImage = account.ProfileImage ?? "DefaultProfileImage.jpg",
|
||||||
|
IsJunior = account.IsJunior,
|
||||||
|
Platforms = account.Platforms ?? 0,
|
||||||
|
PersonalPronouns = account.PersonalPronouns ?? 0,
|
||||||
|
IdentityFlags = account.IdentityFlags ?? 0,
|
||||||
|
Username = account.Username ?? $"Player{account.AccountId}",
|
||||||
|
DisplayName = account.DisplayName ?? $"Player{account.AccountId}",
|
||||||
|
CreatedAt = account.CreatedAt
|
||||||
|
};
|
||||||
|
|
||||||
if (httpRequest.ContentLength.HasValue && httpRequest.ContentLength > 0)
|
return Results.Json(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("/account/create")]
|
||||||
|
public async Task<IResult> AccountCreate(HttpRequest httpRequest, AppDbContext db)
|
||||||
|
{
|
||||||
|
int platform = 0;
|
||||||
|
string platformId = "";
|
||||||
|
|
||||||
|
if (httpRequest.ContentLength.HasValue && httpRequest.ContentLength > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
try
|
var contentType = httpRequest.ContentType ?? "";
|
||||||
|
httpRequest.EnableBuffering();
|
||||||
|
|
||||||
|
using var reader = new StreamReader(httpRequest.Body, leaveOpen: true);
|
||||||
|
var body = await reader.ReadToEndAsync();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(body) && contentType.Contains("application/x-www-form-urlencoded"))
|
||||||
{
|
{
|
||||||
var contentType = httpRequest.ContentType ?? "";
|
foreach (var pair in body.Split('&'))
|
||||||
httpRequest.EnableBuffering();
|
|
||||||
|
|
||||||
using var reader = new StreamReader(httpRequest.Body, leaveOpen: true);
|
|
||||||
var body = await reader.ReadToEndAsync();
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(body) && contentType.Contains("application/x-www-form-urlencoded"))
|
|
||||||
{
|
{
|
||||||
foreach (var pair in body.Split('&'))
|
var keyValue = pair.Split('=');
|
||||||
|
if (keyValue.Length == 2)
|
||||||
{
|
{
|
||||||
var keyValue = pair.Split('=');
|
var key = Uri.UnescapeDataString(keyValue[0]);
|
||||||
if (keyValue.Length == 2)
|
var value = Uri.UnescapeDataString(keyValue[1]);
|
||||||
{
|
|
||||||
var key = Uri.UnescapeDataString(keyValue[0]);
|
|
||||||
var value = Uri.UnescapeDataString(keyValue[1]);
|
|
||||||
|
|
||||||
if (key == "platform" && int.TryParse(value, out var parsedPlatform))
|
if (key == "platform" && int.TryParse(value, out var parsedPlatform))
|
||||||
platform = parsedPlatform;
|
platform = parsedPlatform;
|
||||||
else if (key == "platformId")
|
else if (key == "platformId")
|
||||||
platformId = value;
|
platformId = value;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
httpRequest.Body.Position = 0;
|
|
||||||
}
|
}
|
||||||
catch { }
|
httpRequest.Body.Position = 0;
|
||||||
}
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
var accountId = new Random().Next(10000, 99999);
|
var newAccountId = new Random().Next(10000, 99999);
|
||||||
var account = new Account
|
var account = new Account
|
||||||
|
{
|
||||||
|
AccountId = newAccountId,
|
||||||
|
ProfileImage = "DefaultProfileImage.jpg",
|
||||||
|
IsJunior = false,
|
||||||
|
Platforms = 0,
|
||||||
|
PersonalPronouns = 0,
|
||||||
|
IdentityFlags = 0,
|
||||||
|
Username = $"Player{newAccountId}",
|
||||||
|
DisplayName = $"Player{newAccountId}",
|
||||||
|
CreatedAt = DateTime.UtcNow
|
||||||
|
};
|
||||||
|
|
||||||
|
db.Accounts.Add(account);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(platformId))
|
||||||
|
{
|
||||||
|
db.CachedLogins.Add(new CachedLogin
|
||||||
{
|
{
|
||||||
AccountId = accountId,
|
AccountId = newAccountId,
|
||||||
ProfileImage = "DefaultProfileImage.jpg",
|
Platform = (PlatformType)platform,
|
||||||
IsJunior = false,
|
PlatformID = platformId,
|
||||||
Platforms = 0,
|
LastLoginTime = DateTime.UtcNow,
|
||||||
PersonalPronouns = 0,
|
RequirePassword = false
|
||||||
IdentityFlags = 0,
|
});
|
||||||
Username = $"Player{accountId}",
|
}
|
||||||
DisplayName = $"Player{accountId}",
|
|
||||||
CreatedAt = DateTime.UtcNow
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
|
var maxRoomId = await db.Rooms.MaxAsync(r => (int?)r.RoomId) ?? 0;
|
||||||
|
var maxId = await db.Rooms.MaxAsync(r => (int?)r.Id) ?? 0;
|
||||||
|
var dormRoomId = maxRoomId + 1;
|
||||||
|
var dormRoom = new Room
|
||||||
|
{
|
||||||
|
Id = maxId + 1,
|
||||||
|
RoomId = dormRoomId,
|
||||||
|
Name = "DormRoom",
|
||||||
|
Description = "Your personal room",
|
||||||
|
CreatorAccountId = newAccountId,
|
||||||
|
ImageName = "",
|
||||||
|
State = 0,
|
||||||
|
Accessibility = 0,
|
||||||
|
SupportsLevelVoting = false,
|
||||||
|
IsRRO = false,
|
||||||
|
IsDorm = true,
|
||||||
|
CloningAllowed = false,
|
||||||
|
SupportsVRLow = true,
|
||||||
|
SupportsQuest2 = true,
|
||||||
|
SupportsMobile = true,
|
||||||
|
SupportsScreens = true,
|
||||||
|
SupportsWalkVR = true,
|
||||||
|
SupportsTeleportVR = true,
|
||||||
|
SupportsJuniors = true,
|
||||||
|
MinLevel = 0,
|
||||||
|
WarningMask = 0,
|
||||||
|
CustomWarning = null,
|
||||||
|
DisableMicAutoMute = false,
|
||||||
|
DisableRoomComments = false,
|
||||||
|
EncryptVoiceChat = false,
|
||||||
|
CreatedAt = DateTime.UtcNow,
|
||||||
|
Tags = "[]"
|
||||||
|
};
|
||||||
|
db.Rooms.Add(dormRoom);
|
||||||
|
|
||||||
|
var dormSubRoom = new SubRoom
|
||||||
|
{
|
||||||
|
RoomId = dormRoomId,
|
||||||
|
SubRoomId = 1,
|
||||||
|
Name = "DormRoom",
|
||||||
|
DataBlob = "",
|
||||||
|
IsSandbox = false,
|
||||||
|
MaxPlayers = 4,
|
||||||
|
Accessibility = 0,
|
||||||
|
UnitySceneId = "76d98498-60a1-430c-ab76-b54a29b7a163",
|
||||||
|
DataSavedAt = DateTime.UtcNow
|
||||||
|
};
|
||||||
|
db.SubRooms.Add(dormSubRoom);
|
||||||
|
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
|
return Results.Ok(RecNetResultWithValue<Account>.Ok(account));
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("/parentalcontrol/me")]
|
||||||
|
public IResult ParentalControlMe(HttpRequest request, JwtTokenService jwtService)
|
||||||
|
{
|
||||||
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
|
var accountId = jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(accountId))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
return Results.Content($"{{\"accountId\":{accountId},\"disallowInAppPurchases\":false}}", "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("/account/me/displayname")]
|
||||||
|
public async Task<IResult> UpdateDisplayName(HttpRequest request, AppDbContext db, JwtTokenService jwtService)
|
||||||
|
{
|
||||||
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
|
var accountId = jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(accountId))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
if (!int.TryParse(accountId.AsSpan(), out var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
string newDisplayName = "";
|
||||||
|
|
||||||
|
if (request.ContentLength.HasValue && request.ContentLength > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
request.EnableBuffering();
|
||||||
|
using var reader = new StreamReader(request.Body, leaveOpen: true);
|
||||||
|
var body = await reader.ReadToEndAsync();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(body))
|
||||||
|
{
|
||||||
|
foreach (var pair in body.Split('&'))
|
||||||
|
{
|
||||||
|
var keyValue = pair.Split('=');
|
||||||
|
if (keyValue.Length == 2)
|
||||||
|
{
|
||||||
|
var key = Uri.UnescapeDataString(keyValue[0]);
|
||||||
|
var value = Uri.UnescapeDataString(keyValue[1]);
|
||||||
|
|
||||||
|
if (key == "displayName")
|
||||||
|
newDisplayName = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request.Body.Position = 0;
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
var account = await db.Accounts.FindAsync(id);
|
||||||
|
if (account == null)
|
||||||
|
return Results.NotFound();
|
||||||
|
|
||||||
|
account.DisplayName = newDisplayName;
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
|
return Results.Ok(RecNetResult.Ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("/account/me/username")]
|
||||||
|
public async Task<IResult> UpdateUsername(HttpRequest request, AppDbContext db, JwtTokenService jwtService)
|
||||||
|
{
|
||||||
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
|
var accountId = jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(accountId))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
if (!int.TryParse(accountId.AsSpan(), out var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
string newAccountName = "";
|
||||||
|
|
||||||
|
if (request.ContentLength.HasValue && request.ContentLength > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
request.EnableBuffering();
|
||||||
|
using var reader = new StreamReader(request.Body, leaveOpen: true);
|
||||||
|
var body = await reader.ReadToEndAsync();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(body))
|
||||||
|
{
|
||||||
|
foreach (var pair in body.Split('&'))
|
||||||
|
{
|
||||||
|
var keyValue = pair.Split('=');
|
||||||
|
if (keyValue.Length == 2)
|
||||||
|
{
|
||||||
|
var key = Uri.UnescapeDataString(keyValue[0]);
|
||||||
|
var value = Uri.UnescapeDataString(keyValue[1]);
|
||||||
|
|
||||||
|
if (key == "username")
|
||||||
|
newAccountName = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request.Body.Position = 0;
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
var account = await db.Accounts.FindAsync(id);
|
||||||
|
if (account == null)
|
||||||
|
return Results.NotFound();
|
||||||
|
|
||||||
|
account.Username = newAccountName;
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
|
return Results.Ok(RecNetResult.Ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("/account/{id}/bio")]
|
||||||
|
public async Task<IResult> GetAccountBio(string id, AppDbContext db)
|
||||||
|
{
|
||||||
|
if (!int.TryParse(id, out var accountId))
|
||||||
|
return Results.BadRequest();
|
||||||
|
|
||||||
|
var bio = await db.PlayerBios.FirstOrDefaultAsync(b => b.accountId == accountId);
|
||||||
|
|
||||||
|
if (bio == null)
|
||||||
|
{
|
||||||
|
return Results.Json(new { accountId = accountId, bio = "" });
|
||||||
|
}
|
||||||
|
|
||||||
|
return Results.Json(new { accountId = bio.accountId, bio = bio.bio });
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("/account/me/bio")]
|
||||||
|
public async Task<IResult> UpdateBio(HttpRequest request, AppDbContext db, JwtTokenService jwtService)
|
||||||
|
{
|
||||||
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
|
var accountId = jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(accountId))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
if (!int.TryParse(accountId.AsSpan(), out var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
string newBio = "";
|
||||||
|
|
||||||
|
if (request.ContentLength.HasValue && request.ContentLength > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
request.EnableBuffering();
|
||||||
|
using var reader = new StreamReader(request.Body, leaveOpen: true);
|
||||||
|
var body = await reader.ReadToEndAsync();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(body))
|
||||||
|
{
|
||||||
|
foreach (var pair in body.Split('&'))
|
||||||
|
{
|
||||||
|
var keyValue = pair.Split('=');
|
||||||
|
if (keyValue.Length == 2)
|
||||||
|
{
|
||||||
|
var key = Uri.UnescapeDataString(keyValue[0]);
|
||||||
|
var value = Uri.UnescapeDataString(keyValue[1]);
|
||||||
|
|
||||||
|
if (key == "bio")
|
||||||
|
newBio = Uri.UnescapeDataString(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request.Body.Position = 0;
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
var bio = await db.PlayerBios.FirstOrDefaultAsync(b => b.accountId == id);
|
||||||
|
|
||||||
|
if (bio == null)
|
||||||
|
{
|
||||||
|
bio = new PlayerBio
|
||||||
|
{
|
||||||
|
accountId = id,
|
||||||
|
bio = newBio
|
||||||
};
|
};
|
||||||
|
db.PlayerBios.Add(bio);
|
||||||
db.Accounts.Add(account);
|
}
|
||||||
|
else
|
||||||
if (!string.IsNullOrEmpty(platformId))
|
|
||||||
{
|
|
||||||
db.CachedLogins.Add(new CachedLogin
|
|
||||||
{
|
|
||||||
AccountId = accountId,
|
|
||||||
Platform = (PlatformType)platform,
|
|
||||||
PlatformID = platformId,
|
|
||||||
LastLoginTime = DateTime.UtcNow,
|
|
||||||
RequirePassword = false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
await db.SaveChangesAsync();
|
|
||||||
|
|
||||||
// create players dorm room
|
|
||||||
var maxRoomId = await db.Rooms.MaxAsync(r => (int?)r.RoomId) ?? 0;
|
|
||||||
var maxId = await db.Rooms.MaxAsync(r => (int?)r.Id) ?? 0;
|
|
||||||
var dormRoomId = maxRoomId + 1;
|
|
||||||
var dormId = maxId + 1;
|
|
||||||
var dormRoom = new Room
|
|
||||||
{
|
|
||||||
Id = maxId + 1,
|
|
||||||
RoomId = dormRoomId,
|
|
||||||
Name = "DormRoom",
|
|
||||||
Description = "Your personal room",
|
|
||||||
CreatorAccountId = accountId,
|
|
||||||
ImageName = "",
|
|
||||||
State = 0,
|
|
||||||
Accessibility = 0,
|
|
||||||
SupportsLevelVoting = false,
|
|
||||||
IsRRO = false,
|
|
||||||
IsDorm = true,
|
|
||||||
CloningAllowed = false,
|
|
||||||
SupportsVRLow = true,
|
|
||||||
SupportsQuest2 = true,
|
|
||||||
SupportsMobile = true,
|
|
||||||
SupportsScreens = true,
|
|
||||||
SupportsWalkVR = true,
|
|
||||||
SupportsTeleportVR = true,
|
|
||||||
SupportsJuniors = true,
|
|
||||||
MinLevel = 0,
|
|
||||||
WarningMask = 0,
|
|
||||||
CustomWarning = null,
|
|
||||||
DisableMicAutoMute = false,
|
|
||||||
DisableRoomComments = false,
|
|
||||||
EncryptVoiceChat = false,
|
|
||||||
CreatedAt = DateTime.UtcNow,
|
|
||||||
Tags = "[]"
|
|
||||||
};
|
|
||||||
db.Rooms.Add(dormRoom);
|
|
||||||
|
|
||||||
// Create a sub room for the dorm
|
|
||||||
var dormSubRoom = new SubRoom
|
|
||||||
{
|
|
||||||
RoomId = dormRoomId,
|
|
||||||
SubRoomId = 1,
|
|
||||||
Name = "DormRoom",
|
|
||||||
DataBlob = "",
|
|
||||||
IsSandbox = false,
|
|
||||||
MaxPlayers = 4,
|
|
||||||
Accessibility = 0,
|
|
||||||
UnitySceneId = "76d98498-60a1-430c-ab76-b54a29b7a163", // Dorm scene ID
|
|
||||||
DataSavedAt = DateTime.UtcNow
|
|
||||||
};
|
|
||||||
db.SubRooms.Add(dormSubRoom);
|
|
||||||
|
|
||||||
await db.SaveChangesAsync();
|
|
||||||
|
|
||||||
return Results.Ok(RecNetResultWithValue<Account>.Ok(account));
|
|
||||||
});
|
|
||||||
app.MapGet("/parentalcontrol/me", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
{
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
bio.bio = newBio;
|
||||||
|
db.PlayerBios.Update(bio);
|
||||||
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
await db.SaveChangesAsync();
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
return Results.Json(new { success = true });
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
[HttpPut("/account/me/profileimage")]
|
||||||
return Results.Unauthorized();
|
public async Task<IResult> UpdateProfileImage(HttpRequest request, AppDbContext db, JwtTokenService jwtService)
|
||||||
|
{
|
||||||
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
return Results.Unauthorized();
|
return Results.Unauthorized();
|
||||||
|
|
||||||
return Results.Content($"{{\"accountId\":{accountId},\"disallowInAppPurchases\":false}}", "application/json");
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
});
|
var accountId = jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
app.MapPut("/account/me/displayname", async (HttpRequest request, AppDbContext db) =>
|
if (string.IsNullOrEmpty(accountId))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
if (!int.TryParse(accountId.AsSpan(), out var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
string newProfileImage = "";
|
||||||
|
|
||||||
|
if (request.ContentLength.HasValue && request.ContentLength > 0)
|
||||||
{
|
{
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
try
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
string newDisplayName = "";
|
|
||||||
|
|
||||||
if (request.ContentLength.HasValue && request.ContentLength > 0)
|
|
||||||
{
|
{
|
||||||
try
|
request.EnableBuffering();
|
||||||
{
|
using var reader = new StreamReader(request.Body, leaveOpen: true);
|
||||||
request.EnableBuffering();
|
var body = await reader.ReadToEndAsync();
|
||||||
using var reader = new StreamReader(request.Body, leaveOpen: true);
|
|
||||||
var body = await reader.ReadToEndAsync();
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(body))
|
if (!string.IsNullOrWhiteSpace(body))
|
||||||
|
{
|
||||||
|
foreach (var pair in body.Split('&'))
|
||||||
{
|
{
|
||||||
foreach (var pair in body.Split('&'))
|
var keyValue = pair.Split('=');
|
||||||
|
if (keyValue.Length == 2)
|
||||||
{
|
{
|
||||||
var keyValue = pair.Split('=');
|
var key = Uri.UnescapeDataString(keyValue[0]);
|
||||||
if (keyValue.Length == 2)
|
var value = Uri.UnescapeDataString(keyValue[1]);
|
||||||
{
|
|
||||||
var key = Uri.UnescapeDataString(keyValue[0]);
|
|
||||||
var value = Uri.UnescapeDataString(keyValue[1]);
|
|
||||||
|
|
||||||
if (key == "displayName")
|
if (key == "imageName")
|
||||||
newDisplayName = value;
|
newProfileImage = value;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
request.Body.Position = 0;
|
|
||||||
}
|
}
|
||||||
catch { }
|
request.Body.Position = 0;
|
||||||
}
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
var account = await db.Accounts.FindAsync(id);
|
var account = await db.Accounts.FindAsync(id);
|
||||||
if (account == null)
|
if (account == null)
|
||||||
return Results.NotFound();
|
return Results.NotFound();
|
||||||
|
|
||||||
account.DisplayName = newDisplayName;
|
account.ProfileImage = newProfileImage;
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
return Results.Ok(RecNetResult.Ok());
|
return Results.Ok(RecNetResult.Ok());
|
||||||
});
|
|
||||||
|
|
||||||
app.MapPut("/account/me/username", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
string newAccountName = "";
|
|
||||||
|
|
||||||
if (request.ContentLength.HasValue && request.ContentLength > 0)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
request.EnableBuffering();
|
|
||||||
using var reader = new StreamReader(request.Body, leaveOpen: true);
|
|
||||||
var body = await reader.ReadToEndAsync();
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(body))
|
|
||||||
{
|
|
||||||
foreach (var pair in body.Split('&'))
|
|
||||||
{
|
|
||||||
var keyValue = pair.Split('=');
|
|
||||||
if (keyValue.Length == 2)
|
|
||||||
{
|
|
||||||
var key = Uri.UnescapeDataString(keyValue[0]);
|
|
||||||
var value = Uri.UnescapeDataString(keyValue[1]);
|
|
||||||
|
|
||||||
if (key == "username")
|
|
||||||
newAccountName = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
request.Body.Position = 0;
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
var account = await db.Accounts.FindAsync(id);
|
|
||||||
if (account == null)
|
|
||||||
return Results.NotFound();
|
|
||||||
|
|
||||||
account.Username = newAccountName;
|
|
||||||
await db.SaveChangesAsync();
|
|
||||||
|
|
||||||
return Results.Ok(RecNetResult.Ok());
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapGet("/account/{id}/bio", async (HttpRequest request, string id, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
if (!int.TryParse(id, out var accountId))
|
|
||||||
return Results.BadRequest();
|
|
||||||
|
|
||||||
var bio = await db.PlayerBios.FirstOrDefaultAsync(b => b.accountId == accountId);
|
|
||||||
|
|
||||||
if (bio == null)
|
|
||||||
{
|
|
||||||
return Results.Json(new { accountId = accountId, bio = "" });
|
|
||||||
}
|
|
||||||
|
|
||||||
return Results.Json(new { accountId = bio.accountId, bio = bio.bio });
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapPut("/account/me/bio", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
string newBio = "";
|
|
||||||
|
|
||||||
if (request.ContentLength.HasValue && request.ContentLength > 0)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
request.EnableBuffering();
|
|
||||||
using var reader = new StreamReader(request.Body, leaveOpen: true);
|
|
||||||
var body = await reader.ReadToEndAsync();
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(body))
|
|
||||||
{
|
|
||||||
foreach (var pair in body.Split('&'))
|
|
||||||
{
|
|
||||||
var keyValue = pair.Split('=');
|
|
||||||
if (keyValue.Length == 2)
|
|
||||||
{
|
|
||||||
var key = Uri.UnescapeDataString(keyValue[0]);
|
|
||||||
var value = Uri.UnescapeDataString(keyValue[1]);
|
|
||||||
|
|
||||||
if (key == "bio")
|
|
||||||
newBio = Uri.UnescapeDataString(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
request.Body.Position = 0;
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
var bio = await db.PlayerBios.FirstOrDefaultAsync(b => b.accountId == id);
|
|
||||||
|
|
||||||
if (bio == null)
|
|
||||||
{
|
|
||||||
bio = new PlayerBio
|
|
||||||
{
|
|
||||||
accountId = id,
|
|
||||||
bio = newBio
|
|
||||||
};
|
|
||||||
db.PlayerBios.Add(bio);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bio.bio = newBio;
|
|
||||||
db.PlayerBios.Update(bio);
|
|
||||||
}
|
|
||||||
|
|
||||||
await db.SaveChangesAsync();
|
|
||||||
|
|
||||||
return Results.Json(new { success = true });
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapPut("/account/me/profileimage", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
string newProfileImage = "";
|
|
||||||
|
|
||||||
if (request.ContentLength.HasValue && request.ContentLength > 0)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
request.EnableBuffering();
|
|
||||||
using var reader = new StreamReader(request.Body, leaveOpen: true);
|
|
||||||
var body = await reader.ReadToEndAsync();
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(body))
|
|
||||||
{
|
|
||||||
foreach (var pair in body.Split('&'))
|
|
||||||
{
|
|
||||||
var keyValue = pair.Split('=');
|
|
||||||
if (keyValue.Length == 2)
|
|
||||||
{
|
|
||||||
var key = Uri.UnescapeDataString(keyValue[0]);
|
|
||||||
var value = Uri.UnescapeDataString(keyValue[1]);
|
|
||||||
|
|
||||||
if (key == "imageName")
|
|
||||||
newProfileImage = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
request.Body.Position = 0;
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
var account = await db.Accounts.FindAsync(id);
|
|
||||||
if (account == null)
|
|
||||||
return Results.NotFound();
|
|
||||||
|
|
||||||
account.ProfileImage = newProfileImage;
|
|
||||||
await db.SaveChangesAsync();
|
|
||||||
|
|
||||||
return Results.Ok(RecNetResult.Ok());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,98 +1,93 @@
|
|||||||
using CannedNet;
|
|
||||||
using CannedNet.Data;
|
using CannedNet.Data;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using CannedNet.Services;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using CannedNet.Services.Infrastructure;
|
|
||||||
|
|
||||||
namespace CannedNet.Services.Controllers;
|
namespace CannedNet.Services.Controllers;
|
||||||
|
|
||||||
public class AuthController
|
[ApiController]
|
||||||
|
public class AuthController : ControllerBase
|
||||||
{
|
{
|
||||||
public WebApplicationBuilder Initialize(string[]? args = null) => ServiceExtensions.CreateRecNetBuilder(args);
|
[HttpGet("/eac/challenge")]
|
||||||
|
public async Task<IResult> EacChallenge()
|
||||||
public void MapEndpoints(WebApplication app)
|
|
||||||
{
|
{
|
||||||
var jwtService = app.Services.GetRequiredService<JwtTokenService>();
|
string file = await System.IO.File.ReadAllTextAsync("JSON/eacchallenge.txt");
|
||||||
|
return Results.Content(file, "text/plain");
|
||||||
|
}
|
||||||
|
|
||||||
app.MapGet("/eac/challenge", () =>
|
[HttpGet("/cachedlogin/forplatformid/{platform}/{id}")]
|
||||||
|
public async Task<IResult> CachedLoginForPlatformId(string platform, string id, AppDbContext db)
|
||||||
|
{
|
||||||
|
int platformType = int.Parse(platform);
|
||||||
|
List<CachedLogin> logins = await db.CachedLogins
|
||||||
|
.Where(c => c.Platform == (PlatformType)platformType && c.PlatformID == id)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return Results.Json(logins.Any() ? logins : new List<object>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("/connect/token")]
|
||||||
|
public async Task<IResult> ConnectToken(HttpRequest httpRequest, AppDbContext db, JwtTokenService jwtService)
|
||||||
|
{
|
||||||
|
string accountId = "";
|
||||||
|
string platformId = "";
|
||||||
|
string platform = "";
|
||||||
|
|
||||||
|
if (httpRequest.ContentLength.HasValue && httpRequest.ContentLength > 0)
|
||||||
{
|
{
|
||||||
var file = File.ReadAllText("JSON/eacchallenge.txt");
|
try
|
||||||
return Results.Content(file, "text/plain");
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapGet("/cachedlogin/forplatformid/{platform}/{id}", async (string platform, string id, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var platformType = int.Parse(platform);
|
|
||||||
var logins = await db.CachedLogins
|
|
||||||
.Where(c => c.Platform == (PlatformType)platformType && c.PlatformID == id)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
return Results.Json(logins.Any() ? logins : new List<object>());
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapPost("/connect/token", async (HttpRequest httpRequest, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
string accountId = "";
|
|
||||||
string platformId = "";
|
|
||||||
string platform = "";
|
|
||||||
|
|
||||||
if (httpRequest.ContentLength.HasValue && httpRequest.ContentLength > 0)
|
|
||||||
{
|
{
|
||||||
try
|
httpRequest.EnableBuffering();
|
||||||
|
using var reader = new StreamReader(httpRequest.Body, leaveOpen: true);
|
||||||
|
var body = await reader.ReadToEndAsync();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(body))
|
||||||
{
|
{
|
||||||
httpRequest.EnableBuffering();
|
foreach (var pair in body.Split('&'))
|
||||||
using var reader = new StreamReader(httpRequest.Body, leaveOpen: true);
|
|
||||||
var body = await reader.ReadToEndAsync();
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(body))
|
|
||||||
{
|
{
|
||||||
foreach (var pair in body.Split('&'))
|
var keyValue = pair.Split('=');
|
||||||
|
if (keyValue.Length == 2)
|
||||||
{
|
{
|
||||||
var keyValue = pair.Split('=');
|
var key = Uri.UnescapeDataString(keyValue[0]);
|
||||||
if (keyValue.Length == 2)
|
var value = Uri.UnescapeDataString(keyValue[1]);
|
||||||
{
|
|
||||||
var key = Uri.UnescapeDataString(keyValue[0]);
|
|
||||||
var value = Uri.UnescapeDataString(keyValue[1]);
|
|
||||||
|
|
||||||
if (key == "account_id")
|
if (key == "account_id")
|
||||||
accountId = value;
|
accountId = value;
|
||||||
else if (key == "platform_id")
|
else if (key == "platform_id")
|
||||||
platformId = value;
|
platformId = value;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
httpRequest.Body.Position = 0;
|
|
||||||
}
|
}
|
||||||
catch { }
|
httpRequest.Body.Position = 0;
|
||||||
}
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
var accessToken = jwtService.GenerateToken(accountId, platformId, platform);
|
var accessToken = jwtService.GenerateToken(accountId, platformId, platform);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(accountId) && int.TryParse(accountId, out var id))
|
if (!string.IsNullOrEmpty(accountId) && int.TryParse(accountId, out var id))
|
||||||
|
{
|
||||||
|
var roomInstance = await db.RoomInstances.FirstOrDefaultAsync(r => r.OwnerAccountId == id);
|
||||||
|
if (roomInstance != null)
|
||||||
{
|
{
|
||||||
var roomInstance = await db.RoomInstances.FirstOrDefaultAsync(r => r.OwnerAccountId == id);
|
db.RoomInstances.Remove(roomInstance);
|
||||||
if (roomInstance != null)
|
await db.SaveChangesAsync();
|
||||||
{
|
|
||||||
db.RoomInstances.Remove(roomInstance);
|
|
||||||
await db.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Results.Json(new
|
return Results.Json(new
|
||||||
{
|
{
|
||||||
access_token = accessToken,
|
access_token = accessToken,
|
||||||
expires_in = 3600,
|
expires_in = 3600,
|
||||||
token_type = "Bearer",
|
token_type = "Bearer",
|
||||||
refresh_token = Guid.NewGuid().ToString("N").ToUpper() + "-1",
|
refresh_token = Guid.NewGuid().ToString("N").ToUpper() + "-1",
|
||||||
scope = "offline_access profile rn rn.accounts rn.accounts.gc rn.api rn.chat rn.clubs rn.commerce rn.match.read rn.match.write rn.notify rn.rooms rn.storage",
|
scope = "offline_access profile rn rn.accounts rn.accounts.gc rn.api rn.chat rn.clubs rn.commerce rn.match.read rn.match.write rn.notify rn.rooms rn.storage",
|
||||||
key = "8oQ+e+WQaOBPbEcakhqs3dwZZdOmmyDUmJSD9u4AHMY="
|
key = "8oQ+e+WQaOBPbEcakhqs3dwZZdOmmyDUmJSD9u4AHMY="
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
app.MapGet("/role/developer/{id}", async (HttpRequest request, AppDbContext db, string id) =>
|
[HttpGet("/role/developer/{id}")]
|
||||||
{
|
public IResult GetDeveloperRole(string id)
|
||||||
// TODO: implement
|
{
|
||||||
return Results.Ok(RecNetResult.Ok());
|
return Results.Ok(RecNetResult.Ok());
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,62 +1,62 @@
|
|||||||
using CannedNet.Services.Infrastructure;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace CannedNet.Services.Controllers;
|
namespace CannedNet.Services.Controllers;
|
||||||
|
|
||||||
public class CDNController
|
[ApiController]
|
||||||
|
public class CDNController : ControllerBase
|
||||||
{
|
{
|
||||||
public WebApplicationBuilder Initialize(string[]? args = null) => ServiceExtensions.CreateRecNetBuilder(args);
|
[HttpGet("/config/LoadingScreenTipData")]
|
||||||
|
public IResult LoadingScreenTipData()
|
||||||
public void MapEndpoints(WebApplication app)
|
|
||||||
{
|
{
|
||||||
app.MapGet("/config/LoadingScreenTipData", (HttpRequest request) =>
|
var json = System.IO.File.ReadAllText("JSON/loadingscreentipdata.json");
|
||||||
|
return Results.Content(json, "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("/upload")]
|
||||||
|
public async Task<IResult> Upload()
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var json = File.ReadAllText("JSON/loadingscreentipdata.json");
|
var context = HttpContext;
|
||||||
return Results.Content(json, "application/json");
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapPost("/upload", async (HttpContext context) =>
|
var form = await context.Request.ReadFormAsync();
|
||||||
|
var file = form.Files.FirstOrDefault();
|
||||||
|
|
||||||
|
if (file == null)
|
||||||
|
{
|
||||||
|
return Results.BadRequest(new { error = "No file found in request" });
|
||||||
|
}
|
||||||
|
|
||||||
|
var imageId = Guid.NewGuid().ToString("N");
|
||||||
|
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
|
||||||
|
|
||||||
|
var validExtensions = new[] { ".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp" };
|
||||||
|
if (string.IsNullOrEmpty(extension) || !validExtensions.Contains(extension))
|
||||||
|
{
|
||||||
|
extension = ".png";
|
||||||
|
}
|
||||||
|
|
||||||
|
var savedFileName = imageId + extension;
|
||||||
|
var filePath = Path.Combine("Images", savedFileName);
|
||||||
|
|
||||||
|
if (!Directory.Exists("Images"))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory("Images");
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var fileStream = System.IO.File.Create(filePath))
|
||||||
|
{
|
||||||
|
await file.CopyToAsync(fileStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Results.Ok(new
|
||||||
|
{
|
||||||
|
filename = savedFileName
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
try
|
return Results.Problem($"Error uploading image: {ex.Message}");
|
||||||
{
|
}
|
||||||
var form = await context.Request.ReadFormAsync();
|
|
||||||
var file = form.Files.FirstOrDefault();
|
|
||||||
|
|
||||||
if (file == null)
|
|
||||||
{
|
|
||||||
return Results.BadRequest(new { error = "No file found in request" });
|
|
||||||
}
|
|
||||||
|
|
||||||
var imageId = Guid.NewGuid().ToString("N");
|
|
||||||
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
|
|
||||||
|
|
||||||
var validExtensions = new[] { ".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp" };
|
|
||||||
if (string.IsNullOrEmpty(extension) || !validExtensions.Contains(extension))
|
|
||||||
{
|
|
||||||
extension = ".png";
|
|
||||||
}
|
|
||||||
|
|
||||||
var savedFileName = imageId + extension;
|
|
||||||
var filePath = Path.Combine("Images", savedFileName);
|
|
||||||
|
|
||||||
if (!Directory.Exists("Images"))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory("Images");
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var fileStream = File.Create(filePath))
|
|
||||||
{
|
|
||||||
await file.CopyToAsync(fileStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Results.Ok(new
|
|
||||||
{
|
|
||||||
filename = savedFileName
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return Results.Problem($"Error uploading image: {ex.Message}");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
using CannedNet.Services.Infrastructure;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace CannedNet.Services.Controllers;
|
namespace CannedNet.Services.Controllers;
|
||||||
|
|
||||||
public class ChatController
|
[ApiController]
|
||||||
|
public class ChatController : ControllerBase
|
||||||
{
|
{
|
||||||
public WebApplicationBuilder Initialize(string[]? args = null) => ServiceExtensions.CreateRecNetBuilder(args);
|
[HttpGet("/thread")]
|
||||||
|
public IResult Thread()
|
||||||
public void MapEndpoints(WebApplication app)
|
|
||||||
{
|
{
|
||||||
app.MapGet("/thread", () => Results.Content("[]", "application/json"));
|
return Results.Content("[]", "application/json");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
using CannedNet.Services.Infrastructure;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace CannedNet.Services.Controllers;
|
namespace CannedNet.Services.Controllers;
|
||||||
|
|
||||||
public class ClubsController
|
[ApiController]
|
||||||
|
public class ClubsController : ControllerBase
|
||||||
{
|
{
|
||||||
public WebApplicationBuilder Initialize(string[]? args = null) => ServiceExtensions.CreateRecNetBuilder(args);
|
[HttpGet("/club/home/me")]
|
||||||
|
public IResult ClubHomeMe()
|
||||||
public void MapEndpoints(WebApplication app)
|
|
||||||
{
|
{
|
||||||
app.MapGet("/club/home/me", () =>
|
return Results.NotFound();
|
||||||
{
|
|
||||||
return Results.NotFound();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,13 @@
|
|||||||
using CannedNet.Services.Infrastructure;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace CannedNet.Services.Controllers;
|
namespace CannedNet.Services.Controllers;
|
||||||
|
|
||||||
public class CommerceController
|
[ApiController]
|
||||||
|
public class CommerceController : ControllerBase
|
||||||
{
|
{
|
||||||
public WebApplicationBuilder Initialize(string[]? args = null) => ServiceExtensions.CreateRecNetBuilder(args);
|
[HttpGet("/purchase/v1/hasspentmoney")]
|
||||||
|
public IResult HasSpentMoney()
|
||||||
public void MapEndpoints(WebApplication app)
|
|
||||||
{
|
{
|
||||||
app.MapGet("/purchase/v1/hasspentmoney", (HttpRequest request) =>
|
return Results.NotFound();
|
||||||
{
|
|
||||||
return Results.NotFound();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,17 @@
|
|||||||
using System.Net.Mime;
|
using System.Net.Mime;
|
||||||
using CannedNet.Services.Infrastructure;
|
|
||||||
using SixLabors.ImageSharp;
|
using SixLabors.ImageSharp;
|
||||||
using SixLabors.ImageSharp.Formats.Jpeg;
|
using SixLabors.ImageSharp.Formats.Jpeg;
|
||||||
using SixLabors.ImageSharp.PixelFormats;
|
using SixLabors.ImageSharp.PixelFormats;
|
||||||
using SixLabors.ImageSharp.Processing;
|
using SixLabors.ImageSharp.Processing;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace CannedNet.Services.Controllers;
|
namespace CannedNet.Services.Controllers;
|
||||||
|
|
||||||
public class ImageController
|
[ApiController]
|
||||||
|
public class ImageController : ControllerBase
|
||||||
{
|
{
|
||||||
private static readonly byte[] PlaceholderJpeg;
|
private static readonly byte[] PlaceholderJpeg;
|
||||||
|
private static readonly string ImagesDir;
|
||||||
|
|
||||||
static ImageController()
|
static ImageController()
|
||||||
{
|
{
|
||||||
@@ -20,82 +22,83 @@ public class ImageController
|
|||||||
using var ms = new MemoryStream();
|
using var ms = new MemoryStream();
|
||||||
image.SaveAsJpeg(ms, new JpegEncoder { Quality = 50 });
|
image.SaveAsJpeg(ms, new JpegEncoder { Quality = 50 });
|
||||||
PlaceholderJpeg = ms.ToArray();
|
PlaceholderJpeg = ms.ToArray();
|
||||||
|
|
||||||
|
var dir = "Images";
|
||||||
|
if (!Directory.Exists(dir))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(dir);
|
||||||
|
}
|
||||||
|
ImagesDir = dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebApplicationBuilder Initialize(string[]? args = null)
|
[HttpGet("/{imageName}")]
|
||||||
=> ServiceExtensions.CreateRecNetBuilder(args);
|
public async Task<IResult> GetImage(string imageName)
|
||||||
|
|
||||||
public void MapEndpoints(WebApplication app)
|
|
||||||
{
|
{
|
||||||
var imagesDir = Path.Combine("Images");
|
var context = HttpContext;
|
||||||
Directory.CreateDirectory(imagesDir);
|
|
||||||
|
|
||||||
app.MapGet("/{imageName}", async (HttpContext context, string imageName) =>
|
var filePath = Path.Combine(ImagesDir, imageName);
|
||||||
|
|
||||||
|
byte[] imageBytes;
|
||||||
|
string contentType;
|
||||||
|
|
||||||
|
if (System.IO.File.Exists(filePath))
|
||||||
{
|
{
|
||||||
var filePath = Path.Combine(imagesDir, imageName);
|
imageBytes = await System.IO.File.ReadAllBytesAsync(filePath);
|
||||||
|
var ext = Path.GetExtension(imageName).ToLowerInvariant();
|
||||||
byte[] imageBytes;
|
contentType = ext switch
|
||||||
string contentType;
|
|
||||||
|
|
||||||
if (File.Exists(filePath))
|
|
||||||
{
|
{
|
||||||
imageBytes = await File.ReadAllBytesAsync(filePath);
|
".jpg" or ".jpeg" => "image/jpeg",
|
||||||
var ext = Path.GetExtension(imageName).ToLowerInvariant();
|
".gif" => "image/gif",
|
||||||
contentType = ext switch
|
".webp" => "image/webp",
|
||||||
{
|
".bmp" => "image/bmp",
|
||||||
".jpg" or ".jpeg" => "image/jpeg",
|
_ => "image/png"
|
||||||
".gif" => "image/gif",
|
};
|
||||||
".webp" => "image/webp",
|
}
|
||||||
".bmp" => "image/bmp",
|
else
|
||||||
_ => "image/png"
|
{
|
||||||
};
|
imageBytes = PlaceholderJpeg;
|
||||||
}
|
contentType = "image/jpeg";
|
||||||
else
|
}
|
||||||
{
|
|
||||||
imageBytes = PlaceholderJpeg;
|
|
||||||
contentType = "image/jpeg";
|
|
||||||
}
|
|
||||||
|
|
||||||
var cropSquare = context.Request.Query["cropSquare"].FirstOrDefault();
|
var cropSquare = context.Request.Query["cropSquare"].FirstOrDefault();
|
||||||
var widthStr = context.Request.Query["width"].FirstOrDefault();
|
var widthStr = context.Request.Query["width"].FirstOrDefault();
|
||||||
var heightStr = context.Request.Query["height"].FirstOrDefault();
|
var heightStr = context.Request.Query["height"].FirstOrDefault();
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(widthStr) && string.IsNullOrEmpty(heightStr) && string.IsNullOrEmpty(cropSquare))
|
if (string.IsNullOrEmpty(widthStr) && string.IsNullOrEmpty(heightStr) && string.IsNullOrEmpty(cropSquare))
|
||||||
{
|
{
|
||||||
SignImageResponse(context, ref imageBytes);
|
|
||||||
return Results.File(imageBytes, contentType);
|
|
||||||
}
|
|
||||||
|
|
||||||
using var image = Image.Load(imageBytes);
|
|
||||||
|
|
||||||
var resizeWidth = 0;
|
|
||||||
var resizeHeight = 0;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(cropSquare) && cropSquare != "0" && cropSquare != "false")
|
|
||||||
{
|
|
||||||
var size = Math.Min(image.Width, image.Height);
|
|
||||||
var x = (image.Width - size) / 2;
|
|
||||||
var y = (image.Height - size) / 2;
|
|
||||||
image.Mutate(img => img.Crop(new Rectangle(x, y, size, size)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (int.TryParse(widthStr, out var w))
|
|
||||||
resizeWidth = w;
|
|
||||||
|
|
||||||
if (int.TryParse(heightStr, out var h))
|
|
||||||
resizeHeight = h;
|
|
||||||
|
|
||||||
if (resizeWidth > 0 || resizeHeight > 0)
|
|
||||||
{
|
|
||||||
image.Mutate(x => x.Resize(resizeWidth, resizeHeight));
|
|
||||||
}
|
|
||||||
|
|
||||||
using var output = new MemoryStream();
|
|
||||||
await image.SaveAsJpegAsync(output, new JpegEncoder { Quality = 85 });
|
|
||||||
imageBytes = output.ToArray();
|
|
||||||
SignImageResponse(context, ref imageBytes);
|
SignImageResponse(context, ref imageBytes);
|
||||||
return Results.File(imageBytes, "image/jpeg");
|
return Results.File(imageBytes, contentType);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
using var loadedImage = Image.Load(imageBytes);
|
||||||
|
|
||||||
|
var resizeWidth = 0;
|
||||||
|
var resizeHeight = 0;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(cropSquare) && cropSquare != "0" && cropSquare != "false")
|
||||||
|
{
|
||||||
|
var size = Math.Min(loadedImage.Width, loadedImage.Height);
|
||||||
|
var x = (loadedImage.Width - size) / 2;
|
||||||
|
var y = (loadedImage.Height - size) / 2;
|
||||||
|
loadedImage.Mutate(img => img.Crop(new Rectangle(x, y, size, size)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (int.TryParse(widthStr, out var w))
|
||||||
|
resizeWidth = w;
|
||||||
|
|
||||||
|
if (int.TryParse(heightStr, out var h))
|
||||||
|
resizeHeight = h;
|
||||||
|
|
||||||
|
if (resizeWidth > 0 || resizeHeight > 0)
|
||||||
|
{
|
||||||
|
loadedImage.Mutate(x => x.Resize(resizeWidth, resizeHeight));
|
||||||
|
}
|
||||||
|
|
||||||
|
using var output = new MemoryStream();
|
||||||
|
await loadedImage.SaveAsJpegAsync(output, new JpegEncoder { Quality = 85 });
|
||||||
|
imageBytes = output.ToArray();
|
||||||
|
SignImageResponse(context, ref imageBytes);
|
||||||
|
return Results.File(imageBytes, "image/jpeg");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SignImageResponse(HttpContext context, ref byte[] imageBytes)
|
private static void SignImageResponse(HttpContext context, ref byte[] imageBytes)
|
||||||
|
|||||||
@@ -2,307 +2,49 @@ using System.Text.Json;
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using CannedNet.Data;
|
using CannedNet.Data;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using CannedNet.Services;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using CannedNet.Services.Infrastructure;
|
|
||||||
|
|
||||||
namespace CannedNet.Services.Controllers;
|
namespace CannedNet.Services.Controllers;
|
||||||
|
|
||||||
public class MatchmakingController
|
[ApiController]
|
||||||
|
public class MatchmakingController : ControllerBase
|
||||||
{
|
{
|
||||||
public WebApplicationBuilder Initialize(string[]? args = null) => ServiceExtensions.CreateRecNetBuilder(args);
|
[HttpPost("/player/login")]
|
||||||
|
public IResult PlayerLogin()
|
||||||
public void MapEndpoints(WebApplication app)
|
|
||||||
{
|
{
|
||||||
var jwtService = app.Services.GetRequiredService<JwtTokenService>();
|
return Results.Ok();
|
||||||
|
}
|
||||||
|
|
||||||
app.MapPost("/player/login", () => Results.Ok());
|
[HttpGet("/player")]
|
||||||
|
public async Task<IResult> GetPlayer(HttpRequest request, AppDbContext db)
|
||||||
app.MapGet("/player", async (HttpRequest request, AppDbContext db) =>
|
{
|
||||||
|
var id = request.Query["id"].FirstOrDefault();
|
||||||
|
if (string.IsNullOrEmpty(id) || !int.TryParse(id, out var accountId))
|
||||||
{
|
{
|
||||||
var id = request.Query["id"].FirstOrDefault();
|
var json = System.IO.File.ReadAllText("JSON/getplayer.json");
|
||||||
if (string.IsNullOrEmpty(id) || !int.TryParse(id, out var accountId))
|
return Results.Content(json, "application/json");
|
||||||
{
|
}
|
||||||
var json = File.ReadAllText("JSON/getplayer.json");
|
|
||||||
return Results.Content(json, "application/json");
|
|
||||||
}
|
|
||||||
|
|
||||||
var account = await db.Accounts.FindAsync(accountId);
|
var account = await db.Accounts.FindAsync(accountId);
|
||||||
if (account == null)
|
if (account == null)
|
||||||
{
|
|
||||||
var json = File.ReadAllText("JSON/getplayer.json");
|
|
||||||
return Results.Content(json, "application/json");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the player's active room instance
|
|
||||||
var roomInstance = await db.RoomInstances
|
|
||||||
.Where(r => r.OwnerAccountId == accountId)
|
|
||||||
.OrderByDescending(r => r.Id)
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
var result = new List<object>
|
|
||||||
{
|
|
||||||
new
|
|
||||||
{
|
|
||||||
playerId = account.AccountId,
|
|
||||||
statusVisibility = 0,
|
|
||||||
deviceClass = 0,
|
|
||||||
vrMovementMode = 1,
|
|
||||||
roomInstance = roomInstance != null ? new
|
|
||||||
{
|
|
||||||
roomInstanceId = roomInstance.Id > 0 ? roomInstance.Id : roomInstance.roomInstanceId,
|
|
||||||
roomId = roomInstance.roomId,
|
|
||||||
subRoomId = roomInstance.subRoomId,
|
|
||||||
roomInstanceType = roomInstance.roomInstanceType,
|
|
||||||
location = roomInstance.location,
|
|
||||||
dataBlob = roomInstance.dataBlob,
|
|
||||||
eventId = roomInstance.eventId,
|
|
||||||
clubId = roomInstance.clubId,
|
|
||||||
roomCode = roomInstance.roomCode,
|
|
||||||
photonRegionId = roomInstance.photonRegionId,
|
|
||||||
photonRoomId = roomInstance.photonRoomId,
|
|
||||||
name = roomInstance.name,
|
|
||||||
maxCapacity = roomInstance.maxCapacity,
|
|
||||||
isFull = roomInstance.isFull,
|
|
||||||
isPrivate = roomInstance.isPrivate,
|
|
||||||
isInProgress = roomInstance.isInProgress,
|
|
||||||
EncryptVoiceChat = roomInstance.EncryptVoiceChat
|
|
||||||
} : (object?)null,
|
|
||||||
isOnline = roomInstance != null,
|
|
||||||
appVersion = "",
|
|
||||||
platform = account.Platforms ?? 0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return Results.Json(result);
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapPost("/goto/room/{room}", async (HttpRequest request, string room, AppDbContext db) =>
|
|
||||||
{
|
{
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
var json = System.IO.File.ReadAllText("JSON/getplayer.json");
|
||||||
|
return Results.Content(json, "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
var roomInstance = await db.RoomInstances
|
||||||
return Results.Unauthorized();
|
.Where(r => r.OwnerAccountId == accountId)
|
||||||
|
.OrderByDescending(r => r.Id)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
var result = new List<object>
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
request.EnableBuffering();
|
|
||||||
request.Body.Position = 0;
|
|
||||||
var form = await request.ReadFormAsync();
|
|
||||||
int joinMode = 0;
|
|
||||||
if (int.TryParse(form["JoinMode"].ToString(), out var mode))
|
|
||||||
{
|
|
||||||
joinMode = mode;
|
|
||||||
}
|
|
||||||
request.Body.Position = 0;
|
|
||||||
|
|
||||||
Room? roomData = null;
|
|
||||||
var roomLower = room.ToLower();
|
|
||||||
|
|
||||||
if (roomLower == "dormroom")
|
|
||||||
{
|
|
||||||
roomData = await db.Rooms.FirstOrDefaultAsync(r => r.IsDorm && r.CreatorAccountId == id);
|
|
||||||
}
|
|
||||||
else if (int.TryParse(room, out var roomId))
|
|
||||||
{
|
|
||||||
roomData = await db.Rooms.FirstOrDefaultAsync(r => r.RoomId == roomId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (roomData == null)
|
|
||||||
{
|
|
||||||
roomData = await db.Rooms.FirstOrDefaultAsync(r => r.Name.ToLower() == roomLower);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (roomData == null)
|
|
||||||
{
|
|
||||||
return Results.NotFound("Room not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
var subRoom = await db.SubRooms.FirstOrDefaultAsync(s => s.RoomId == roomData.RoomId);
|
|
||||||
|
|
||||||
string location = subRoom?.UnitySceneId ?? "";
|
|
||||||
int subRoomId = subRoom?.SubRoomId ?? 0;
|
|
||||||
int maxCapacity = subRoom?.MaxPlayers ?? 4;
|
|
||||||
|
|
||||||
|
|
||||||
RoomInstance? instanceToUse;
|
|
||||||
string photonRoomId;
|
|
||||||
|
|
||||||
bool isPrivateInstance = joinMode == 2 || roomData.IsDorm;
|
|
||||||
|
|
||||||
var existingInstance = await db.RoomInstances.FirstOrDefaultAsync(r => r.OwnerAccountId == id && r.roomId == roomData.RoomId);
|
|
||||||
|
|
||||||
if (existingInstance != null)
|
|
||||||
{
|
|
||||||
photonRoomId = existingInstance.photonRoomId ?? Guid.NewGuid().ToString();
|
|
||||||
existingInstance.roomInstanceId = existingInstance.Id;
|
|
||||||
existingInstance.roomId = roomData.RoomId;
|
|
||||||
existingInstance.subRoomId = subRoomId;
|
|
||||||
existingInstance.location = location;
|
|
||||||
existingInstance.dataBlob = "";
|
|
||||||
existingInstance.photonRegionId = "us";
|
|
||||||
existingInstance.photonRoomId = photonRoomId;
|
|
||||||
existingInstance.name = roomData.Name;
|
|
||||||
existingInstance.maxCapacity = maxCapacity;
|
|
||||||
existingInstance.isFull = false;
|
|
||||||
existingInstance.isPrivate = isPrivateInstance;
|
|
||||||
instanceToUse = existingInstance;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
photonRoomId = Guid.NewGuid().ToString();
|
|
||||||
|
|
||||||
var oldInstances = await db.RoomInstances
|
|
||||||
.Where(r => r.OwnerAccountId == id && r.roomId != roomData.RoomId)
|
|
||||||
.ToListAsync();
|
|
||||||
db.RoomInstances.RemoveRange(oldInstances);
|
|
||||||
|
|
||||||
var publicInstance = await db.RoomInstances
|
|
||||||
.FirstOrDefaultAsync(r => r.roomId == roomData.RoomId && !r.isPrivate && !r.isFull);
|
|
||||||
|
|
||||||
if (publicInstance != null)
|
|
||||||
{
|
|
||||||
photonRoomId = publicInstance.photonRoomId ?? Guid.NewGuid().ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
instanceToUse = new RoomInstance
|
|
||||||
{
|
|
||||||
OwnerAccountId = id,
|
|
||||||
roomInstanceId = 1,
|
|
||||||
roomId = roomData.RoomId,
|
|
||||||
subRoomId = subRoomId,
|
|
||||||
roomInstanceType = 2,
|
|
||||||
location = location,
|
|
||||||
dataBlob = "",
|
|
||||||
photonRegionId = "us",
|
|
||||||
photonRoomId = photonRoomId,
|
|
||||||
name = roomData.Name,
|
|
||||||
maxCapacity = maxCapacity,
|
|
||||||
isFull = false,
|
|
||||||
isPrivate = isPrivateInstance,
|
|
||||||
isInProgress = false,
|
|
||||||
EncryptVoiceChat = roomData.EncryptVoiceChat
|
|
||||||
};
|
|
||||||
db.RoomInstances.Add(instanceToUse);
|
|
||||||
}
|
|
||||||
|
|
||||||
await db.SaveChangesAsync();
|
|
||||||
|
|
||||||
if (instanceToUse.Id == 0)
|
|
||||||
{
|
|
||||||
instanceToUse = await db.RoomInstances.FirstOrDefaultAsync(r => r.OwnerAccountId == id && r.roomId == roomData.RoomId);
|
|
||||||
}
|
|
||||||
|
|
||||||
var response = new
|
|
||||||
{
|
|
||||||
errorCode = 0,
|
|
||||||
roomInstance = new
|
|
||||||
{
|
|
||||||
roomInstanceId = instanceToUse?.Id ?? 1,
|
|
||||||
roomId = instanceToUse?.roomId ?? roomData.RoomId,
|
|
||||||
subRoomId = instanceToUse?.subRoomId ?? subRoomId,
|
|
||||||
roomInstanceType = instanceToUse?.roomInstanceType ?? 2,
|
|
||||||
location = instanceToUse?.location ?? location,
|
|
||||||
dataBlob = instanceToUse?.dataBlob ?? "",
|
|
||||||
eventId = instanceToUse?.eventId ?? 0,
|
|
||||||
clubId = instanceToUse?.clubId ?? 0,
|
|
||||||
roomCode = instanceToUse?.roomCode ?? "",
|
|
||||||
photonRegionId = instanceToUse?.photonRegionId ?? "us",
|
|
||||||
photonRoomId = instanceToUse?.photonRoomId ?? photonRoomId,
|
|
||||||
name = instanceToUse?.name ?? roomData.Name,
|
|
||||||
maxCapacity = instanceToUse?.maxCapacity ?? maxCapacity,
|
|
||||||
isFull = instanceToUse?.isFull ?? false,
|
|
||||||
isPrivate = isPrivateInstance,
|
|
||||||
isInProgress = instanceToUse?.isInProgress ?? false,
|
|
||||||
EncryptVoiceChat = instanceToUse?.EncryptVoiceChat ?? roomData.EncryptVoiceChat
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return Results.Json(response);
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapPost("/goto/none", (HttpRequest request) =>
|
|
||||||
{
|
{
|
||||||
// dormroom location id : 76d98498-60a1-430c-ab76-b54a29b7a163
|
new
|
||||||
// offline dorm
|
|
||||||
|
|
||||||
return Results.Json(new
|
|
||||||
{
|
{
|
||||||
errorCode = 0,
|
playerId = account.AccountId,
|
||||||
roomInstance = new
|
statusVisibility = 0,
|
||||||
{
|
deviceClass = 0,
|
||||||
roomInstanceId = 1,
|
vrMovementMode = 1,
|
||||||
roomId = 1,
|
|
||||||
subRoomId = 1,
|
|
||||||
roomInstanceType = 2,
|
|
||||||
location = "76d98498-60a1-430c-ab76-b54a29b7a163",
|
|
||||||
dataBlob = "",
|
|
||||||
eventId = 0,
|
|
||||||
clubId = 0,
|
|
||||||
photonRegionId = "us",
|
|
||||||
photonRoomId = Guid.NewGuid(),
|
|
||||||
name = "DormRoom",
|
|
||||||
maxCapacity = 4,
|
|
||||||
isFull = false,
|
|
||||||
isPrivate = true,
|
|
||||||
isInProgress = false,
|
|
||||||
EncryptVoiceChat = false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapPost("/player/heartbeat", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
request.EnableBuffering();
|
|
||||||
request.Body.Position = 0;
|
|
||||||
using var reader = new StreamReader(request.Body);
|
|
||||||
var body = await reader.ReadToEndAsync();
|
|
||||||
|
|
||||||
request.Body.Position = 0;
|
|
||||||
var form = await request.ReadFormAsync();
|
|
||||||
var loginLock = form["LoginLock"].ToString();
|
|
||||||
|
|
||||||
HeartbeatRequest? heartbeat = null;
|
|
||||||
if (!string.IsNullOrWhiteSpace(body) && body.TrimStart().StartsWith("{"))
|
|
||||||
{
|
|
||||||
heartbeat = JsonSerializer.Deserialize<HeartbeatRequest>(body);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (heartbeat == null)
|
|
||||||
heartbeat = new HeartbeatRequest();
|
|
||||||
|
|
||||||
// Get the player's active room instance (most recent one)
|
|
||||||
var roomInstance = await db.RoomInstances
|
|
||||||
.Where(r => r.OwnerAccountId == id)
|
|
||||||
.OrderByDescending(r => r.Id)
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
|
|
||||||
return Results.Json(new
|
|
||||||
{
|
|
||||||
playerId = heartbeat.playerId != 0 ? heartbeat.playerId : id,
|
|
||||||
statusVisibility = heartbeat.statusVisibility,
|
|
||||||
deviceClass = heartbeat.deviceClass,
|
|
||||||
vrMovementMode = heartbeat.vrMovementMode != 0 ? heartbeat.vrMovementMode : 1,
|
|
||||||
roomInstance = roomInstance != null ? new
|
roomInstance = roomInstance != null ? new
|
||||||
{
|
{
|
||||||
roomInstanceId = roomInstance.Id > 0 ? roomInstance.Id : roomInstance.roomInstanceId,
|
roomInstanceId = roomInstance.Id > 0 ? roomInstance.Id : roomInstance.roomInstanceId,
|
||||||
@@ -322,22 +64,277 @@ public class MatchmakingController
|
|||||||
isPrivate = roomInstance.isPrivate,
|
isPrivate = roomInstance.isPrivate,
|
||||||
isInProgress = roomInstance.isInProgress,
|
isInProgress = roomInstance.isInProgress,
|
||||||
EncryptVoiceChat = roomInstance.EncryptVoiceChat
|
EncryptVoiceChat = roomInstance.EncryptVoiceChat
|
||||||
} : null,
|
} : (object?)null,
|
||||||
isOnline = roomInstance != null,
|
isOnline = roomInstance != null,
|
||||||
appVersion = heartbeat.appVersion ?? "",
|
appVersion = "",
|
||||||
platform = heartbeat.platform
|
platform = account.Platforms ?? 0
|
||||||
});
|
}
|
||||||
});
|
};
|
||||||
app.MapPut("/player/statusvisibility", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
|
return Results.Json(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("/goto/room/{room}")]
|
||||||
|
public async Task<IResult> GotoRoom(string room, HttpRequest request, AppDbContext db, JwtTokenService jwtService)
|
||||||
|
{
|
||||||
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
|
var accountId = jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(accountId))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
if (!int.TryParse(accountId.AsSpan(), out var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
request.EnableBuffering();
|
||||||
|
request.Body.Position = 0;
|
||||||
|
var form = await request.ReadFormAsync();
|
||||||
|
int joinMode = 0;
|
||||||
|
if (int.TryParse(form["JoinMode"].ToString(), out var mode))
|
||||||
{
|
{
|
||||||
// TODO ADD FUNCTIONALITY
|
joinMode = mode;
|
||||||
return Results.Ok();
|
}
|
||||||
});
|
request.Body.Position = 0;
|
||||||
app.MapPost("/roominstance/{id}/reportjoinresult", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
|
Room? roomData = null;
|
||||||
|
var roomLower = room.ToLower();
|
||||||
|
|
||||||
|
if (roomLower == "dormroom")
|
||||||
{
|
{
|
||||||
return Results.Ok();
|
roomData = await db.Rooms.FirstOrDefaultAsync(r => r.IsDorm && r.CreatorAccountId == id);
|
||||||
|
}
|
||||||
|
else if (int.TryParse(room, out var roomId))
|
||||||
|
{
|
||||||
|
roomData = await db.Rooms.FirstOrDefaultAsync(r => r.RoomId == roomId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roomData == null)
|
||||||
|
{
|
||||||
|
roomData = await db.Rooms.FirstOrDefaultAsync(r => r.Name.ToLower() == roomLower);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roomData == null)
|
||||||
|
{
|
||||||
|
return Results.NotFound("Room not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
var subRoom = await db.SubRooms.FirstOrDefaultAsync(s => s.RoomId == roomData.RoomId);
|
||||||
|
|
||||||
|
string location = subRoom?.UnitySceneId ?? "";
|
||||||
|
int subRoomId = subRoom?.SubRoomId ?? 0;
|
||||||
|
int maxCapacity = subRoom?.MaxPlayers ?? 4;
|
||||||
|
|
||||||
|
RoomInstance? instanceToUse;
|
||||||
|
string photonRoomId;
|
||||||
|
|
||||||
|
bool isPrivateInstance = joinMode == 2 || roomData.IsDorm;
|
||||||
|
|
||||||
|
var existingInstance = await db.RoomInstances.FirstOrDefaultAsync(r => r.OwnerAccountId == id && r.roomId == roomData.RoomId);
|
||||||
|
|
||||||
|
if (existingInstance != null)
|
||||||
|
{
|
||||||
|
photonRoomId = existingInstance.photonRoomId ?? Guid.NewGuid().ToString();
|
||||||
|
existingInstance.roomInstanceId = existingInstance.Id;
|
||||||
|
existingInstance.roomId = roomData.RoomId;
|
||||||
|
existingInstance.subRoomId = subRoomId;
|
||||||
|
existingInstance.location = location;
|
||||||
|
existingInstance.dataBlob = "";
|
||||||
|
existingInstance.photonRegionId = "us";
|
||||||
|
existingInstance.photonRoomId = photonRoomId;
|
||||||
|
existingInstance.name = roomData.Name;
|
||||||
|
existingInstance.maxCapacity = maxCapacity;
|
||||||
|
existingInstance.isFull = false;
|
||||||
|
existingInstance.isPrivate = isPrivateInstance;
|
||||||
|
instanceToUse = existingInstance;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
photonRoomId = Guid.NewGuid().ToString();
|
||||||
|
|
||||||
|
var oldInstances = await db.RoomInstances
|
||||||
|
.Where(r => r.OwnerAccountId == id && r.roomId != roomData.RoomId)
|
||||||
|
.ToListAsync();
|
||||||
|
db.RoomInstances.RemoveRange(oldInstances);
|
||||||
|
|
||||||
|
var publicInstance = await db.RoomInstances
|
||||||
|
.FirstOrDefaultAsync(r => r.roomId == roomData.RoomId && !r.isPrivate && !r.isFull);
|
||||||
|
|
||||||
|
if (publicInstance != null)
|
||||||
|
{
|
||||||
|
photonRoomId = publicInstance.photonRoomId ?? Guid.NewGuid().ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
instanceToUse = new RoomInstance
|
||||||
|
{
|
||||||
|
OwnerAccountId = id,
|
||||||
|
roomInstanceId = 1,
|
||||||
|
roomId = roomData.RoomId,
|
||||||
|
subRoomId = subRoomId,
|
||||||
|
roomInstanceType = 2,
|
||||||
|
location = location,
|
||||||
|
dataBlob = "",
|
||||||
|
photonRegionId = "us",
|
||||||
|
photonRoomId = photonRoomId,
|
||||||
|
name = roomData.Name,
|
||||||
|
maxCapacity = maxCapacity,
|
||||||
|
isFull = false,
|
||||||
|
isPrivate = isPrivateInstance,
|
||||||
|
isInProgress = false,
|
||||||
|
EncryptVoiceChat = roomData.EncryptVoiceChat
|
||||||
|
};
|
||||||
|
db.RoomInstances.Add(instanceToUse);
|
||||||
|
}
|
||||||
|
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
|
if (instanceToUse.Id == 0)
|
||||||
|
{
|
||||||
|
instanceToUse = await db.RoomInstances.FirstOrDefaultAsync(r => r.OwnerAccountId == id && r.roomId == roomData.RoomId);
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = new
|
||||||
|
{
|
||||||
|
errorCode = 0,
|
||||||
|
roomInstance = new
|
||||||
|
{
|
||||||
|
roomInstanceId = instanceToUse?.Id ?? 1,
|
||||||
|
roomId = instanceToUse?.roomId ?? roomData.RoomId,
|
||||||
|
subRoomId = instanceToUse?.subRoomId ?? subRoomId,
|
||||||
|
roomInstanceType = instanceToUse?.roomInstanceType ?? 2,
|
||||||
|
location = instanceToUse?.location ?? location,
|
||||||
|
dataBlob = instanceToUse?.dataBlob ?? "",
|
||||||
|
eventId = instanceToUse?.eventId ?? 0,
|
||||||
|
clubId = instanceToUse?.clubId ?? 0,
|
||||||
|
roomCode = instanceToUse?.roomCode ?? "",
|
||||||
|
photonRegionId = instanceToUse?.photonRegionId ?? "us",
|
||||||
|
photonRoomId = instanceToUse?.photonRoomId ?? photonRoomId,
|
||||||
|
name = instanceToUse?.name ?? roomData.Name,
|
||||||
|
maxCapacity = instanceToUse?.maxCapacity ?? maxCapacity,
|
||||||
|
isFull = instanceToUse?.isFull ?? false,
|
||||||
|
isPrivate = isPrivateInstance,
|
||||||
|
isInProgress = instanceToUse?.isInProgress ?? false,
|
||||||
|
EncryptVoiceChat = instanceToUse?.EncryptVoiceChat ?? roomData.EncryptVoiceChat
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return Results.Json(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("/goto/none")]
|
||||||
|
public IResult GotoNone()
|
||||||
|
{
|
||||||
|
return Results.Json(new
|
||||||
|
{
|
||||||
|
errorCode = 0,
|
||||||
|
roomInstance = new
|
||||||
|
{
|
||||||
|
roomInstanceId = 1,
|
||||||
|
roomId = 1,
|
||||||
|
subRoomId = 1,
|
||||||
|
roomInstanceType = 2,
|
||||||
|
location = "76d98498-60a1-430c-ab76-b54a29b7a163",
|
||||||
|
dataBlob = "",
|
||||||
|
eventId = 0,
|
||||||
|
clubId = 0,
|
||||||
|
photonRegionId = "us",
|
||||||
|
photonRoomId = Guid.NewGuid(),
|
||||||
|
name = "DormRoom",
|
||||||
|
maxCapacity = 4,
|
||||||
|
isFull = false,
|
||||||
|
isPrivate = true,
|
||||||
|
isInProgress = false,
|
||||||
|
EncryptVoiceChat = false
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost("/player/heartbeat")]
|
||||||
|
public async Task<IResult> PlayerHeartbeat(HttpRequest request, AppDbContext db, JwtTokenService jwtService)
|
||||||
|
{
|
||||||
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
|
var accountId = jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(accountId))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
if (!int.TryParse(accountId.AsSpan(), out var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
request.EnableBuffering();
|
||||||
|
request.Body.Position = 0;
|
||||||
|
using var reader = new StreamReader(request.Body);
|
||||||
|
var body = await reader.ReadToEndAsync();
|
||||||
|
|
||||||
|
request.Body.Position = 0;
|
||||||
|
var form = await request.ReadFormAsync();
|
||||||
|
var loginLock = form["LoginLock"].ToString();
|
||||||
|
|
||||||
|
HeartbeatRequest? heartbeat = null;
|
||||||
|
if (!string.IsNullOrWhiteSpace(body) && body.TrimStart().StartsWith("{"))
|
||||||
|
{
|
||||||
|
heartbeat = JsonSerializer.Deserialize<HeartbeatRequest>(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heartbeat == null)
|
||||||
|
heartbeat = new HeartbeatRequest();
|
||||||
|
|
||||||
|
var roomInstance = await db.RoomInstances
|
||||||
|
.Where(r => r.OwnerAccountId == id)
|
||||||
|
.OrderByDescending(r => r.Id)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
return Results.Json(new
|
||||||
|
{
|
||||||
|
playerId = heartbeat.playerId != 0 ? heartbeat.playerId : id,
|
||||||
|
statusVisibility = heartbeat.statusVisibility,
|
||||||
|
deviceClass = heartbeat.deviceClass,
|
||||||
|
vrMovementMode = heartbeat.vrMovementMode != 0 ? heartbeat.vrMovementMode : 1,
|
||||||
|
roomInstance = roomInstance != null ? new
|
||||||
|
{
|
||||||
|
roomInstanceId = roomInstance.Id > 0 ? roomInstance.Id : roomInstance.roomInstanceId,
|
||||||
|
roomId = roomInstance.roomId,
|
||||||
|
subRoomId = roomInstance.subRoomId,
|
||||||
|
roomInstanceType = roomInstance.roomInstanceType,
|
||||||
|
location = roomInstance.location,
|
||||||
|
dataBlob = roomInstance.dataBlob,
|
||||||
|
eventId = roomInstance.eventId,
|
||||||
|
clubId = roomInstance.clubId,
|
||||||
|
roomCode = roomInstance.roomCode,
|
||||||
|
photonRegionId = roomInstance.photonRegionId,
|
||||||
|
photonRoomId = roomInstance.photonRoomId,
|
||||||
|
name = roomInstance.name,
|
||||||
|
maxCapacity = roomInstance.maxCapacity,
|
||||||
|
isFull = roomInstance.isFull,
|
||||||
|
isPrivate = roomInstance.isPrivate,
|
||||||
|
isInProgress = roomInstance.isInProgress,
|
||||||
|
EncryptVoiceChat = roomInstance.EncryptVoiceChat
|
||||||
|
} : null,
|
||||||
|
isOnline = roomInstance != null,
|
||||||
|
appVersion = heartbeat.appVersion ?? "",
|
||||||
|
platform = heartbeat.platform
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("/player/statusvisibility")]
|
||||||
|
public IResult PlayerStatusVisibility()
|
||||||
|
{
|
||||||
|
return Results.Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("/roominstance/{id}/reportjoinresult")]
|
||||||
|
public IResult ReportJoinResult(string id)
|
||||||
|
{
|
||||||
|
return Results.Ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class HeartbeatRequest
|
public class HeartbeatRequest
|
||||||
|
|||||||
@@ -1,18 +1,15 @@
|
|||||||
using CannedNet.Services.Infrastructure;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace CannedNet.Services.Controllers;
|
namespace CannedNet.Services.Controllers;
|
||||||
|
|
||||||
public class NSController
|
[ApiController]
|
||||||
|
[Route("ns")]
|
||||||
|
public class NSController : ControllerBase
|
||||||
{
|
{
|
||||||
public WebApplicationBuilder Initialize(string[]? args = null) => ServiceExtensions.CreateRecNetBuilder(args);
|
[HttpGet]
|
||||||
|
public IResult Index()
|
||||||
public void MapEndpoints(WebApplication app)
|
|
||||||
{
|
{
|
||||||
// Rec Room automatically calls this and sets the endpoints that correspond to services in the JSON file. These will be moved to the main server config once I get there.
|
var json = System.IO.File.ReadAllText("JSON/endpoints.json");
|
||||||
app.MapGet("/", () =>
|
return Results.Content(json, "application/json");
|
||||||
{
|
|
||||||
var json = File.ReadAllText("JSON/endpoints.json");
|
|
||||||
return Results.Content(json, "application/json");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,13 @@
|
|||||||
using CannedNet.Hubs;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using CannedNet.Services.Infrastructure;
|
|
||||||
using Microsoft.AspNetCore.SignalR;
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
|
||||||
namespace CannedNet.Services.Controllers;
|
namespace CannedNet.Services.Controllers;
|
||||||
|
|
||||||
public class NotifyController
|
[ApiController]
|
||||||
|
public class NotifyController : ControllerBase
|
||||||
{
|
{
|
||||||
public WebApplicationBuilder Initialize(string[]? args = null) => ServiceExtensions.CreateRecNetBuilder(args);
|
[HttpGet("/hub/v1")]
|
||||||
|
public void HubEndpoint()
|
||||||
public void MapEndpoints(WebApplication app)
|
|
||||||
{
|
{
|
||||||
app.MapHub<NotificationsHub>("/hub/v1");
|
|
||||||
|
|
||||||
var hubContext = app.Services.GetRequiredService<IHubContext<NotificationsHub>>();
|
|
||||||
NotificationService.SetHubContext(hubContext);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
using CannedNet.Data;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace CannedNet.Services.Infrastructure;
|
|
||||||
|
|
||||||
public static class ServiceExtensions
|
|
||||||
{
|
|
||||||
public static void ConfigureRecNetServices(this WebApplicationBuilder builder)
|
|
||||||
{
|
|
||||||
builder.Services.ConfigureHttpJsonOptions(options =>
|
|
||||||
options.SerializerOptions.PropertyNamingPolicy = null);
|
|
||||||
|
|
||||||
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection")
|
|
||||||
?? "Host=localhost;Port=5432;Database=cannednet;Username=postgres;Password=postgres";
|
|
||||||
|
|
||||||
builder.Services.AddDbContext<AppDbContext>(options =>
|
|
||||||
options.UseNpgsql(connectionString));
|
|
||||||
|
|
||||||
builder.Services.AddScoped<JwtTokenService>();
|
|
||||||
builder.Services.AddSingleton<NotificationService>();
|
|
||||||
builder.Services.AddScoped<StorefrontFillService>();
|
|
||||||
builder.Services.AddSignalR();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ConfigureHostUrl(this WebApplicationBuilder builder, string defaultUrl)
|
|
||||||
{
|
|
||||||
var url = builder.Configuration["Hosting:Url"];
|
|
||||||
builder.WebHost.UseUrls(string.IsNullOrWhiteSpace(url) ? defaultUrl : url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static WebApplicationBuilder CreateRecNetBuilder(string[]? args) =>
|
|
||||||
WebApplication.CreateBuilder(args ?? []);
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
using System.Net.Mime;
|
|
||||||
using CannedNet.Services.Controllers;
|
|
||||||
|
|
||||||
namespace CannedNet.Services.Infrastructure;
|
|
||||||
|
|
||||||
public class ServiceRegistry
|
|
||||||
{
|
|
||||||
public required string Name { get; init; }
|
|
||||||
public required int Port { get; init; }
|
|
||||||
public required Type ServiceType { get; init; }
|
|
||||||
public required Action<WebApplicationBuilder> ConfigureBuilder { get; init; }
|
|
||||||
public required Action<WebApplication, JwtTokenService> MapEndpoints { get; init; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Services
|
|
||||||
{
|
|
||||||
public static readonly List<ServiceRegistry> All =
|
|
||||||
[
|
|
||||||
new() { Name = "NS", Port = 5001, ServiceType = typeof(NSController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new NSController().MapEndpoints(app) },
|
|
||||||
new() { Name = "API", Port = 5000, ServiceType = typeof(APIController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new APIController().MapEndpoints(app) },
|
|
||||||
new() { Name = "Auth", Port = 5002, ServiceType = typeof(AuthController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, jwt) => new AuthController().MapEndpoints(app) },
|
|
||||||
new() { Name = "Chat", Port = 5003, ServiceType = typeof(ChatController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new ChatController().MapEndpoints(app) },
|
|
||||||
new() { Name = "Match", Port = 5004, ServiceType = typeof(MatchmakingController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new MatchmakingController().MapEndpoints(app) },
|
|
||||||
new() { Name = "Accounts", Port = 5005, ServiceType = typeof(AccountsController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, jwt) => new AccountsController().MapEndpoints(app, jwt) },
|
|
||||||
new() { Name = "Notify", Port = 5006, ServiceType = typeof(NotifyController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new NotifyController().MapEndpoints(app) },
|
|
||||||
new() { Name = "CDN", Port = 5007, ServiceType = typeof(CDNController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new CDNController().MapEndpoints(app) },
|
|
||||||
new() { Name = "Image", Port = 5008, ServiceType = typeof(ImageController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new ImageController().MapEndpoints(app) },
|
|
||||||
new() { Name = "Clubs", Port = 5009, ServiceType = typeof(ClubsController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new ClubsController().MapEndpoints(app) },
|
|
||||||
new() { Name = "Commerce", Port = 5010, ServiceType = typeof(CommerceController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new CommerceController().MapEndpoints(app) }
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -12,6 +12,8 @@ public class JwtTokenService
|
|||||||
private readonly SigningCredentials _signingCredentials;
|
private readonly SigningCredentials _signingCredentials;
|
||||||
private const string KeyId = "7C2F041398671515B0862CB23FAF95B03";
|
private const string KeyId = "7C2F041398671515B0862CB23FAF95B03";
|
||||||
|
|
||||||
|
public static RSA GetRsaInstance() => _rsa;
|
||||||
|
|
||||||
public JwtTokenService()
|
public JwtTokenService()
|
||||||
{
|
{
|
||||||
_securityKey = new RsaSecurityKey(_rsa) { KeyId = KeyId };
|
_securityKey = new RsaSecurityKey(_rsa) { KeyId = KeyId };
|
||||||
|
|||||||
Reference in New Issue
Block a user