mirror of
https://github.com/myawired/2025-RecRoom-Server-E12354.git
synced 2026-07-17 16:11:15 +10:00
3263 lines
116 KiB
C#
3263 lines
116 KiB
C#
using System.ComponentModel.DataAnnotations;
|
|
using System.Diagnostics.Contracts;
|
|
using System.Net.Mime;
|
|
using System.Net.WebSockets;
|
|
using System.Numerics;
|
|
using System.Security.Cryptography.Xml;
|
|
using System.Security.Principal;
|
|
using System.Text.RegularExpressions;
|
|
using System.Xml.Linq;
|
|
using Discord;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
|
using Microsoft.Extensions.Configuration.UserSecrets;
|
|
using Newtonsoft.Json;
|
|
using Newtonsoft.Json.Linq;
|
|
using Rec_rewild_live_rewrite.api;
|
|
using Rec_rewild_live_rewrite.api.dbs;
|
|
using Rec_rewild_live_rewrite.api.server;
|
|
using Rec_rewild_live_rewrite.api.server.Classes;
|
|
using Rec_rewild_live_rewrite.api.server.Classes.db_class;
|
|
using RewildLiveSource.api.admin;
|
|
using RewildLiveSource.Controllers;
|
|
using SixLabors.ImageSharp;
|
|
using SixLabors.ImageSharp.Metadata;
|
|
using static ImageMetadataDB;
|
|
using static Rec_rewild_live_rewrite.api.server.Classes.db_class.EventDBClasses;
|
|
using static Rec_rewild_live_rewrite.api.server.Classes.db_class.RoomDBClasses;
|
|
using static Rec_rewild_live_rewrite.api.server.Classes.RRPlus;
|
|
using static Rec_rewild_live_rewrite.api.WebsocketEvents;
|
|
using System.Text.Json.Nodes;
|
|
using System.Text.Json;
|
|
using System.IO;
|
|
|
|
namespace Rec_rewild_live_rewrite.Controllers
|
|
{
|
|
[ApiController]
|
|
public class APIController : ControllerBase
|
|
{
|
|
private static readonly string UPTIME = DateTime.UtcNow.ToString("o");
|
|
|
|
|
|
[HttpGet("/api/versioncheck/v4")]
|
|
public IActionResult VersionCheck([FromQuery(Name = "v"), Required] string appVersion, [FromQuery(Name = "p"), Required] int? platform)
|
|
{
|
|
/*if (appVersion == "20250731.01")
|
|
{
|
|
return Ok(new VersionCheck
|
|
{
|
|
ValidVersion = VersionStatus.ValidForPlay,
|
|
VersionStatus = VersionStatus.ValidForPlay,
|
|
UpdateNotificationStage = UpdateNoti.None,
|
|
IsVersionIslanded = false,
|
|
IsCrossPlayDisabled = false
|
|
});
|
|
}
|
|
|
|
return Ok(new VersionCheck
|
|
{
|
|
ValidVersion = VersionStatus.UpdateRequired,
|
|
VersionStatus = VersionStatus.UpdateRequired,
|
|
UpdateNotificationStage = UpdateNoti.Prompt,
|
|
IsVersionIslanded = true,
|
|
IsCrossPlayDisabled = false
|
|
});*/
|
|
return Ok(new VersionCheck
|
|
{
|
|
ValidVersion = VersionStatus.ValidForPlay,
|
|
VersionStatus = VersionStatus.ValidForPlay,
|
|
UpdateNotificationStage = UpdateNoti.None,
|
|
IsVersionIslanded = false,
|
|
IsCrossPlayDisabled = false
|
|
});
|
|
}
|
|
|
|
[HttpGet("/api/versioncheck/islandedversions")]
|
|
public IActionResult IslandedVersions()
|
|
{
|
|
return Ok(ConfigRewild.Bracket);
|
|
}
|
|
|
|
[HttpGet("/api/gameconfigs/v1/all")]
|
|
public IActionResult Gameconfigs()
|
|
{
|
|
string path = Path.Combine(Environment.CurrentDirectory, "Data", "APIS", "Gameconfigs.json");
|
|
|
|
if (!System.IO.File.Exists(path))
|
|
{
|
|
Console.WriteLine("Warning: Gameconfigs.json not found, returning []");
|
|
return Ok(ConfigRewild.Bracket);
|
|
}
|
|
|
|
return PhysicalFile(path, "application/json");
|
|
}
|
|
|
|
|
|
[HttpGet("/api/config/v1/amplitude")] // Get amplitude, analytics stuff - e12354
|
|
public ContentResult Amplitude()
|
|
{
|
|
return new ContentResult
|
|
{
|
|
Content = JsonConvert.SerializeObject(new Amplitude2023
|
|
{
|
|
AmplitudeKey = "cb2fb2ecb9953512c29af5bca58f2b4a",
|
|
UseRudderStack = true,
|
|
RudderStackKey = "23NiJHIgu3koaGNCZIiuYvIQNCu",
|
|
UseStatSig = ConfigRewild.StatsigEnabled,
|
|
StatSigKey = "client-SBZkOrjD3r1Cat3f3W8K6sBd11WKlXZXIlCWj6l4Aje",
|
|
StatSigEnvironment = 0
|
|
}),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/avatar/v1/defaultunlocked")]
|
|
public ContentResult DefaultUnlockeItems()
|
|
{
|
|
return new ContentResult
|
|
{
|
|
Content = ConfigRewild.DefaultUnlocked,
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/customAvatarItems/v1/isCreationAllowedForAccount")]
|
|
public ContentResult IsCreationAllowedForAccount()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult
|
|
{
|
|
Content = JsonConvert.SerializeObject(new SuccessResponse
|
|
{
|
|
success = true,
|
|
value = null
|
|
}),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/objectives/v1/myprogress")]
|
|
public ContentResult MyObjectivesProgress()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult
|
|
{
|
|
Content = JsonConvert.SerializeObject(new MyObjectives
|
|
{
|
|
Objectives = new List<object>(),
|
|
ObjectiveGroups = new List<object>()
|
|
}),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpPost("/api/PlayerReporting/v1/moderationBlockDetails")]
|
|
public IActionResult ModerationBlockDetails()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok(PlayerDB.Get_moderation_block(account.Id));
|
|
}
|
|
|
|
[HttpPost("/api/PlayerReporting/v1/hile")]
|
|
public IActionResult HileAPI([FromForm] Hile.HileTypes Type, [FromForm] string? Message)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok("false");
|
|
}
|
|
|
|
[HttpGet("/api/avatar/v2")]
|
|
public IActionResult myAvatarV2()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
ulong targetId = account.Id;
|
|
|
|
player_data player = PlayerDB.GetFullAccount(targetId);
|
|
if (player == null)
|
|
{
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 400
|
|
};
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(player.player_Extra.avatar))
|
|
{
|
|
return Ok(new
|
|
{
|
|
LegacyData = new
|
|
{
|
|
SelectionsV1 = (string?)null,
|
|
SelectionsV2 = (string?)null,
|
|
FaceFeatures = (string?)null,
|
|
SkinColor = (string?)null,
|
|
HairColor = (string?)null
|
|
},
|
|
Selections = Array.Empty<object>(),
|
|
DataVersion = 9,
|
|
CustomizationSettings = (string?)null,
|
|
ThumbnailFileName = (string?)null,
|
|
Name = (string?)null,
|
|
Accessibility = 0,
|
|
Slot = 0
|
|
});
|
|
}
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = player.player_Extra.avatar,
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/avatar/v2/{accid?}")]
|
|
public ContentResult AvatarV2(ulong? accid = null)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
ulong targetId = accid ?? account.Id;
|
|
|
|
player_data player = PlayerDB.GetFullAccount(targetId);
|
|
if (player == null)
|
|
{
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 400
|
|
};
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(player.player_Extra.avatar))
|
|
{
|
|
return new ContentResult()
|
|
{
|
|
Content = JsonConvert.SerializeObject(new
|
|
{
|
|
FaceFeatures = "",
|
|
HairColor = "",
|
|
OutfitSelections = "",
|
|
SkinColor = ""
|
|
}),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = player.player_Extra.avatar,
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/avatar/v4/items")]
|
|
public async Task<IActionResult> GetAvatarItems()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
string path = Path.Combine(
|
|
Environment.CurrentDirectory,
|
|
"Data",
|
|
"APIS",
|
|
"items",
|
|
"avatar_items.json"
|
|
);
|
|
|
|
if (!System.IO.File.Exists(path))
|
|
return Ok(ConfigRewild.Bracket);
|
|
|
|
return PhysicalFile(path, "application/json");
|
|
}
|
|
|
|
[HttpGet("/api/checklist/v1/current")]
|
|
public ContentResult CurrentChecklist()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/players/v2/progression/bulk")]
|
|
public ContentResult BulkPlayersProgression([FromQuery] List<ulong> id)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
if (id == null || id.Count == 0)
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
|
|
var result = id.Select(Progress.GetPlayerLevel);
|
|
return new ContentResult()
|
|
{
|
|
Content = JsonConvert.SerializeObject(result),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/announcement/v1/get")]
|
|
public ContentResult GetAnnouncements()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/equipment/v2/getUnlocked")]
|
|
public IActionResult GetUnlockedEquipment()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
string path = Path.Combine(
|
|
Environment.CurrentDirectory,
|
|
"Data",
|
|
"APIS",
|
|
"items",
|
|
"Equipments.json"
|
|
);
|
|
|
|
if (!System.IO.File.Exists(path))
|
|
return Ok(Array.Empty<object>());
|
|
|
|
return PhysicalFile(path, "application/json");
|
|
}
|
|
|
|
[HttpGet("/api/consumables/v2/getUnlocked")]
|
|
public IActionResult GetUnlockedConsumables()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
string path = Path.Combine(
|
|
Environment.CurrentDirectory,
|
|
"Data",
|
|
"APIS",
|
|
"items",
|
|
"Consumables.json"
|
|
);
|
|
|
|
if (!System.IO.File.Exists(path))
|
|
return Ok(Array.Empty<object>());
|
|
|
|
return PhysicalFile(path, "application/json");
|
|
}
|
|
|
|
[HttpGet("/api/playerReputation/v2/bulk")]
|
|
public ContentResult BulkPlayersReputation([FromQuery] List<ulong> id)
|
|
{
|
|
if (id == null || id.Count == 0)
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
|
|
var reps = new List<Rep>();
|
|
// var player = PlayerDB.GetFullAccount(account.Id);
|
|
foreach (var playerId in id)
|
|
{
|
|
var acc = PlayerDB.GetFullAccount(playerId);
|
|
if (acc?.player == null)
|
|
continue;
|
|
|
|
var rep = acc.player.PlayerReputation ?? new mPlayerReputation();
|
|
var extra = acc.player_Extra;
|
|
|
|
reps.Add(new Rep
|
|
{
|
|
AccountId = playerId,
|
|
IsCheerful = rep.IsCheerful,
|
|
Noteriety = 0,
|
|
SelectedCheer = rep.SelectedCheer,
|
|
CheerCredit = rep.CheerCredit,
|
|
CheerGeneral = rep.CheerGeneral,
|
|
CheerHelpful = rep.CheerHelpful,
|
|
CheerCreative = rep.CheerCreative,
|
|
CheerGreatHost = rep.CheerGreatHost,
|
|
CheerSportsman = rep.CheerSportsman,
|
|
});
|
|
}
|
|
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = JsonConvert.SerializeObject(reps),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/roomkeys/v1/mine")]
|
|
public ContentResult my_roomkeys()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
|
|
[HttpGet("/api/avatar/v1/defaultbaseavataritems")]
|
|
public ContentResult DefaultBaseAvatarItems()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = ConfigRewild.DefaultBaseAvatarItems,
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/avatar/v1/lockeditems/bulk")]
|
|
public ContentResult GetLockedItemsBulk([FromBody] LockedItems request)
|
|
{
|
|
|
|
|
|
string path = Path.Combine("Data", "AvatarItems.json");
|
|
if (!System.IO.File.Exists(path))
|
|
return new ContentResult
|
|
{
|
|
Content = "[]",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
|
|
var allItems = JArray.Parse(System.IO.File.ReadAllText(path));
|
|
|
|
JArray filteredItems = new JArray();
|
|
if (request.AvatarItemDescriptions != null && request.AvatarItemDescriptions.Count > 0)
|
|
{
|
|
foreach (var item in allItems)
|
|
{
|
|
string desc = item["AvatarItemDesc"]?.ToString();
|
|
if (desc != null && request.AvatarItemDescriptions.Contains(desc))
|
|
{
|
|
filteredItems.Add(item);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
filteredItems = allItems;
|
|
}
|
|
|
|
return new ContentResult
|
|
{
|
|
Content = filteredItems.ToString(),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/config/v1/backtrace")]
|
|
public ContentResult Backtrace()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = JsonConvert.SerializeObject(new
|
|
{
|
|
ReportBudget = 0,
|
|
FilterType = 0,
|
|
SampleRate = 0.025,
|
|
LogLineCount = 50,
|
|
CaptureNativeCrashes = 1,
|
|
ANRThresholdMs = 0,
|
|
MessageCount = 1000,
|
|
MessageRegex = "^Cannot set the parent of the GameObject .* while its new parent|^\\>\\x2010x\\:\\x20|'LabelTheme' contains missing PaletteTheme reference on",
|
|
VersionRegex = ".*"
|
|
}),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/config/v2")]
|
|
public ContentResult ConfigV2()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
var levels = new List<LevelProgressionMap>();
|
|
levels.Add(new LevelProgressionMap { Level = 0, RequiredXp = 1, GiftDropId = null });
|
|
for (int i = 1; i <= 20; i++)
|
|
{
|
|
levels.Add(new LevelProgressionMap
|
|
{
|
|
Level = i,
|
|
RequiredXp = i + 1,
|
|
GiftDropId = 0
|
|
});
|
|
}
|
|
|
|
var dailySet = new List<DailyObjective>
|
|
{
|
|
new DailyObjective { Type = 20, Score = 1, Xp = 200 },
|
|
new DailyObjective { Type = 21, Score = 1, Xp = 200 },
|
|
new DailyObjective { Type = 22, Score = 1, Xp = 200 }
|
|
};
|
|
|
|
var dailyObjectives = new List<List<DailyObjective>>();
|
|
for (int i = 0; i < 7; i++)
|
|
dailyObjectives.Add(new List<DailyObjective>(dailySet));
|
|
|
|
string url = $"{Request.Scheme}://{Request.Host}";
|
|
|
|
var config = new Config
|
|
{
|
|
MessageOfTheDay = "Welcome to Rec_rewild live!",
|
|
CdnBaseUri = $"{url}",
|
|
ShareBaseUrl = $"{url}/share/{0}",
|
|
LevelProgressionMaps = levels,
|
|
MatchmakingParams = new MatchmakingParams
|
|
{
|
|
PreferFullRoomsFrequency = 1.0,
|
|
PreferEmptyRoomsFrequency = 0.0
|
|
},
|
|
DailyObjectives = dailyObjectives,
|
|
ServerMaintainence = new ServerMaintenance
|
|
{
|
|
StartsInMinutes = 0
|
|
},
|
|
AutoMicMutingConfig = new AutoMicMutingConfig
|
|
{
|
|
MicSpamVolumeThreshold = 10.0,
|
|
MicVolumeSampleInterval = 1.0,
|
|
MicVolumeSampleRollingWindowLength = 15.0,
|
|
MicSpamSamplePercentageForWarning = 100.0,
|
|
MicSpamSamplePercentageForWarningToEnd = 0.0,
|
|
MicSpamSamplePercentageForForceMute = 500.0,
|
|
MicSpamSamplePercentageForForceMuteToEnd = 0.0,
|
|
MicSpamWarningStateVolumeMultiplier = 10.0
|
|
},
|
|
StorefrontConfig = new StorefrontConfig
|
|
{
|
|
MinPlayerLevelForGifting = 0
|
|
},
|
|
RoomKeyConfig = new RoomKeyConfig
|
|
{
|
|
MaxKeysPerRoom = 100
|
|
},
|
|
RoomCurrencyConfig = new RoomCurrencyConfig
|
|
{
|
|
AwardCurrencyCooldownSeconds = 10.0
|
|
},
|
|
ConfigTable = new List<ConfigTableEntry>
|
|
{
|
|
new ConfigTableEntry { Key = "Gift.DropChance", Value = "1" },
|
|
new ConfigTableEntry { Key = "Gift.XP", Value = "0.5" }
|
|
},
|
|
PhotonConfig = new PhotonConfig
|
|
{
|
|
CloudRegion = "us",
|
|
CrcCheckEnabled = false,
|
|
EnableServerTracingAfterDisconnect = false
|
|
}
|
|
};
|
|
|
|
return new ContentResult
|
|
{
|
|
Content = JsonConvert.SerializeObject(config, Formatting.None),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/storefronts/v3/giftdropstore/{StoreId}")]
|
|
public IActionResult GetGiftdropStore(int StoreId)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok(new
|
|
{
|
|
NewUntil = (string?)null,
|
|
NextUpdate = "9999-12-31T18:00:00Z",
|
|
StoreItems = Array.Empty<object>(),
|
|
StorefrontName = (string?)null,
|
|
StorefrontType = StoreId,
|
|
SubscriberDiscountPercent = 10
|
|
});
|
|
}
|
|
|
|
[HttpGet("/api/challenge/v2/getCurrent")]
|
|
public ContentResult GetCurrentChallenges()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/PlayerReporting/v1/voteToKickReasons")]
|
|
public ContentResult VoteToKickReasons()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
var reasons = new[]
|
|
{
|
|
new { Reason = "Discriminatory language", ReportCategory = 102 },
|
|
new { Reason = "Discriminatory behavior", ReportCategory = 102 },
|
|
new { Reason = "Threats or encouraging suicide", ReportCategory = 102 },
|
|
new { Reason = "Toxic behavior", ReportCategory = 102 },
|
|
new { Reason = "Sexual behavior in public", ReportCategory = 101 },
|
|
new { Reason = "Sexual language in public", ReportCategory = 101 },
|
|
new { Reason = "Non-consensual sexual behavior", ReportCategory = 101 },
|
|
new { Reason = "Player in walls or floor", ReportCategory = 103 },
|
|
new { Reason = "Friendly fire", ReportCategory = 103 },
|
|
new { Reason = "Microphone spam", ReportCategory = 103 },
|
|
new { Reason = "Abusing bugs or exploits", ReportCategory = 103 },
|
|
new { Reason = "Spawn camping", ReportCategory = 103 },
|
|
new { Reason = "Inactive in games (AFK)", ReportCategory = 6 },
|
|
new { Reason = "Prefab swapping", ReportCategory = 6 },
|
|
new { Reason = "Not following game rules", ReportCategory = 6 }
|
|
};
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = JsonConvert.SerializeObject(reasons),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/images/v2/named")]
|
|
public ContentResult NamedImages()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/avatar/v2/gifts")]
|
|
public ContentResult Gifts()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/gamerewards/v1/pending")]
|
|
public ContentResult PendingGameRewards()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/communityboard/v2/current")]
|
|
public ContentResult CurrentCommunityBoard()
|
|
{
|
|
string authtoken = HttpContext.Request.Headers["Authorization"].ToString();
|
|
|
|
if (string.IsNullOrEmpty(authtoken))
|
|
{
|
|
authtoken = HttpContext.Request.Cookies["Authorization"];
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(authtoken))
|
|
{
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 401
|
|
};
|
|
}
|
|
string playerdata = ClientSecurity.DecodeToken(authtoken);
|
|
if (playerdata == null)
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 401
|
|
};
|
|
if (playerdata.Contains("error_token"))
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 401
|
|
};
|
|
player_info account = JsonConvert.DeserializeObject<player_info>(playerdata);
|
|
|
|
string filePath = Path.Combine(Environment.CurrentDirectory, "Data", "APIS", "communityboard.json");
|
|
string content = System.IO.File.ReadAllText(filePath);
|
|
return new ContentResult()
|
|
{
|
|
Content = content,
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/storefronts/v4/balance/{balance_type}")]
|
|
public ContentResult StorefrontBalance(int balance_type = 0)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
var balance = new[]
|
|
{
|
|
new
|
|
{
|
|
Balance = 0,
|
|
BalanceType = balance_type,
|
|
CurrencyType = balance_type,
|
|
Platform = 0
|
|
}
|
|
};
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = JsonConvert.SerializeObject(balance),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/customAvatarItems/v1/isCreationEnabled")]
|
|
public ContentResult IsCreationEnabled()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
player_data FullAccount = PlayerDB.GetFullAccount(account.Id);
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "true",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/customAvatarItems/v1/isRenderingEnabled")]
|
|
public ContentResult IsRenderingEnabled()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
player_data FullAccount = PlayerDB.GetFullAccount(account.Id);
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "true",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpPost("/api/CampusCard/v1/UpdateAndGetSubscription")]
|
|
public IActionResult RRPlus()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
var subscription = new SubscriptionResponse
|
|
{
|
|
subscription = new Subscription
|
|
{
|
|
subscriptionId = 507911,
|
|
recNetPlayerId = account.Id,
|
|
platformType = 0,
|
|
platformId = "76561198216660599",
|
|
platformPurchaseId = "4069635207998545083",
|
|
@event = null,
|
|
type = 0,
|
|
level = 0,
|
|
period = 0,
|
|
expirationDate = new DateTime(2024, 3, 20, 12, 0, 0, DateTimeKind.Utc),
|
|
isAutoRenewing = false,
|
|
createdAt = new DateTime(2024, 2, 18, 7, 15, 0, 284, DateTimeKind.Utc).AddTicks(5308),
|
|
modifiedAt = new DateTime(2024, 3, 20, 7, 1, 55, DateTimeKind.Utc).AddTicks(3454572)
|
|
},
|
|
platformAccountSubscribedPlayerId = null
|
|
};
|
|
|
|
return Content(System.Text.Json.JsonSerializer.Serialize(subscription), "application/json");
|
|
}
|
|
|
|
[HttpGet("/api/subscriptionseasons/v1/seasons/current")]
|
|
public ContentResult RRPlus2()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/inventions/v2/mine")]
|
|
public ContentResult MyInventions()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]", // todo db
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/roomkeys/v1/room")]
|
|
public ContentResult Roomkeys()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]", // todo db
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/roomcurrencies/v1/currencies")]
|
|
public ContentResult RoomCurrencies()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]", // todo db
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/roomconsumables/v1/roomConsumable/room/{RoomId}")]
|
|
public ContentResult RoomConsumables(ulong RoomId)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]", // todo db
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/roomconsumables/v1/roomConsumable/room/{RoomId}/me")]
|
|
public ContentResult MyRoomConsumables(ulong RoomId)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]", // todo db
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/roomcurrencies/v1/getAllBalances")]
|
|
public ContentResult GetAllRoomCurrenciesBalances()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]", // todo db
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/images/v1/slideshow")]
|
|
public ContentResult Slideshow()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]", // todo db
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/itemWishlists/v1/wishlist/me")]
|
|
public IActionResult MyItemWishlists()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok(ConfigRewild.Bracket);
|
|
}
|
|
|
|
[HttpGet("/api/itemWishlists/v1/wishlist/{playerId}")]
|
|
public IActionResult GetWishlistForPlayer(ulong playerId)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok(ConfigRewild.Bracket);
|
|
}
|
|
|
|
[HttpGet("/api/server/status")]
|
|
public ContentResult status()
|
|
{
|
|
|
|
string key = HttpContext.Request.Headers["key"].ToString();
|
|
|
|
if (key == ConfigRewild.VALID_STATUS_KEY)
|
|
{
|
|
return new ContentResult
|
|
{
|
|
Content = JsonConvert.SerializeObject(new
|
|
{
|
|
uptime = UPTIME,
|
|
}),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
else
|
|
{
|
|
return new ContentResult
|
|
{
|
|
Content = JsonConvert.SerializeObject(new
|
|
{
|
|
message = "Forbidden!"
|
|
}),
|
|
ContentType = "application/json",
|
|
StatusCode = 403
|
|
};
|
|
}
|
|
}
|
|
|
|
[HttpPost("/api/sanitize/v1")]
|
|
public IActionResult APISanitizeV1([FromBody] Sanitize request)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
string value = request?.Value ?? "";
|
|
|
|
if (ConfigRewild.AllowSwears == true)
|
|
{
|
|
return Content(JsonConvert.SerializeObject(value), "application/json");
|
|
}
|
|
string sanitized = Sanitize.SanitizeMessage(value);
|
|
if (ConfigRewild.LogMessagesFromSanitize == true)
|
|
{
|
|
_ = Task.Run(() =>
|
|
{
|
|
try
|
|
{
|
|
Webhook.Send(account.Id, "mod", "Reporting Info - Sanitize", $"({account.Id}) @{account.Username} \n**Sanitize requested!**\n" +
|
|
$"**Current Room:** {HeartbeatDB.GetPlayerCurrentRoomName(account.Id)}\n" +
|
|
$"**Request Message:** \"{value}\"\n" +
|
|
$"**Sanitized Message:** \"{sanitized}\"\n" +
|
|
$"**Context:** \"{request.Context}\""
|
|
, 5898927);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.Error.WriteLine(ex);
|
|
}
|
|
});
|
|
}
|
|
return Content(JsonConvert.SerializeObject(sanitized), "application/json");
|
|
}
|
|
|
|
[HttpPost("/api/sanitize/v1/isPure")]
|
|
public IActionResult ApiSanitizeV1IsPure([FromBody] Sanitize request)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
var isPure = !Sanitize.ContainsSwears(request.Value);
|
|
|
|
return Ok(new
|
|
{
|
|
IsPure = isPure
|
|
});
|
|
}
|
|
|
|
[HttpGet("/api/customAvatarItems/v2/fromCreator/{PlayerId}")]
|
|
public ContentResult CustomAvatarItemsFromCreator(ulong PlayerId)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = JsonConvert.SerializeObject(new RoomDBClasses.Resultslist<RoomDBClasses.RoomRoot>
|
|
{
|
|
Results = [],
|
|
TotalResults = 0
|
|
}),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
|
|
[HttpGet("/api/influencerpartnerprogram/influencer")]
|
|
public ContentResult influencerpartnerprogram(ulong accountId)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 404
|
|
};
|
|
}
|
|
|
|
[HttpPost("/api/avatar/v2/set")]
|
|
public async Task<ContentResult> SetAvatar()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
string jsonData = "";
|
|
try
|
|
{
|
|
using var reader = new StreamReader(HttpContext.Request.Body);
|
|
jsonData = await reader.ReadToEndAsync();
|
|
}
|
|
catch
|
|
{
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 400
|
|
};
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(jsonData))
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 400
|
|
};
|
|
|
|
try
|
|
{
|
|
Newtonsoft.Json.Linq.JToken.Parse(jsonData);
|
|
}
|
|
catch
|
|
{
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 400
|
|
};
|
|
}
|
|
|
|
|
|
var player = PlayerDB.GetFullAccount(account.Id);
|
|
if (player == null)
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 401
|
|
};
|
|
|
|
try
|
|
{
|
|
PlayerDB.set_player_avatar(jsonData, player.playerid);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"[Avatar Set Error] {ex}");
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 400
|
|
};
|
|
}
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
|
|
[HttpPost("/api/consumables/v1/consume")]
|
|
public IActionResult ConsumeConsumable()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok("");
|
|
}
|
|
|
|
[HttpGet("/api/online_players")]
|
|
public IActionResult OnlinePlayers()
|
|
{
|
|
var onlineList = new List<object>();
|
|
|
|
foreach (var (playerId, socket) in NotificationsController.WebSockets)
|
|
{
|
|
onlineList.Add(new
|
|
{
|
|
PlayerId = playerId,
|
|
CurrentRoom = HeartbeatDB.GetPlayerCurrentRoomName(playerId)
|
|
});
|
|
}
|
|
|
|
return Ok(onlineList);
|
|
}
|
|
|
|
[HttpGet("/api/ping")]
|
|
public ContentResult ServerPing()
|
|
{
|
|
return new ContentResult
|
|
{
|
|
Content = "true",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
// todo check if it a real image file and return a 400 error if it not a image file - Waeboi69
|
|
[HttpPost("/api/images/v4/uploadsaved")]
|
|
public async Task<ContentResult> UploadImage()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
HttpContext.Request.EnableBuffering();
|
|
|
|
byte[] array;
|
|
using (var memoryStream = new MemoryStream(capacity: 4 * 1024 * 1024))
|
|
{
|
|
await HttpContext.Request.Body.CopyToAsync(memoryStream, bufferSize: 131072);
|
|
array = memoryStream.ToArray();
|
|
}
|
|
|
|
HttpContext.Request.Body.Position = 0;
|
|
|
|
var saveImageTask = Task.Run(() => Images.SaveImageFile(array));
|
|
var formTask = HttpContext.Request.ReadFormAsync();
|
|
|
|
var file = await saveImageTask.ConfigureAwait(false);
|
|
var form = await formTask.ConfigureAwait(false);
|
|
|
|
if (!form.TryGetValue("imgMeta", out var imgMetaValue) || string.IsNullOrEmpty(imgMetaValue))
|
|
{
|
|
return new ContentResult
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 400
|
|
};
|
|
}
|
|
|
|
ImageMetadataDB.ImageMetadata? metadata = null;
|
|
|
|
if (!string.IsNullOrEmpty(imgMetaValue))
|
|
{
|
|
metadata = JsonConvert.DeserializeObject<ImageMetadataDB.ImageMetadata>(imgMetaValue!);
|
|
}
|
|
|
|
var newImage = new FullSavedImage
|
|
{
|
|
Id = 0,
|
|
RoomId = metadata.roomId,
|
|
PlayerId = account.Id,
|
|
ImageName = file.rawfilename,
|
|
Description = metadata.description,
|
|
Accessibility = metadata.accessibility,
|
|
TaggedPlayerIds = metadata.playerIds,
|
|
CreatedAt = DateTime.UtcNow
|
|
};
|
|
|
|
if (metadata.savedImageType != SavedImageTypeEnum.OutfitThumbnail)
|
|
{
|
|
await Task.Run(() => ImageMetadataDB.InsertImage(newImage)).ConfigureAwait(false);
|
|
|
|
if (metadata.accessibility == ImageAccessibility.Public)
|
|
{
|
|
_ = Task.Run(() => Webhook.Send(
|
|
account.Id, "prod", "Server info",
|
|
$"({account.Id}) @{account.Username} has uploaded an image",
|
|
5898927, $"https://recrewild.oldrec.net/img/{file.rawfilename}"
|
|
));
|
|
}
|
|
}
|
|
|
|
return new ContentResult
|
|
{
|
|
Content = JsonConvert.SerializeObject(new
|
|
{
|
|
success = true,
|
|
error = "",
|
|
ImageName = file.rawfilename
|
|
}),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
|
|
[HttpGet("/api/images/v6")]
|
|
public ContentResult GetImageByImageName(string name)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
try
|
|
{
|
|
var image = ImageMetadataDB.GetImageByName(name);
|
|
|
|
if (image != null)
|
|
{
|
|
return new ContentResult
|
|
{
|
|
Content = JsonConvert.SerializeObject(image, Formatting.Indented),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
return new ContentResult
|
|
{
|
|
Content = "[]",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"[Image V6 Error] {ex}");
|
|
return new ContentResult
|
|
{
|
|
Content = "[]",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
}
|
|
|
|
[HttpGet("/api/images/v5/cheered/bulk")]
|
|
public ContentResult ImagesCheered([FromQuery] int[] id)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
var results = id.Select(imageId => new
|
|
{
|
|
SavedImageId = imageId,
|
|
IsCheered = ImageMetadataDB.HasUserCheered(imageId, account.Id)
|
|
}).ToList();
|
|
|
|
return new ContentResult
|
|
{
|
|
Content = JsonConvert.SerializeObject(results),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/images/v4/room/{id}")]
|
|
public ContentResult GetRoomImages(int id, int sort = 0, int filter = 0, int take = 50, int skip = 0)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
var images = ImageMetadataDB.GetRoomImages(account.Id, id, sort, filter, take, skip);
|
|
return new ContentResult
|
|
{
|
|
Content = JsonConvert.SerializeObject(images, Formatting.Indented),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpPost("/api/images/v1/cheer")]
|
|
public ContentResult CheerImage([FromBody] CheerRequest request)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
bool isCheered = ImageMetadataDB.ToggleCheer(request.SavedImageId, account.Id, request.Cheer);
|
|
int cheerCount = ImageMetadataDB.GetCheerCount(request.SavedImageId);
|
|
|
|
ImageMetadataDB.UpdateImageCheerCount(request.SavedImageId, cheerCount);
|
|
|
|
return new ContentResult
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/images/v5/player/{playerid}")]
|
|
public IActionResult GetPlayerImages(ulong playerid, int sort = 0)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
var playerImages = ImageMetadataDB.GetPlayerImages(account.Id, playerid);
|
|
|
|
return Ok(playerImages);
|
|
}
|
|
|
|
[HttpGet("/api/images/v5/bulk")]
|
|
public ContentResult GetImagesByBulkIds()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
var idsRaw = Request.Query["ids"];
|
|
|
|
List<int> idList = idsRaw
|
|
.SelectMany(x => x.Split(',', StringSplitOptions.RemoveEmptyEntries))
|
|
.Select(x => x.Trim())
|
|
.Where(x => int.TryParse(x, out _))
|
|
.Select(int.Parse)
|
|
.ToList();
|
|
|
|
if (idList.Count == 0)
|
|
{
|
|
return new ContentResult
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 400
|
|
};
|
|
}
|
|
|
|
var images = ImageMetadataDB.GetImagesByIds(idList);
|
|
|
|
return new ContentResult
|
|
{
|
|
Content = JsonConvert.SerializeObject(images),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
|
|
[HttpGet("/api/rooms/v1/filters")]
|
|
public ContentResult GetRoomTags()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
var roomTags = new
|
|
{
|
|
PinnedFilters = new[]
|
|
{
|
|
"recroomoriginal", "community", "featured", "quest", "pvp", "hangout", "game",
|
|
"art", "store", "tutorial", "fandom", "performance", "action", "horror"
|
|
},
|
|
PopularFilters = new[]
|
|
{
|
|
"pvp", "quest", "game", "hangout", "art"
|
|
},
|
|
TrendingFilters = new[]
|
|
{
|
|
"roleplay", "nomp", "rp", "casual", "fun", "action", "military", "sports"
|
|
}
|
|
};
|
|
|
|
return new ContentResult
|
|
{
|
|
Content = JsonConvert.SerializeObject(roomTags),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/inventions/v1/room")]
|
|
public ContentResult RoomInventions(ulong id)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult
|
|
{
|
|
Content = "[]",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpPost("/api/rooms/v1/verifyRole")]
|
|
public ContentResult VerifyRole()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult
|
|
{
|
|
Content = "[]",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/avatar/v3/saved")]
|
|
public ContentResult GetOutfit()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = PlayerDB.GetAvatarSaved(account.Id),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpPost("/api/avatar/v4/saved/set")]
|
|
public async Task<ContentResult> SaveOutfit()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
using var reader = new StreamReader(HttpContext.Request.Body);
|
|
string body = await reader.ReadToEndAsync();
|
|
|
|
avatar_data_saved avatar;
|
|
try
|
|
{
|
|
avatar = JsonConvert.DeserializeObject<avatar_data_saved>(body);
|
|
if (avatar == null)
|
|
throw new Exception("Deserialization returned null");
|
|
|
|
Console.WriteLine($"Slot: {avatar.Slot}, Name: {avatar.Name}, SkinColor: {avatar.SkinColor}");
|
|
|
|
|
|
PlayerDB.SetAvatarSaved(account.Id, new List<avatar_data_saved> { avatar });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine("Failed to parse or save avatar JSON: " + ex.Message);
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 400
|
|
};
|
|
}
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = JsonConvert.SerializeObject(new
|
|
{
|
|
Success = true,
|
|
Slot = avatar.Slot
|
|
}),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpPost("/api/PlayerCheer/v1/SetSelectedCheer")]
|
|
public async Task<ContentResult> SetSelectedCheer()
|
|
{
|
|
try
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
string? cheerCategoryStr = HttpContext.Request.Form["CheerCategory"];
|
|
|
|
if (string.IsNullOrEmpty(cheerCategoryStr))
|
|
{
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
if (!Enum.TryParse<CheerCategoryEnum>(cheerCategoryStr, out var cheerCategory))
|
|
{
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 400
|
|
};
|
|
}
|
|
|
|
if (account == null)
|
|
{
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 401
|
|
};
|
|
}
|
|
await Task.Run(() => PlayerDB.SetPlayerCheer(cheerCategory, account.Id));
|
|
|
|
try
|
|
{
|
|
var selfUpdate = JsonConvert.SerializeObject(WebsocketEvents.CreateResponseReputationUpdate(account.Id));
|
|
var globalUpdate = JsonConvert.SerializeObject(WebsocketEvents.CreateResponseReputationUpdate(account.Id));
|
|
|
|
var notifySelfTask = Notifications.SendToPlayer(account.Id, selfUpdate);
|
|
var notifyAllTask = Notifications.SendToAll(globalUpdate);
|
|
|
|
await Task.WhenAll(notifySelfTask, notifyAllTask);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Failed to send notification: {ex.Message}");
|
|
}
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"SetSelectedCheer Error: {ex}");
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 400
|
|
};
|
|
}
|
|
}
|
|
|
|
[HttpGet("/api/incentivizedreferrals/progress")]
|
|
public ContentResult get_incentivizedreferrals_incentivizedreferrals()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = JsonConvert.SerializeObject(new
|
|
{
|
|
success = true,
|
|
value = new
|
|
{
|
|
ReferralsVerifiedCount = 0,
|
|
PlayerReferralRewards = new List<object>()
|
|
},
|
|
/*
|
|
[{
|
|
"UnlockedAt": null,
|
|
"ClaimedAt": null,
|
|
"Status": 0,
|
|
"ReferralRewardTier": {
|
|
"ReferralRewardTierId": 1,
|
|
"RequiredReferralCount": 1,
|
|
"RewardSelectionCount": 1
|
|
}
|
|
}]
|
|
*/
|
|
}),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
//https://econ.rec.net/api/influencerpartnerprogram/influencer?accountId=1503269750 return a 404 or a influencer account id
|
|
|
|
// /api/influencerpartnerprogram/support
|
|
|
|
// /api/inventions/v1/fromcreators // todo: add this
|
|
|
|
|
|
[HttpGet("/api/influencerpartnerprogram/influencers")]
|
|
public ContentResult GetAllInfluencers()
|
|
{
|
|
// https://econ.rec.net/api/influencerpartnerprogram/influencers?take=1000
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult
|
|
{
|
|
Content = JsonConvert.SerializeObject(new
|
|
{
|
|
InfluencerIds = PlayerDB.GetInfluencerIds(),
|
|
ContinuationToken = (string?)null
|
|
}),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpPost("/api/influencerpartnerprogram/support")]
|
|
public ContentResult SupportInfluencer()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
string? SupportIdStr = HttpContext.Request.Form["influencerAccountId"].ToString();
|
|
ulong SupportId = ulong.Parse(SupportIdStr);
|
|
PlayerDB.SupportInfluencer(account.Id, SupportId);
|
|
|
|
return new ContentResult
|
|
{
|
|
Content = JsonConvert.SerializeObject(new
|
|
{
|
|
success = true,
|
|
error = "",
|
|
value = (string?)null
|
|
}),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpPost("/api/influencerpartnerprogram/remove")]
|
|
public ContentResult RemoveInfluencer()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
PlayerDB.SupportInfluencer(account.Id, 0);
|
|
|
|
return new ContentResult
|
|
{
|
|
Content = JsonConvert.SerializeObject(new
|
|
{
|
|
success = true,
|
|
error = "",
|
|
value = (string?)null
|
|
}),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/influencerpartnerprogram/myinfluencer")]
|
|
public IActionResult MyInfluencer()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
var myInfluencer = PlayerDB.GetMyInfluencer(account.Id);
|
|
if (myInfluencer == 0)
|
|
{
|
|
return NotFound();
|
|
}
|
|
return Ok(myInfluencer);
|
|
}
|
|
|
|
// /api/relationships/v2/sendfriendrequest?id={playerid}
|
|
|
|
// /api/relationships/v2/addfriend?id={playerid}
|
|
|
|
// /api/relationships/v2/acceptfriendrequest?id={playerid}
|
|
|
|
[HttpGet("/api/relationships/v2/get")]
|
|
public ContentResult GetRelationships()
|
|
{
|
|
string authtoken = HttpContext.Request.Headers["Authorization"].ToString();
|
|
|
|
if (string.IsNullOrEmpty(authtoken))
|
|
{
|
|
authtoken = HttpContext.Request.Cookies["Authorization"];
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(authtoken))
|
|
{
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 401
|
|
};
|
|
}
|
|
string playerdata = ClientSecurity.DecodeToken(authtoken);
|
|
if (playerdata == null)
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 401
|
|
};
|
|
if (playerdata.Contains("error_token"))
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 401
|
|
};
|
|
player_info? account = JsonConvert.DeserializeObject<player_info>(playerdata);
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = JsonConvert.SerializeObject(FriendsDB.GetRelationships(account.Id)),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/relationships/v2/sendfriendrequest")]
|
|
public async Task<ContentResult> SendFriendRequest(ulong id) // player id
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
if (PlayerDB.CheckDevFlag(account.Id) && id == 1)
|
|
{
|
|
RelationshipDetail rs = FriendsDB.SendFriendRequest(id, account.Id);
|
|
|
|
_ = Task.Run(async () =>
|
|
{
|
|
await Task.Delay(1000);
|
|
FriendsDB.AcceptFriendRequest(account.Id, 1);
|
|
});
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = JsonConvert.SerializeObject(rs),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
|
|
RelationshipDetail relationship = FriendsDB.SendFriendRequest(id, account.Id);
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = JsonConvert.SerializeObject(relationship),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/relationships/v2/acceptfriendrequest")]
|
|
public ContentResult AcceptFriendRequest(ulong id) // player id
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
// Todo: add rate limiting
|
|
|
|
RelationshipDetail relationship = FriendsDB.AcceptFriendRequest(id, account.Id);
|
|
|
|
if (relationship == null)
|
|
{
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 400
|
|
};
|
|
}
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = JsonConvert.SerializeObject(relationship),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/relationships/v2/addfriend")]
|
|
public ContentResult AddFriendViaHandshakeInGame(ulong id) // player id
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
// Todo: add rate limiting
|
|
RelationshipDetail relationship = FriendsDB.AcceptFriendRequest(id, account.Id);
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = JsonConvert.SerializeObject(relationship),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/relationships/v2/removefriend")]
|
|
public ContentResult RemoveFriend(ulong id) // player id
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
//Todo: add rate limiting
|
|
|
|
RelationshipDetail relationship = FriendsDB.RemoveFriend(id, account.Id);
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = JsonConvert.SerializeObject(relationship),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
/*
|
|
[HttpPost("/api/customAvatarItems/v1")]
|
|
public async Task<ContentResult> CreateCustomAvatar()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
HttpContext.Request.EnableBuffering();
|
|
|
|
byte[] array;
|
|
using (var memoryStream = new MemoryStream(capacity: 4 * 1024 * 1024))
|
|
{
|
|
await HttpContext.Request.Body.CopyToAsync(memoryStream, bufferSize: 131072);
|
|
array = memoryStream.ToArray();
|
|
}
|
|
|
|
HttpContext.Request.Body.Position = 0;
|
|
|
|
// todo: get the desinflesti elif g
|
|
|
|
var saveImageTask = Task.Run(() => Images.SaveImageFile(array));
|
|
var formTask = HttpContext.Request.ReadFormAsync();
|
|
|
|
var file = await saveImageTask.ConfigureAwait(false);
|
|
var form = await formTask.ConfigureAwait(false);
|
|
if (!form.TryGetValue("metadata", out var metadatavalue) || string.IsNullOrEmpty(metadatavalue))
|
|
{
|
|
return new ContentResult
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 400
|
|
};
|
|
}
|
|
CreateCustomAvatarItemResponse metadata = JsonConvert.DeserializeObject<CreateCustomAvatarItemResponse>(metadatavalue);
|
|
if (metadata.Accessibility == 1)
|
|
{
|
|
return new ContentResult
|
|
{
|
|
Content = JsonConvert.SerializeObject(new
|
|
{
|
|
Success = false,
|
|
Value = (string?)null,
|
|
ErrorId = "Rooms.DoesntExist",
|
|
Error = "Sorry, that option is not available yet. Switch to 'Just Me'"
|
|
}),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = JsonConvert.SerializeObject(new
|
|
{
|
|
Success = true,
|
|
Value = metadata,
|
|
}),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
*/
|
|
|
|
[HttpPost("/api/customAvatarItems/v1/bulk")]
|
|
public IActionResult BulkCustomAvatarItems([FromForm] List<string> customAvatarItemIds)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
string path = Path.Combine(Environment.CurrentDirectory, "Data", "APIS", "customitems.json");
|
|
|
|
if (!System.IO.File.Exists(path))
|
|
{
|
|
return NotFound();
|
|
}
|
|
|
|
string json = System.IO.File.ReadAllText(path);
|
|
|
|
JObject root = JObject.Parse(json);
|
|
JArray results = (JArray)root["Results"];
|
|
|
|
var filtered = results
|
|
.Where(x => customAvatarItemIds.Contains((string)x["CustomAvatarItemId"]))
|
|
.ToList();
|
|
|
|
return new ContentResult
|
|
{
|
|
Content = JArray.FromObject(filtered).ToString(),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/inventions/v1/featured")]
|
|
public ContentResult FeaturedInventions()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]", // todo db
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/customAvatarItems/v1/featured")]
|
|
public IActionResult FeaturedCustomAvatarItems()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
string path = Path.Combine(Environment.CurrentDirectory, "Data", "APIS", "customitems.json");
|
|
var stream = System.IO.File.OpenRead(path);
|
|
|
|
return new FileStreamResult(stream, "application/json");
|
|
}
|
|
|
|
[HttpGet("/api/testcasemanagement/v1/{route}")]
|
|
public ContentResult TestCaseManagement(string route)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
if (route == "testplans")
|
|
{
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]", // todo db
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
if (route == "testpasssummary")
|
|
{
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]", // todo db
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]", // todo db
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/playerevents/v1/searchlive")]
|
|
public ContentResult SearchLivePlayerEvents()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]", // todo db
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpPut("roomconsumables/v1/roomConsumable")]
|
|
public ContentResult CreateRoomConsumable()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]", // todo db
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/messages/v2/get")]
|
|
public ContentResult GetMessages()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = JsonConvert.SerializeObject(PlayerDB.GetMessages(account.Id)),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpPost("/api/PlayerCheer/v1/create")]
|
|
public async Task<IActionResult> SendCheer([FromForm] ulong PlayerIdTo, [FromForm] int CheerCategory, [FromForm] ulong RoomId, [FromForm] bool Anonymous)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
/* What the game requests:
|
|
PlayerIdTo=1
|
|
CheerCategory=0
|
|
RoomId=1
|
|
Anonymous=False
|
|
*/
|
|
|
|
Rec_rewild_live_rewrite.api.WebsocketEvents.MessageType cheerType = Anonymous ? Rec_rewild_live_rewrite.api.WebsocketEvents.MessageType.PlayerCheerAnonymous : Rec_rewild_live_rewrite.api.WebsocketEvents.MessageType.PlayerCheer;
|
|
if (account.PlayerReputation.CheerCredit <= 0)
|
|
{
|
|
return Ok(new
|
|
{
|
|
success = false,
|
|
error = "You have no more cheers.",
|
|
value = (string?)null
|
|
});
|
|
}
|
|
|
|
if (PlayerIdTo == account.Id)
|
|
{
|
|
return Ok(new
|
|
{
|
|
success = false,
|
|
error = "You cannot cheer yourself!",
|
|
value = (string?)null
|
|
});
|
|
}
|
|
|
|
// decrease cheer credit by 1
|
|
await Task.Run(() =>
|
|
PlayerDB.SetCheerCredit(account.PlayerReputation.CheerCredit - 1, account.Id)
|
|
);
|
|
|
|
var newMsg = PlayerDB.AddMessage(
|
|
toPlayerId: PlayerIdTo,
|
|
fromPlayerId: account.Id,
|
|
type: cheerType,
|
|
data: CheerCategory.ToString(),
|
|
roomId: RoomId,
|
|
playerEventId: null
|
|
);
|
|
|
|
try
|
|
{
|
|
var response = JsonConvert.SerializeObject(
|
|
WebsocketEvents.CreateMessageResponse(newMsg)
|
|
);
|
|
|
|
var notifyTask = Notifications.SendToPlayer(PlayerIdTo, response);
|
|
await Task.WhenAll(notifyTask);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Failed to send notification: {ex.Message}");
|
|
}
|
|
|
|
return Ok(new
|
|
{
|
|
success = true,
|
|
error = "",
|
|
value = (string?)null
|
|
});
|
|
}
|
|
|
|
[HttpPost("/api/messages/v3/delete")]
|
|
public IActionResult DeleteMessages([FromBody] DeleteMessagesRequest request)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
if (request?.MessageIds == null || request.MessageIds.Count == 0)
|
|
{
|
|
return NoContent();
|
|
}
|
|
|
|
foreach (var id in request.MessageIds)
|
|
{
|
|
PlayerDB.DeleteMessage(account.Id, id);
|
|
}
|
|
|
|
return NoContent();
|
|
}
|
|
|
|
[HttpGet("/api/playerevents/v1/room/{RoomId}")]
|
|
public ContentResult PlayerEventsForRoom(ulong RoomId)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "[]", // todo db
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/playerevents/v1/tagfilters")]
|
|
public ContentResult PlayerEventsTagFilters()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
var tagfilters = new
|
|
{
|
|
PinnedFilters = new[]
|
|
{
|
|
"workshops",
|
|
"celebration",
|
|
"game",
|
|
"meetup",
|
|
"performance",
|
|
"coop",
|
|
"grandopening",
|
|
"class",
|
|
"competition"
|
|
},
|
|
PopularFilters = new[]
|
|
{
|
|
"workshops",
|
|
"celebration",
|
|
"class",
|
|
"coop",
|
|
"competition",
|
|
"game",
|
|
"grandopening",
|
|
"meetup",
|
|
"performance"
|
|
},
|
|
TrendingFilters = (string?)null
|
|
};
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = JsonConvert.SerializeObject(tagfilters),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpPost("/api/playerevents/v2")]
|
|
public ContentResult CreatePlayerEvent([FromBody] EventDBClasses.CreateEventRequest request)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
FullPlayerEvent NewlyCreatedEvent = EventDB.CreateEvent(account.Id, request);
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = JsonConvert.SerializeObject(new
|
|
{
|
|
Result = EventResults.Success,
|
|
TagModifyResult = (string?)null,
|
|
PlayerEvent = new
|
|
{
|
|
Tags = NewlyCreatedEvent.Tags,
|
|
PlayerEventId = NewlyCreatedEvent.PlayerEventId,
|
|
CreatorPlayerId = NewlyCreatedEvent.CreatorPlayerId,
|
|
ImageName = NewlyCreatedEvent.ImageName,
|
|
RoomId = NewlyCreatedEvent.RoomId,
|
|
SubRoomId = NewlyCreatedEvent.SubRoomId,
|
|
ClubId = NewlyCreatedEvent.ClubId,
|
|
Name = NewlyCreatedEvent.Name,
|
|
Description = NewlyCreatedEvent.Description,
|
|
StartTime = NewlyCreatedEvent.StartTime,
|
|
EndTime = NewlyCreatedEvent.EndTime,
|
|
AttendeeCount = NewlyCreatedEvent.AttendeeCount,
|
|
State = NewlyCreatedEvent.State,
|
|
ImageAccessibility = NewlyCreatedEvent.Accessibility,
|
|
IsMultiInstance = NewlyCreatedEvent.IsMultiInstance,
|
|
SupportMultiInstanceRoomChat = NewlyCreatedEvent.SupportMultiInstanceRoomChat,
|
|
DefaultBroadcastPermissions = NewlyCreatedEvent.DefaultBroadcastPermissions,
|
|
CanRequestBroadcastPermissions = NewlyCreatedEvent.CanRequestBroadcastPermissions,
|
|
RecurrenceSchedule = NewlyCreatedEvent.RecurrenceSchedule
|
|
}
|
|
}), // todo db
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/playerevents/v1/{EventId}/responses")]
|
|
public ContentResult PlayerEventResponsesForEventId(ulong EventId)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
var playerEvent = EventDB.GetFullEventById(EventId);
|
|
|
|
if (playerEvent == null)
|
|
{
|
|
return new ContentResult
|
|
{
|
|
Content = "[]",
|
|
ContentType = "application/json",
|
|
StatusCode = 404
|
|
};
|
|
}
|
|
|
|
return new ContentResult
|
|
{
|
|
Content = JsonConvert.SerializeObject(playerEvent.Responses ?? new List<FullEventResponses>()),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/playerevents/v1")]
|
|
public ContentResult GetAllEvents()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
var events = EventDB.SearchEventByQuery("");
|
|
|
|
return new ContentResult
|
|
{
|
|
Content = JsonConvert.SerializeObject(events.Select(e => new
|
|
{
|
|
e.PlayerEventId,
|
|
e.CreatorPlayerId,
|
|
e.ImageName,
|
|
e.RoomId,
|
|
e.SubRoomId,
|
|
e.ClubId,
|
|
e.Name,
|
|
e.Description,
|
|
e.StartTime,
|
|
e.EndTime,
|
|
e.AttendeeCount,
|
|
e.State,
|
|
e.Accessibility,
|
|
e.IsMultiInstance,
|
|
e.SupportMultiInstanceRoomChat,
|
|
e.DefaultBroadcastPermissions,
|
|
e.CanRequestBroadcastPermissions,
|
|
e.BroadcastingRoomInstanceId,
|
|
e.RecurrenceSchedule
|
|
})),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/playerevents/v1/all")]
|
|
public ContentResult GetAllEvents2()
|
|
{
|
|
//var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
//if (error != null)
|
|
// return error;
|
|
|
|
var events = EventDB.SearchEventByQuery("");
|
|
|
|
return new ContentResult
|
|
{
|
|
Content = JsonConvert.SerializeObject(new
|
|
{
|
|
Created = events.Select(e => new
|
|
{
|
|
e.PlayerEventId,
|
|
e.CreatorPlayerId,
|
|
e.ImageName,
|
|
e.RoomId,
|
|
e.SubRoomId,
|
|
e.ClubId,
|
|
e.Name,
|
|
e.Description,
|
|
e.StartTime,
|
|
e.EndTime,
|
|
e.AttendeeCount,
|
|
e.State,
|
|
e.Accessibility,
|
|
e.IsMultiInstance,
|
|
e.SupportMultiInstanceRoomChat,
|
|
e.DefaultBroadcastPermissions,
|
|
e.CanRequestBroadcastPermissions,
|
|
e.BroadcastingRoomInstanceId,
|
|
e.RecurrenceSchedule
|
|
}),
|
|
Responses = new List<object>(),
|
|
}),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpGet("/api/playerevents/v1/search")]
|
|
public ContentResult SearchEvents(string query = "", string sort = "Attendance", string scheduleFilter = "Upcoming")
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
var events = EventDB.SearchEventByQuery(query);
|
|
|
|
return new ContentResult
|
|
{
|
|
Content = JsonConvert.SerializeObject(events.Select(e => new
|
|
{
|
|
e.PlayerEventId,
|
|
e.CreatorPlayerId,
|
|
e.ImageName,
|
|
e.RoomId,
|
|
e.SubRoomId,
|
|
e.ClubId,
|
|
e.Name,
|
|
e.Description,
|
|
e.StartTime,
|
|
e.EndTime,
|
|
e.AttendeeCount,
|
|
e.State,
|
|
e.Accessibility,
|
|
e.IsMultiInstance,
|
|
e.SupportMultiInstanceRoomChat,
|
|
e.DefaultBroadcastPermissions,
|
|
e.CanRequestBroadcastPermissions,
|
|
e.BroadcastingRoomInstanceId,
|
|
e.RecurrenceSchedule
|
|
})),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpPut("playerevents/v2/{EventId}/name")]
|
|
public ContentResult SetEventName(ulong EventId, [FromForm] string name)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
FullPlayerEvent playerEvent = EventDB.GetFullEventById(EventId);
|
|
|
|
if (playerEvent == null)
|
|
{
|
|
Utils.ErrorEvent(EventResults.DoesNotExist);
|
|
}
|
|
|
|
if (playerEvent.CreatorPlayerId != account.Id)
|
|
{
|
|
Utils.ErrorEvent(EventResults.DoesNotOwnEvent);
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(name) || name.Length > 64)
|
|
{
|
|
Utils.ErrorEvent(EventResults.InappropriateName);
|
|
}
|
|
|
|
if (Sanitize.ContainsSwears(name))
|
|
{
|
|
Utils.ErrorEvent(EventResults.InappropriateName);
|
|
}
|
|
|
|
FullPlayerEvent UpdatedEvent = EventDB.SetEventName(EventId, name);
|
|
return new ContentResult()
|
|
{
|
|
Content = JsonConvert.SerializeObject(new
|
|
{
|
|
Result = EventResults.Success,
|
|
TagModifyResult = (string?)null,
|
|
PlayerEvent = new
|
|
{
|
|
Tags = UpdatedEvent.Tags,
|
|
PlayerEventId = UpdatedEvent.PlayerEventId,
|
|
CreatorPlayerId = UpdatedEvent.CreatorPlayerId,
|
|
ImageName = UpdatedEvent.ImageName,
|
|
RoomId = UpdatedEvent.RoomId,
|
|
SubRoomId = UpdatedEvent.SubRoomId,
|
|
ClubId = UpdatedEvent.ClubId,
|
|
Name = UpdatedEvent.Name,
|
|
Description = UpdatedEvent.Description,
|
|
StartTime = UpdatedEvent.StartTime,
|
|
EndTime = UpdatedEvent.EndTime,
|
|
AttendeeCount = UpdatedEvent.AttendeeCount,
|
|
State = UpdatedEvent.State,
|
|
ImageAccessibility = UpdatedEvent.Accessibility,
|
|
IsMultiInstance = UpdatedEvent.IsMultiInstance,
|
|
SupportMultiInstanceRoomChat = UpdatedEvent.SupportMultiInstanceRoomChat,
|
|
DefaultBroadcastPermissions = UpdatedEvent.DefaultBroadcastPermissions,
|
|
CanRequestBroadcastPermissions = UpdatedEvent.CanRequestBroadcastPermissions,
|
|
RecurrenceSchedule = UpdatedEvent.RecurrenceSchedule
|
|
}
|
|
}),
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
}
|
|
|
|
[HttpPost("/api/playerwarnings")]
|
|
public IActionResult CreatePlayerWarning([FromForm] ulong WarnedPlayerId, [FromForm] Moderation_Detail.ReportCategory ReportCategory, [FromForm] string DisplayReason, [FromForm] string? ModeratorNote = "") // WarnedPlayerId=3&ReportCategory=103&DisplayReason=Intentional%20team%20killing&ModeratorNote=
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
if (!PlayerDB.CheckDevFlag(account.Id))
|
|
{
|
|
return Forbid();
|
|
}
|
|
|
|
PlayerDB.Set_moderation_block(
|
|
playerid: account.Id,
|
|
category: ReportCategory,
|
|
duration: 0,
|
|
-1,
|
|
isHostKick: false,
|
|
message: DisplayReason,
|
|
playerIdReporter: WarnedPlayerId,
|
|
isBan: false,
|
|
bannedByPlayerId: account.Id
|
|
);
|
|
|
|
return Ok(new
|
|
{
|
|
success = true,
|
|
error = "",
|
|
value = (string?)null
|
|
});
|
|
}
|
|
|
|
[HttpGet("/api/banappeal/generateCode")]
|
|
public IActionResult GenerateBanAppealCode()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok(new
|
|
{
|
|
success = false,
|
|
error = "",
|
|
value = "DM @e12354 to appeal!"
|
|
});
|
|
}
|
|
|
|
[HttpGet("/outfits/me")]
|
|
public IActionResult GetMyOutfits()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
var player = PlayerDB.GetFullAccount(account.Id);
|
|
|
|
if (string.IsNullOrEmpty(player.player_Extra.avatar))
|
|
{
|
|
return Ok(new
|
|
{
|
|
LegacyData = new
|
|
{
|
|
SelectionsV1 = (string?)null,
|
|
SelectionsV2 = (string?)null,
|
|
FaceFeatures = (string?)null,
|
|
SkinColor = (string?)null,
|
|
HairColor = (string?)null
|
|
},
|
|
Selections = Array.Empty<object>(),
|
|
DataVersion = 9,
|
|
CustomizationSettings = (string?)null,
|
|
ThumbnailFileName = (string?)null,
|
|
Name = (string?)null,
|
|
Accessibility = 0,
|
|
Slot = 0
|
|
});
|
|
}
|
|
|
|
|
|
return Ok(player.player_Extra.avatar);
|
|
}
|
|
|
|
[HttpPut("/outfits/me")]
|
|
public async Task<IActionResult> SetMyOutfit()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
string jsonData = "";
|
|
try
|
|
{
|
|
using var reader = new StreamReader(HttpContext.Request.Body);
|
|
jsonData = await reader.ReadToEndAsync();
|
|
}
|
|
catch
|
|
{
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 400
|
|
};
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(jsonData))
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 400
|
|
};
|
|
|
|
try
|
|
{
|
|
Newtonsoft.Json.Linq.JToken.Parse(jsonData);
|
|
}
|
|
catch
|
|
{
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 400
|
|
};
|
|
}
|
|
|
|
|
|
var player = PlayerDB.GetFullAccount(account.Id);
|
|
if (player == null)
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 401
|
|
};
|
|
|
|
try
|
|
{
|
|
PlayerDB.set_player_avatar(jsonData, player.playerid);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"[Avatar Set Error] {ex}");
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 400
|
|
};
|
|
}
|
|
|
|
return new ContentResult()
|
|
{
|
|
Content = "",
|
|
ContentType = "application/json",
|
|
StatusCode = 200
|
|
};
|
|
|
|
return Ok(player.player_Extra.avatar);
|
|
}
|
|
|
|
[HttpGet("/outfits/me/saved")]
|
|
public IActionResult GetMySavedOutfits()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok(ConfigRewild.Bracket);
|
|
}
|
|
|
|
|
|
[HttpGet("/sampling")]
|
|
public IActionResult Sampling()
|
|
{
|
|
// Validate the user token
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
var samplingData = new List<object>
|
|
{
|
|
new { eventType = "SimilarEntitiesContext", shouldBeSampled = false },
|
|
new { eventType = "OnlineRankingContext", shouldBeSampled = false },
|
|
new { eventType = "ugc_makerpen_modify_object", shouldBeSampled = false },
|
|
new { eventType = "heartbeat", shouldBeSampled = false },
|
|
new { eventType = "edible_bite", shouldBeSampled = false },
|
|
new { eventType = "impression", shouldBeSampled = false },
|
|
new { eventType = "downloadable_cache_loaded", shouldBeSampled = false },
|
|
new { eventType = "ugc_makerpen_selectionChanged", shouldBeSampled = false },
|
|
new { eventType = "hand_gesture_use", shouldBeSampled = false },
|
|
new { eventType = "ugc_makerpen_open_menu", shouldBeSampled = false },
|
|
new { eventType = "load_outfit_failed", shouldBeSampled = false },
|
|
new { eventType = "subroom_stats", shouldBeSampled = false },
|
|
new { eventType = "button_press", shouldBeSampled = false },
|
|
new { eventType = "click", shouldBeSampled = false },
|
|
new { eventType = "emote_use", shouldBeSampled = false },
|
|
new { eventType = "watch_stats", shouldBeSampled = false },
|
|
new { eventType = "edible_consume", shouldBeSampled = false },
|
|
new { eventType = "ugc_makerpen_menu_item_selected", shouldBeSampled = false },
|
|
new { eventType = "drinkable_drink", shouldBeSampled = false },
|
|
new { eventType = "sessionMetadata", shouldBeSampled = false },
|
|
new { eventType = "stacked_UI_flow_change", shouldBeSampled = false },
|
|
new { eventType = "food_spawned", shouldBeSampled = false },
|
|
new { eventType = "Announcement_Shown", shouldBeSampled = false },
|
|
new { eventType = "ugc_makerpen_connect", shouldBeSampled = false },
|
|
new { eventType = "mtm_round_stats", shouldBeSampled = false },
|
|
new { eventType = "RRUI_route_change", shouldBeSampled = false },
|
|
new { eventType = "drinkable_consume", shouldBeSampled = false },
|
|
new { eventType = "makerpen_session_detailed", shouldBeSampled = false },
|
|
new { eventType = "store_search", shouldBeSampled = false },
|
|
new { eventType = "ugc_makerpen_create_object", shouldBeSampled = false },
|
|
new { eventType = "ugc_makerpen_changed_setting", shouldBeSampled = false },
|
|
new { eventType = "ugc_room_save_stats_detailed", shouldBeSampled = false },
|
|
new { eventType = "downloadable_item_loaded", shouldBeSampled = false },
|
|
new { eventType = "ugc_makerpen_configure_object", shouldBeSampled = false },
|
|
new { eventType = "ugc_makerpen_search", shouldBeSampled = false },
|
|
new { eventType = "ugc_makerpen_acm_movement_check", shouldBeSampled = false },
|
|
new { eventType = "eligible_for_matchmaking_toast_event", shouldBeSampled = false },
|
|
new { eventType = "ineligible_for_matchmaking_toast_event", shouldBeSampled = false },
|
|
new { eventType = "external_room_progression_shown", shouldBeSampled = false },
|
|
new { eventType = "time_to_content_load", shouldBeSampled = false },
|
|
new { eventType = "time_to_first_card_loaded", shouldBeSampled = false },
|
|
new { eventType = "avatar_outfit_changed", shouldBeSampled = false },
|
|
new { eventType = "DataAPIQuery", shouldBeSampled = false },
|
|
new { eventType = "RoomElasticsearchQuery", shouldBeSampled = false },
|
|
new { eventType = "ugc_makerpen_favorite_object", shouldBeSampled = false },
|
|
new { eventType = "mlm_quest_step_start", shouldBeSampled = false },
|
|
new { eventType = "mlm_acquire_egg", shouldBeSampled = false },
|
|
new { eventType = "mlm_monster_added", shouldBeSampled = false },
|
|
new { eventType = "mlm_monster_need_met", shouldBeSampled = false },
|
|
new { eventType = "mlm_monster_lvl_up", shouldBeSampled = false },
|
|
new { eventType = "mlm_travel_companion_change", shouldBeSampled = false },
|
|
new { eventType = "mlm_monster_rename", shouldBeSampled = false },
|
|
new { eventType = "mlm_left_evergrown", shouldBeSampled = false },
|
|
new { eventType = "mlm_crafting_complete", shouldBeSampled = false },
|
|
new { eventType = "mlm_sanctuary_lvl_up", shouldBeSampled = false },
|
|
new { eventType = "mlm_monster_light_lvl_up", shouldBeSampled = false },
|
|
new { eventType = "mlm_daily_check_in", shouldBeSampled = false },
|
|
new { eventType = "mlm_add_guaranteed_item", shouldBeSampled = false },
|
|
new { eventType = "RoomAutocompleteElasticsearchQuery", shouldBeSampled = false },
|
|
new { eventType = "mlm_player_capacity_reached", shouldBeSampled = false },
|
|
new { eventType = "mlm_tag_failure", shouldBeSampled = false },
|
|
new { eventType = "mlm_npc_nearby", shouldBeSampled = false },
|
|
new { eventType = "mlm_conversation_start", shouldBeSampled = false },
|
|
new { eventType = "autocomplete_impression", shouldBeSampled = false },
|
|
new { eventType = "rtb_player_stats", shouldBeSampled = false },
|
|
new { eventType = "rtb_challenge_stats", shouldBeSampled = false },
|
|
new { eventType = "rtb_public_event_stats", shouldBeSampled = false },
|
|
new { eventType = "ugc_makerpen_container_rename", shouldBeSampled = false },
|
|
new { eventType = "rtb_feedback", shouldBeSampled = false },
|
|
new { eventType = "contextual_features", shouldBeSampled = false },
|
|
new { eventType = "RoomSearchRequest", shouldBeSampled = false },
|
|
new { eventType = "StatsigParameterDesync", shouldBeSampled = false },
|
|
new { eventType = "reccon_candy_stats", shouldBeSampled = false },
|
|
new { eventType = "reccon_roomstats", shouldBeSampled = false },
|
|
new { eventType = "reccon_trivia_stats", shouldBeSampled = false },
|
|
new { eventType = "reccon_fashion_stats", shouldBeSampled = false },
|
|
new { eventType = "mlm_missing_replicators", shouldBeSampled = false },
|
|
new { eventType = "engagementTitlescreenJumpRightInStatsigTimeout", shouldBeSampled = false },
|
|
new { eventType = "engagementTitlescreenJumpRightInOnlineFriendClick", shouldBeSampled = false },
|
|
new { eventType = "engagementTitlescreenJumpRightInOnlineFriendsPagination", shouldBeSampled = false },
|
|
new { eventType = "engagementTitlescreenJumpRightInOnlineFriendsJoinFriendClick", shouldBeSampled = false },
|
|
new { eventType = "engagementTitlescreenJumpRightInOnlineFriendsViewAll", shouldBeSampled = false },
|
|
new { eventType = "smart_circuit_makerpen_drag_released", shouldBeSampled = false },
|
|
new { eventType = "ugc_room_event", shouldBeSampled = false },
|
|
new { eventType = "CustomAvatarItemSearchRequest", shouldBeSampled = false },
|
|
new { eventType = "perf_metrics", shouldBeSampled = false },
|
|
new { eventType = "whalegame_boatmaterialreset", shouldBeSampled = false },
|
|
new { eventType = "engagementTitlescreenJumpRightInOnlineFriendsViewMore", shouldBeSampled = false },
|
|
new { eventType = "ValentinesDay2025", shouldBeSampled = false },
|
|
new { eventType = "orientation_purchase_flow_steps", shouldBeSampled = false },
|
|
new { eventType = "ai_error", shouldBeSampled = false },
|
|
new { eventType = "ai_mistake", shouldBeSampled = false },
|
|
new { eventType = "ai_missing_functionality", shouldBeSampled = false },
|
|
new { eventType = "ai_response_error", shouldBeSampled = false },
|
|
new { eventType = "ai_text_bug", shouldBeSampled = false },
|
|
new { eventType = "socialcreation1_robotparts", shouldBeSampled = false },
|
|
new { eventType = "socialcreation1_robotactivated", shouldBeSampled = false },
|
|
new { eventType = "ai_conversation", shouldBeSampled = false },
|
|
new { eventType = "ai_expense", shouldBeSampled = false },
|
|
new { eventType = "crossed_bridge", shouldBeSampled = false },
|
|
new { eventType = "completed_task_normally", shouldBeSampled = false },
|
|
new { eventType = "bridge_dropped_time", shouldBeSampled = false },
|
|
new { eventType = "Player_pressed_button", shouldBeSampled = false },
|
|
new { eventType = "bridge_dropped_due_to_time", shouldBeSampled = false },
|
|
new { eventType = "Players_at_finishline", shouldBeSampled = false },
|
|
new { eventType = "Players_at_timeout", shouldBeSampled = false },
|
|
new { eventType = "Social_creation_2_events", shouldBeSampled = false },
|
|
new { eventType = "socail_creation_2_completed_task_normally", shouldBeSampled = false },
|
|
new { eventType = "Socialcreation2_Players_at_finishline", shouldBeSampled = false },
|
|
new { eventType = "Socialcreation2_completed_task_normally", shouldBeSampled = false },
|
|
new { eventType = "Socialcreation2_Placed_object", shouldBeSampled = false },
|
|
new { eventType = "Socialcreation2_Players_at_timeout", shouldBeSampled = false },
|
|
new { eventType = "Socialcreation2_crossed_bridge", shouldBeSampled = false },
|
|
new { eventType = "Socialcreation2_bridge_dropped_due_to_time", shouldBeSampled = false },
|
|
new { eventType = "Socialcreation2_Player_pressed_button", shouldBeSampled = false },
|
|
new { eventType = "widget_watch_state_change", shouldBeSampled = false },
|
|
new { eventType = "ListFilteredEntities", shouldBeSampled = false },
|
|
new { eventType = "roomie_ai_session", shouldBeSampled = false },
|
|
new { eventType = "roomie_ai_response", shouldBeSampled = false },
|
|
new { eventType = "roomie_ai_conversation_history", shouldBeSampled = false },
|
|
new { eventType = "ai_session", shouldBeSampled = false },
|
|
new { eventType = "ai_conversation_history", shouldBeSampled = false },
|
|
new { eventType = "ai_response", shouldBeSampled = false },
|
|
new { eventType = "roomie_ai_expense", shouldBeSampled = false },
|
|
new { eventType = "roomie_ai_error", shouldBeSampled = false },
|
|
new { eventType = "roomie_ai_response_error", shouldBeSampled = false },
|
|
new { eventType = "avatar_item_consumable", shouldBeSampled = false },
|
|
new { eventType = "ham_reached", shouldBeSampled = false },
|
|
new { eventType = "prompt_submitted", shouldBeSampled = false },
|
|
new { eventType = "llm_response_received", shouldBeSampled = false },
|
|
new { eventType = "AccountsToGenericCandidatesContext", shouldBeSampled = false },
|
|
new { eventType = "RoomsToGenericSimilarEntitiesContext", shouldBeSampled = false },
|
|
new { eventType = "Rooms_searchContext", shouldBeSampled = false },
|
|
new { eventType = "QueryRecommendation", shouldBeSampled = false },
|
|
new { eventType = "Generic_searchContext", shouldBeSampled = false },
|
|
new { eventType = "avatar_effect_grenade", shouldBeSampled = false },
|
|
new { eventType = "game_ai_session", shouldBeSampled = false },
|
|
new { eventType = "game_ai_conversation_history", shouldBeSampled = false },
|
|
new { eventType = "game_ai_response", shouldBeSampled = false },
|
|
new { eventType = "game_ai_response_error", shouldBeSampled = false },
|
|
new { eventType = "roomie_avatar_equip", shouldBeSampled = false },
|
|
new { eventType = "game_ai_error", shouldBeSampled = false },
|
|
new { eventType = "roomie_ai_stuck_in_text", shouldBeSampled = false },
|
|
new { eventType = "roomie_ai_restart", shouldBeSampled = false },
|
|
new { eventType = "gift_button_clicked", shouldBeSampled = false },
|
|
new { eventType = "gift_button_consume_clicked", shouldBeSampled = false },
|
|
new { eventType = "rma_booth_entered", shouldBeSampled = false },
|
|
new { eventType = "rma_rate_button_pushed ", shouldBeSampled = false },
|
|
new { eventType = "rma_rating_completion", shouldBeSampled = false },
|
|
new { eventType = "sj_rate_button_pushed", shouldBeSampled = false },
|
|
new { eventType = "sj_rating_completion", shouldBeSampled = false },
|
|
new { eventType = "avatar_glitch_effect_grenade", shouldBeSampled = false },
|
|
new { eventType = "game_ai_expense", shouldBeSampled = false },
|
|
new { eventType = "roomie_interaction", shouldBeSampled = false },
|
|
new { eventType = "roomie_ai_energy_updated", shouldBeSampled = false },
|
|
new { eventType = "Ticket consumed", shouldBeSampled = false }
|
|
};
|
|
|
|
return Ok(samplingData);
|
|
}
|
|
|
|
[HttpGet("/api/consumables/v1/all")]
|
|
public async Task<IActionResult> GetUnlockableConsumables()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
string path = Path.Combine(Environment.CurrentDirectory, "Data", "APIS", "items", "AllUnlockableConsumables.json");
|
|
string content = await System.IO.File.ReadAllTextAsync(path);
|
|
return Ok(content);
|
|
}
|
|
|
|
[HttpPost("/statsigUserProperties")]
|
|
public IActionResult GetStatsigUserProperties()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok(new
|
|
{
|
|
success = ConfigRewild.StatsigEnabled
|
|
});
|
|
}
|
|
|
|
[HttpGet("/api/referee/files")]
|
|
public IActionResult GetRefereeFiles()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok(ConfigRewild.Bracket);
|
|
}
|
|
|
|
[HttpPost("/api/PlayerReporting/v1/referee")] // we hate referee so false it to hell
|
|
public IActionResult RefereeCheck()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok("false");
|
|
}
|
|
|
|
[HttpGet("/api/ugcPurchasables/v1/items/room/{roomId}")]
|
|
public IActionResult RefereeCheck(ulong roomId)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok(ConfigRewild.Bracket);
|
|
}
|
|
|
|
[HttpPost("/lists/contextualfeatures")]
|
|
public IActionResult ContextualFeatures()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok(new
|
|
{
|
|
success = true,
|
|
error_id = (string?)null,
|
|
error = (string?)null
|
|
});
|
|
}
|
|
|
|
[HttpGet("/api/progressionEvents/active")]
|
|
public IActionResult GetActiveProgressionEvents()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return NoContent();
|
|
}
|
|
|
|
[HttpGet("/api/makerai/checkfreetrialeligibility")]
|
|
public IActionResult CheckFreeTrialEligibility()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Content("false", "application/json");
|
|
}
|
|
|
|
[HttpGet("/api/inventions/v2/search")]
|
|
public IActionResult SearchInventions([FromQuery] int skip, [FromQuery] int take)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok(ConfigRewild.Bracket);
|
|
}
|
|
|
|
[HttpGet("/api/relationships/mutualfriends")]
|
|
public IActionResult CheckFreeTrialEligibility([FromQuery(Name = "id"), Required] int PlayerId)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok(ConfigRewild.Bracket);
|
|
}
|
|
|
|
|
|
[HttpGet("/api/CampusCard/v1/SignUpBonus")]
|
|
public IActionResult GetRRPlusSignUpBonus()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok(new
|
|
{
|
|
RRPlusSignUpBonusId = 3,
|
|
MinFreeItemsPrice = 6000,
|
|
MaxFreeItemsPrice = 10000
|
|
});
|
|
}
|
|
|
|
[HttpGet("/lists/algorithmiclists/{algorithmicList}")]
|
|
public async Task<IActionResult> GetAlgorithmicList(string algorithmicList, [FromQuery] int type)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null) return error;
|
|
|
|
var safeFileName = Path.GetFileName(algorithmicList);
|
|
|
|
string path = Path.Combine(
|
|
Environment.CurrentDirectory,
|
|
"Data", "APIS", "AlgorithmicLists",
|
|
$"{safeFileName}_{type}.json"
|
|
);
|
|
|
|
if (!System.IO.File.Exists(path))
|
|
return Ok(new
|
|
{
|
|
Type = type,
|
|
Entities = Array.Empty<object>()
|
|
});
|
|
|
|
try
|
|
{
|
|
var jsonText = await System.IO.File.ReadAllTextAsync(path);
|
|
var node = JsonNode.Parse(jsonText);
|
|
|
|
return Ok(new
|
|
{
|
|
Type = type,
|
|
Entities = node as JsonArray ?? new JsonArray()
|
|
});
|
|
}
|
|
catch (System.Text.Json.JsonException)
|
|
{
|
|
return Ok(new
|
|
{
|
|
Type = type,
|
|
Entities = Array.Empty<object>()
|
|
});
|
|
}
|
|
}
|
|
|
|
[HttpGet("/lists/curatedlists")]
|
|
public async Task<IActionResult> GetCuratedlists([FromQuery] ulong creatorAccountId, [FromQuery] ulong type, [FromQuery] string name)
|
|
{
|
|
string path = Path.Combine(
|
|
Environment.CurrentDirectory,
|
|
"Data", "APIS", "CuratedLists",
|
|
$"{creatorAccountId}_{type}_{name}.json"
|
|
);
|
|
|
|
if (!System.IO.File.Exists(path))
|
|
return NotFound();
|
|
|
|
return PhysicalFile(path, "application/json");
|
|
}
|
|
|
|
[HttpGet("/api/activities/charades/v1/words/Icebreakers")]
|
|
public IActionResult GetIcebreakers(ulong RoomId)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
string path = Path.Combine(Environment.CurrentDirectory, "Data", "APIS", "Charades", "Icebreakers.json");
|
|
if (!System.IO.File.Exists(path))
|
|
return Ok(ConfigRewild.Bracket);
|
|
|
|
return PhysicalFile(path, "application/json");
|
|
}
|
|
|
|
[HttpGet("/aimoderation/roomie/enabledForPlayer")]
|
|
public IActionResult IsRoomieEnabledForPlayer()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok("true");
|
|
}
|
|
|
|
[HttpPost("/aimoderation/roomie/conversation")]
|
|
public IActionResult SaveRoomieConversation([FromForm] string conversation)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null) return error;
|
|
|
|
if (string.IsNullOrEmpty(conversation))
|
|
return BadRequest();
|
|
|
|
string pattern = @"(?<=\d{2}:\d{2}:\d{2}\s)(USER|AI)(?=\s\(|:)";
|
|
|
|
string processedConversation = Regex.Replace(conversation ?? "", pattern, m =>
|
|
{
|
|
return m.Value == "USER" ? account.Username : "Roomie";
|
|
});
|
|
|
|
_ = Task.Run(() => Webhook.Send(
|
|
account.Id,
|
|
"roomie",
|
|
"Roomie Info",
|
|
$"User: @{account.Username} ({account.Id})\n\nLog: {processedConversation}",
|
|
5898927,
|
|
null
|
|
));
|
|
|
|
return Ok();
|
|
}
|
|
|
|
[HttpGet("/api/players/v1/playerPhotoTaggingSetting")]
|
|
public IActionResult GetPlayerPhotoTaggingSetting()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok(PlayerDB.GetPlayerPhotoTaggingSetting(account.Id));
|
|
}
|
|
|
|
[HttpPut("/api/players/v1/playerPhotoTaggingSetting")]
|
|
public IActionResult SetPlayerPhotoTaggingSetting([FromBody] SetPlayerPhotoTaggingSettingRequest request)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok(PlayerDB.SetPlayerPhotoTaggingSetting(account.Id, request.Setting));
|
|
}
|
|
|
|
[HttpGet("/api/keepsakes/globalconfig")]
|
|
public IActionResult GetKeepsakeGlobalConfig()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok(new
|
|
{
|
|
KeepsakeFeatureEnabled = true,
|
|
KeepsakeRoomLimit = 10,
|
|
SocialXpBoostEnabled = false
|
|
});
|
|
}
|
|
|
|
[HttpGet("/api/quickPlay/v1/getandclear")]
|
|
public IActionResult GetAndClearQuickPlay()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return NoContent();
|
|
}
|
|
|
|
[HttpGet("/api/keepsakes/rooms/{roomId}")]
|
|
public IActionResult GetKeepsakesForRoom(ulong roomId)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return NoContent();
|
|
}
|
|
|
|
[HttpPost("/api/messages/v1/friendOnlineStatus")]
|
|
public IActionResult GetFriendOnlineCount()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok(new
|
|
{
|
|
success = true,
|
|
value = new
|
|
{
|
|
FriendsOnlineCount = int.MaxValue // hehe
|
|
}
|
|
});
|
|
}
|
|
|
|
[HttpGet("/api/purchasableXpBoosts/activations")]
|
|
public IActionResult GetPurchasableXpBoosts()
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok(new
|
|
{
|
|
Results = Array.Empty<object>(),
|
|
TotalResults = 0
|
|
});
|
|
}
|
|
|
|
[HttpGet("/api/inventions/v2/batch")]
|
|
public IActionResult GetListOfInventions([FromQuery] List<ulong> id)
|
|
{
|
|
var (account, error) = AuthHelper.ValidateToken(HttpContext);
|
|
if (error != null)
|
|
return error;
|
|
|
|
return Ok(ConfigRewild.Bracket);
|
|
}
|
|
|
|
[HttpPost("/api/consumables/v1/updateActive")]
|
|
public IActionResult UpdateActiveConsumable()
|
|
{
|
|
return NoContent();
|
|
}
|
|
|
|
[HttpGet("/api/inventions/v1/fromcreators")]
|
|
public IActionResult UpdateActiveConsumable([FromQuery] ulong id, [FromQuery] int skip, [FromQuery] int take)
|
|
{
|
|
return Ok(ConfigRewild.Bracket);
|
|
}
|
|
|
|
[HttpGet("/sections/bulk")]
|
|
public IActionResult GetSectionsBulk([FromQuery] List<string> id)
|
|
{
|
|
var filePath = Path.Combine(Environment.CurrentDirectory, "Data", "APIS", "WatchPages", "bulk.json");
|
|
|
|
if (!System.IO.File.Exists(filePath))
|
|
return NotFound();
|
|
|
|
var jsonString = System.IO.File.ReadAllText(filePath);
|
|
var allSections = System.Text.Json.JsonSerializer.Deserialize<List<Dictionary<string, object>>>(jsonString);
|
|
|
|
if (id == null || !id.Any())
|
|
return Ok(new List<object>());
|
|
|
|
var filtered = allSections.Where(s => s.ContainsKey("id") && id.Contains(s["id"]?.ToString())).ToList();
|
|
|
|
return Ok(filtered);
|
|
}
|
|
}
|
|
}
|