using CSharpDiscordWebhook.Objects; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using RadicadeServer.DB; using RadicadeServer.Extensions; using RadicadeServer.RecNet.Enums.Inventions; using RadicadeServer.RecNet; using RadicadeServer.RecNet.Inventions; using RadicadeServer.RecNet.Responses; using RadicadeServer.RecNet.Rooms; using RadicadeServer.Utils; namespace RadicadeServer.API.Inventions.V1 { [Route("api/inventions/v1")] public class InventionsV1(RecDBContext db) : Controller { [HttpGet("room")] public List GetInventionsInRoom() { return []; } [HttpGet("fromcreators")] public async Task GetInventionsFromCreators( [FromQuery] long[]? id, [FromQuery] int skip = 0, [FromQuery] int take = 100) { if (id == null || id.Length == 0) return BadRequest(new { error = "At least one creator id is required." }); var creatorIds = id.Where(creatorId => creatorId > 0).Distinct().ToArray(); var offset = Math.Max(0, skip); var limit = Math.Clamp(take, 1, 100); var inventions = await db.Inventions .Where(invention => creatorIds.Contains(invention.CreatorPlayerId)) .OrderByDescending(invention => invention.CreatedAt) .ThenByDescending(invention => invention.InventionId) .Skip(offset) .Take(limit) .ToListAsync(); return Ok(inventions.Select(invention => invention.ToInvention()).ToList()); } [HttpGet("unpublish"), Authorize] public async Task UnpublishInvention([FromQuery] long inventionId) { var userId = User.GetUserId(); var invention = await db.Inventions.FirstOrDefaultAsync(x => x.CreatorPlayerId == userId && x.InventionId == inventionId); if (invention == null) return null; invention.IsPublished = false; await db.SaveChangesAsync(); return await invention.ToFullInvention(db); } [HttpGet("personaldetails/{inventionId}")] public async Task GetPersonalDetailsForInvention(long inventionId) { var userId = User.GetUserId(); var details = await db.InventionPersonalDetails.FirstOrDefaultAsync(x => x.InventionId == inventionId && x.PlayerId == userId); if (details == null) return new InventionPersonalDetails { IsCheering = false }; return details; } [HttpGet("tagfilters")] public RoomFilters? GetTagFilters() { return new RoomFilters { PinnedFilters = ["dormskin", "weapon", "certified", "plushie", "scifi", "fantasy", "costume", "art", "character", "environment", "gadget"], PopularFilters = ["dormskin", "weapon", "certified", "plushie", "scifi", "fantasy", "costume", "art", "character", "environment", "gadget"], TrendingFilters = [] }; } [HttpGet("dormskinsfromids")] public async Task> GetDormSkinsFromIds([FromQuery] string[]? ids) { var parsed = (ids ?? Array.Empty()) .SelectMany(raw => (raw ?? "").Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)) .Select(part => long.TryParse(part, out var value) ? value : -1) .Where(value => value > 0) .Distinct() .ToList(); if (parsed.Count == 0) return []; var known = await db.Inventions.AsNoTracking() .Where(x => parsed.Contains(x.InventionId) && !x.HideFromPlayer) .Select(x => x.InventionId) .ToListAsync(); var knownSet = known.ToHashSet(); return parsed.Where(knownSet.Contains).ToList(); } [HttpGet("featureddormskins")] public async Task> GetFeaturedDormSkins() { var featured = await db.Inventions.AsNoTracking() .Where(x => !x.HideFromPlayer && x.IsPublished) .OrderByDescending(x => x.ModifiedAt) .Take(24) .ToListAsync(); return featured.Select(x => x.ToInvention()).ToList(); } [HttpGet("version"), Authorize] public async Task GetInventionVersion([FromQuery] long inventionId, [FromQuery] int version) { var userId = User.GetUserId(); var invention = await db.Inventions.FirstOrDefaultAsync(x => x.InventionId == inventionId); if (invention == null) return null; return await db.GetInventionVersion(version, inventionId); } [HttpGet("update"), Authorize] public async Task UpdateInvention([FromQuery] long inventionId, [FromQuery] string? name, [FromQuery] string? imgName, [FromQuery] string? description, [FromQuery] string? permission) { var userId = User.GetUserId(); var invention = await db.Inventions.FirstOrDefaultAsync(x => x.CreatorPlayerId == userId && x.InventionId == inventionId); if (invention == null) return null; if (name != null) invention.Name = name; if (description != null) invention.Description = description; if (imgName != null) invention.ImageName = imgName; if (permission != null) { if (Enum.TryParse(permission, out var parsedRole)) invention.GeneralPermission = parsedRole; } await db.SaveChangesAsync(); return await invention.ToFullInvention(db); } [HttpGet("toptoday")] public async Task> GetTopInventions() { var topInventions = await db.Inventions.Where(x => !x.HideFromPlayer && x.IsPublished) .OrderByDescending(x => x.ModifiedAt).ToListAsync(); var converted = new List(); foreach (var i in topInventions) { var invention = i.ToInvention(); converted.Add(invention); } return converted; } [HttpGet("featured")] public async Task> GetFeaturedInventions() { var featured = await db.Inventions .Where(x => !x.HideFromPlayer && x.IsPublished) .OrderByDescending(x => x.ModifiedAt) .Take(24) .ToListAsync(); return featured.Select(x => x.ToInvention()).ToList(); } [HttpPost("settags"), Authorize] public async Task UpdateInventionTags([FromBody] ModifyInventionTagsRequest req) { var userId = User.GetUserId(); var invention = await db.Inventions.FirstOrDefaultAsync(x => x.CreatorPlayerId == userId && x.InventionId == req.InventionId); if (invention == null) return new InventionTagResponse { Result = RecNet.Enums.InventionTagResult.InventionDoesNotExist }; if (req.CustomTags.Count >= 10) new InventionTagResponse { Result = RecNet.Enums.InventionTagResult.TooManyTags }; var tags = new List(); foreach (string tag in req.AutoTags) { tags.Add(new ItemTag { Tag = tag, Type = RecNet.Enums.TagType.Auto }); } foreach (string tag in req.CustomTags) { tags.Add(new ItemTag { Tag = tag, Type = RecNet.Enums.TagType.General }); } invention.Tags = StringTools.CreateTagString(tags); await db.SaveChangesAsync(); return new InventionTagResponse { Tags = StringTools.TagsToStrings(tags), Result = RecNet.Enums.InventionTagResult.Success }; } [HttpGet("details"), Authorize] public async Task GetInventionDetails([FromQuery] long inventionId) { var userId = User.GetUserId(); var invention = await db.Inventions.FirstOrDefaultAsync(x => x.InventionId == inventionId); if (invention == null) return null; if (invention.Tags == null) return new TagResponse { Tags = [] }; return new TagResponse { Tags = StringTools.ReadTags(invention.Tags) }; } [HttpGet("batch"), Authorize] public async Task?> GetBatchInventions([FromBody] List ids) { var userId = User.GetUserId(); var inventions = new List(); foreach (var id in ids) { var invention = await db.Inventions.FirstOrDefaultAsync(x => x.InventionId == id); if (invention == null) continue; inventions.Add(invention.ToInvention()); } return inventions; } [HttpGet("fulllineageowner"), Authorize] public async Task OwnsInventionLineage([FromQuery] List id) { var userId = User.GetUserId(); var unlocks = await db.Unlocks.AsNoTracking().FirstOrDefaultAsync(x => x.AccountId == userId); var bought = new HashSet(); if (unlocks != null && !string.IsNullOrWhiteSpace(unlocks.Inventions) && unlocks.Inventions != "null") { try { bought = (unlocks.Inventions.FromJson>() ?? new List()).ToHashSet(); } catch { } } bool owns = false; foreach (var i in id) { if (bought.Contains(i)) { owns = true; break; } var invention = await db.Inventions.FirstOrDefaultAsync(x => x.InventionId == i); if (invention != null) owns = (invention.CreatorPlayerId == userId || invention.GeneralPermission == InventionRole.Publish); if (owns) break; } return owns; } [HttpGet(""), Authorize] public async Task GetInventionById([FromQuery] long id) { var userId = User.GetUserId(); var invention = await db.Inventions.FirstOrDefaultAsync(x => x.InventionId == id); if (invention == null) return null; return invention; } } }