using Foxchat.Chat.Database; using Foxchat.Chat.Database.Models; using Foxchat.Chat.Middleware; using Foxchat.Chat.Services; using Foxchat.Core.Models; using Foxchat.Core.Models.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using ApiError = Foxchat.Core.ApiError; namespace Foxchat.Chat.Controllers.Api; [ApiController] [Route("/_fox/chat/guilds")] public class GuildsController(ILogger logger, ChatContext db, UserResolverService userResolverService) : ControllerBase { [HttpPost] public async Task CreateGuild([FromBody] GuildsApi.CreateGuildRequest req) { var (instance, _, userId) = HttpContext.GetSignatureWithUser(); var user = await userResolverService.ResolveUserAsync(instance, userId); var guild = new Guild { Name = req.Name, Owner = user, }; db.Add(guild); guild.Users.Add(user); var defaultChannel = new Channel { Guild = guild, Name = "general" }; db.Add(defaultChannel); await db.SaveChangesAsync(); return Ok(new Guilds.Guild( guild.Id.ToString(), guild.Name, [user.Id.ToString()], [new Channels.PartialChannel(defaultChannel.Id.ToString(), defaultChannel.Name)]) ); } [HttpGet("{id}")] public async Task GetGuild(Ulid id) { var (instance, _, userId) = HttpContext.GetSignatureWithUser(); var guild = await db.Guilds .Include(g => g.Channels) .FirstOrDefaultAsync(g => g.Id == id && g.Users.Any(u => u.RemoteUserId == userId && u.InstanceId == instance.Id)); if (guild == null) throw new ApiError.NotFound("Guild not found"); return Ok(new Guilds.Guild( guild.Id.ToString(), guild.Name, [guild.OwnerId.ToString()], guild.Channels.Select(c => new Channels.PartialChannel(c.Id.ToString(), c.Name)) )); } [HttpGet("@me")] public async Task GetUserGuilds() { var (instance, _, userId) = HttpContext.GetSignatureWithUser(); var guilds = await db.Guilds .Include(g => g.Channels) .Where(g => g.Users.Any(u => u.RemoteUserId == userId && u.InstanceId == instance.Id)) .ToListAsync(); var guildResponses = guilds.Select(g => new Guilds.Guild( g.Id.ToString(), g.Name, [g.OwnerId.ToString()], g.Channels.Select(c => new Channels.PartialChannel(c.Id.ToString(), c.Name)) )); return Ok(guildResponses); } }