yikes,
This commit is contained in:
@@ -0,0 +1,904 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json;
|
||||
using Vanadium.Auth;
|
||||
using Vanadium.Classes.DBs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using static Vanadium.Classes.DBs.DBClasses.ClubsDBClasses;
|
||||
|
||||
namespace Vanadium.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
public class ClubsController : ControllerBase
|
||||
{
|
||||
private static int ParseVisibility(string? raw)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(raw)) return -1;
|
||||
return raw.ToLowerInvariant() switch
|
||||
{
|
||||
"public" => (int)ClubVisibility.Public,
|
||||
"unlisted" => (int)ClubVisibility.Unlisted,
|
||||
"private" => (int)ClubVisibility.Private,
|
||||
"0" => (int)ClubVisibility.Private,
|
||||
"1" => (int)ClubVisibility.Public,
|
||||
"2" => (int)ClubVisibility.Unlisted,
|
||||
_ => -1
|
||||
};
|
||||
}
|
||||
|
||||
private static int ParseJoinability(string? raw)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(raw)) return -1;
|
||||
return raw.ToLowerInvariant() switch
|
||||
{
|
||||
"open" => (int)ClubJoinability.Open,
|
||||
"approvalrequired" => (int)ClubJoinability.ApprovalRequired,
|
||||
"closed" => (int)ClubJoinability.Closed,
|
||||
"0" => (int)ClubJoinability.Open,
|
||||
"1" => (int)ClubJoinability.ApprovalRequired,
|
||||
"2" => (int)ClubJoinability.Closed,
|
||||
_ => -1
|
||||
};
|
||||
}
|
||||
|
||||
[HttpGet("/club/{clubId}/members/{userId}")]
|
||||
public IActionResult GetClubMember(long clubId, long userId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
var member = ClubsDB.GetClubMembers(clubId).FirstOrDefault(m => m.AccountId == userId);
|
||||
if (member == null) return Ok(new {});
|
||||
return Ok(member);
|
||||
}
|
||||
|
||||
[HttpGet("/club/search")]
|
||||
public IActionResult SearchClubs(
|
||||
[FromQuery] string? query,
|
||||
[FromQuery] string? category,
|
||||
[FromQuery] int sort = 0,
|
||||
[FromQuery] int count = 30,
|
||||
[FromQuery] int skip = 0)
|
||||
{
|
||||
count = Math.Clamp(count, 1, 100);
|
||||
var result = ClubsDB.Search(query, category, sort, count, skip);
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(result),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost("/club/create")]
|
||||
public IActionResult CreateClub(
|
||||
[FromForm] string name,
|
||||
[FromForm] string? description,
|
||||
[FromForm] string? category)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var club = ClubsDB.CreateClub(
|
||||
id.Value,
|
||||
name.Trim(),
|
||||
description?.Trim() ?? "",
|
||||
(category ?? "Social").Trim());
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new
|
||||
{
|
||||
success = true,
|
||||
error = "",
|
||||
value = ClubsDB.ToDetails(club, id.Value)
|
||||
}),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpGet("/club/categoryTags")]
|
||||
public IActionResult GetClubCategoryTags()
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var tags = new List<string>
|
||||
{
|
||||
"Social",
|
||||
"Creative",
|
||||
"Competitive",
|
||||
"Casual",
|
||||
"Educational",
|
||||
"Entertainment",
|
||||
"Lifestyle"
|
||||
};
|
||||
|
||||
return Ok(tags);
|
||||
}
|
||||
|
||||
[HttpGet("/club/mine/created")]
|
||||
public IActionResult GetMyCreatedClubs()
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var clubs = ClubsDB.GetClubsCreatedBy(id.Value)
|
||||
.Select(ClubsDB.ToSummary)
|
||||
.ToList();
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(clubs),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpGet("/club/mine/member")]
|
||||
public IActionResult GetMyMemberClubs()
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var clubs = ClubsDB.GetClubsJoinedBy(id.Value)
|
||||
.Where(c => c.Visibility != 2)
|
||||
.Select(ClubsDB.ToSummary)
|
||||
.ToList();
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(clubs),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpGet("/club/account/{player}/created")]
|
||||
public IActionResult GetOthersCreatedClubs(long player)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var clubs = ClubsDB.GetClubsCreatedBy(player)
|
||||
.Where(c => c.Visibility != 2)
|
||||
.Select(ClubsDB.ToSummary)
|
||||
.ToList();
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(clubs),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpGet("/club/{clubId}")]
|
||||
[HttpGet("/club/{clubId}/details")]
|
||||
public IActionResult GetClubDetails(long clubId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var club = ClubsDB.GetClub(clubId);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
return Ok(new ClubDetailsDTO
|
||||
{
|
||||
Club = ClubsDB.ToSummary(club),
|
||||
CustomTags = club.CustomTags,
|
||||
AdditionalImages = club.AdditionalImages,
|
||||
CoownerPermissions = club.Permissions.FirstOrDefault(p => p.Type == (int)ClubMemberType.CoOwner),
|
||||
ModeratorPermissions = club.Permissions.FirstOrDefault(p => p.Type == (int)ClubMemberType.Moderator),
|
||||
MemberPermissions = club.Permissions.FirstOrDefault(p => p.Type == (int)ClubMemberType.Member),
|
||||
MyMembershipType = club.Members
|
||||
.FirstOrDefault(m => m.AccountId == id.Value)?.MemberType ?? 0
|
||||
});
|
||||
}
|
||||
|
||||
[HttpGet("/club/{clubId}/members")]
|
||||
public IActionResult GetClubMembers(long clubId, [FromQuery] int? membershipType)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var club = ClubsDB.GetClub(clubId);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
var members = ClubsDB.GetClubMembers(clubId);
|
||||
if (membershipType.HasValue)
|
||||
members = members.Where(m => m.MembershipType == membershipType.Value).ToList();
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { value = members, success = true, error_id = (int?)null, error = (string?)null }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpDelete("/club/{clubId}")]
|
||||
public IActionResult DeleteClub(long clubId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var club = ClubsDB.GetClub(clubId);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
if (club.CreatorAccountId != id.Value)
|
||||
{
|
||||
APIController.SendNonHileWebhook(id.Value, $"Attempted to delete club {clubId} but is not the creator.");
|
||||
return StatusCode(403);
|
||||
}
|
||||
|
||||
ClubsDB.DeleteClub(clubId);
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = (string?)null, value = ClubsDB.ToDetails(club, id.Value) }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPut("/club/{clubId}/modify")]
|
||||
public IActionResult ModifyClub(
|
||||
long clubId,
|
||||
[FromForm] string? name,
|
||||
[FromForm] string? description,
|
||||
[FromForm] string? category)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var existing = ClubsDB.GetClub(clubId);
|
||||
if (existing == null) return NotFound("");
|
||||
|
||||
if (!ClubsDB.CanEditDetails(clubId, id.Value))
|
||||
{
|
||||
APIController.SendNonHileWebhook(id.Value, $"Attempted to modify club {clubId} but does not have permission.");
|
||||
return StatusCode(403);
|
||||
}
|
||||
|
||||
var club = ClubsDB.Modify(
|
||||
clubId,
|
||||
(name ?? existing.Name).Trim(),
|
||||
(description ?? existing.Description ?? "").Trim(),
|
||||
(category ?? existing.Category).Trim(),
|
||||
id.Value);
|
||||
|
||||
if (club == null) return Unauthorized("");
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = (string?)null, value = ClubsDB.ToDetails(club, id.Value) }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPut("/club/{clubId}/modifydetails")]
|
||||
public IActionResult ModifyClubDetails(
|
||||
long clubId,
|
||||
[FromForm] string? visibility,
|
||||
[FromForm] string? joinability,
|
||||
[FromForm] string? allowJuniors,
|
||||
[FromForm] string? customTags)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
if (!ClubsDB.CanEditDetails(clubId, id.Value))
|
||||
{
|
||||
APIController.SendNonHileWebhook(id.Value, $"Attempted to modify club {clubId} but does not have permission. (2)");
|
||||
return StatusCode(403);
|
||||
}
|
||||
|
||||
int? vis = visibility != null ? ParseVisibility(visibility) : (int?)null;
|
||||
int? join = joinability != null ? ParseJoinability(joinability) : (int?)null;
|
||||
if (join == 1) return StatusCode(501);
|
||||
bool? juniors = null;
|
||||
if (allowJuniors != null)
|
||||
juniors = allowJuniors.ToLowerInvariant() is "true" or "1";
|
||||
|
||||
List<string>? tags = null;
|
||||
if (customTags != null)
|
||||
tags = customTags
|
||||
.Split(',', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(t => t.Trim())
|
||||
.Where(t => !string.IsNullOrEmpty(t))
|
||||
.ToList();
|
||||
|
||||
var club = ClubsDB.ModifyDetails(clubId, vis, join, juniors, tags, id.Value);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = "", value = ClubsDB.ToDetails(club, id.Value) }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPut("/club/{clubId}/minlevel")]
|
||||
public IActionResult SetMinLevel(long clubId, [FromForm] int minLevel)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
if (!ClubsDB.CanEditDetails(clubId, id.Value))
|
||||
{
|
||||
APIController.SendNonHileWebhook(id.Value, $"Attempted to set min level for club {clubId} but does not have permission.");
|
||||
return StatusCode(403);
|
||||
}
|
||||
|
||||
var club = ClubsDB.SetMinLevel(clubId, minLevel, id.Value);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = (string?)null, value = ClubsDB.ToDetails(club, id.Value) }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPut("/club/{clubId}/mainimage")]
|
||||
public IActionResult SetMainImage(long clubId, [FromForm] string imageName)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var existing = ClubsDB.GetClub(clubId);
|
||||
if (existing == null) return NotFound("");
|
||||
|
||||
if (!ClubsDB.CanEditDetails(clubId, id.Value))
|
||||
{
|
||||
APIController.SendNonHileWebhook(id.Value, $"Attempted to set the main image for club {clubId} but does not have permission.");
|
||||
return StatusCode(403);
|
||||
}
|
||||
|
||||
var club = ClubsDB.SetMainImage(clubId, imageName, id.Value);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = "", value = ClubsDB.ToDetails(club, id.Value) }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpDelete("/club/{clubId}/mainimage")]
|
||||
public IActionResult DeleteMainImage(long clubId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var existing = ClubsDB.GetClub(clubId);
|
||||
if (existing == null) return NotFound("");
|
||||
|
||||
if (!ClubsDB.CanEditDetails(clubId, id.Value))
|
||||
{
|
||||
APIController.SendNonHileWebhook(id.Value, $"Attempted to delete the main image for club {clubId} but does not have permission.");
|
||||
return StatusCode(403);
|
||||
}
|
||||
|
||||
if (existing.AdditionalImages.Count == 0)
|
||||
return StatusCode(405);
|
||||
|
||||
var club = ClubsDB.DeleteMainImage(clubId, id.Value);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = "", value = ClubsDB.ToDetails(club, id.Value) }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPut("/club/{clubId}/additionalimage/{index}")]
|
||||
public IActionResult SetAdditionalImage(long clubId, int index, [FromForm] string imageName)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var existing = ClubsDB.GetClub(clubId);
|
||||
if (existing == null) return NotFound("");
|
||||
|
||||
if (!ClubsDB.CanEditDetails(clubId, id.Value))
|
||||
{
|
||||
APIController.SendNonHileWebhook(id.Value, $"Attempted to set additional image {index} for club {clubId} but does not have permission.");
|
||||
return StatusCode(403);
|
||||
}
|
||||
|
||||
var club = ClubsDB.SetAdditionalImage(clubId, index, imageName, id.Value);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = "", value = ClubsDB.ToDetails(club, id.Value) }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPut("/club/{clubId}/clubhouse")]
|
||||
public IActionResult SetClubhouse(long clubId, [FromForm] long roomId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var existing = ClubsDB.GetClub(clubId);
|
||||
if (existing == null) return NotFound("");
|
||||
|
||||
if (!ClubsDB.IsOwnerOrCoOwner(clubId, id.Value) && existing.CreatorAccountId != id.Value)
|
||||
{
|
||||
APIController.SendNonHileWebhook(id.Value, $"Attempted to set clubhouse for club {clubId} but does not have permission.");
|
||||
return StatusCode(403);
|
||||
}
|
||||
|
||||
var club = ClubsDB.SetClubhouse(clubId, roomId, id.Value);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = "", value = ClubsDB.ToDetails(club, id.Value) }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpDelete("/club/{clubId}/clubhouse")]
|
||||
public IActionResult RemoveClubhouse(long clubId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var existing = ClubsDB.GetClub(clubId);
|
||||
if (existing == null) return NotFound("");
|
||||
|
||||
if (!ClubsDB.IsOwnerOrCoOwner(clubId, id.Value) && existing.CreatorAccountId != id.Value)
|
||||
{
|
||||
APIController.SendNonHileWebhook(id.Value, $"Attempted to remove clubhouse for club {clubId} but does not have permission.");
|
||||
return StatusCode(403);
|
||||
}
|
||||
|
||||
var club = ClubsDB.RemoveClubhouse(clubId, id.Value);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = "", value = ClubsDB.ToDetails(club, id.Value) }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpGet("/club/{clubId}/hasDisabledClubChat")]
|
||||
public IActionResult HasDisabledClubChat(long clubId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var club = ClubsDB.GetClub(clubId);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
[HttpPut("/club/{clubId}/members/requesttojoin")]
|
||||
public async Task<IActionResult> RequestToJoin(long clubId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var existing = ClubsDB.GetClub(clubId);
|
||||
if (existing == null) return NotFound("");
|
||||
|
||||
if (existing.Joinability == (int)ClubJoinability.Closed) return BadRequest(new { success = false, error = "The club is invite only", error_id = "Club.InviteOnly", value = (object?)null });
|
||||
|
||||
var club = ClubsDB.JoinClub(clubId, id.Value);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
var joined = club.Members.FirstOrDefault(m => m.AccountId == id.Value);
|
||||
if (joined != null)
|
||||
{
|
||||
await NotificationsController.BroadcastClubMembershipUpdate(joined.MemberId, id.Value, clubId, joined.MemberType, joined.JoinedAt);
|
||||
await NotificationsController.BroadcastCreatorClubSubscriptionUpdate(club.CreatorAccountId, clubId, joined.MemberType);
|
||||
}
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = "", value = ClubsDB.ToDetails(club, id.Value) }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost("/club/{clubId}/members/leave")]
|
||||
public async Task<IActionResult> RequestLeaveClub(long clubId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var existing = ClubsDB.GetClub(clubId);
|
||||
if (existing == null) return NotFound("");
|
||||
|
||||
var leaving = existing.Members.FirstOrDefault(m => m.AccountId == id.Value);
|
||||
|
||||
var club = ClubsDB.LeaveClub(clubId, id.Value);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
if (leaving != null)
|
||||
{
|
||||
await NotificationsController.BroadcastClubMembershipUpdate(leaving.MemberId, id.Value, clubId, 0, DateTime.UtcNow);
|
||||
await NotificationsController.BroadcastCreatorClubSubscriptionUpdate(existing.CreatorAccountId, clubId, 0);
|
||||
}
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = "", value = ClubsDB.ToDetails(club, id.Value) }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPut("/club/{clubId}/permissions/{membershipType}")]
|
||||
public IActionResult SetPermissions(long clubId, int membershipType, [FromForm] bool approveMember, [FromForm] bool banUnban, [FromForm] bool createEvent, [FromForm] bool editDetails, [FromForm] bool editPermissionSettings, [FromForm] bool postAnnouncement)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var existing = ClubsDB.GetClub(clubId);
|
||||
if (existing == null) return NotFound("");
|
||||
|
||||
if (!ClubsDB.IsOwnerOrCoOwner(clubId, id.Value))
|
||||
{
|
||||
APIController.SendNonHileWebhook(id.Value, $"Attempted to set permissions for club {clubId} but does not have permission.");
|
||||
return StatusCode(403);
|
||||
}
|
||||
|
||||
var club = ClubsDB.SetPermissions(clubId, membershipType, approveMember, banUnban, createEvent, editDetails, editPermissionSettings, postAnnouncement);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = "", value = ClubsDB.ToDetails(club, id.Value) }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpGet("/club/home/me")]
|
||||
public IActionResult GetMyHomeClub()
|
||||
{
|
||||
var player = AuthStuff.GetCurrentPlayer(Request);
|
||||
if (player == null) return Unauthorized("");
|
||||
|
||||
int homeClubId = (int)player.Player.PlayerExtra.HomeClubhouseId;
|
||||
if (homeClubId == 0 || homeClubId == null) return NotFound("");
|
||||
|
||||
var club = ClubsDB.GetClub(homeClubId);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(ClubsDB.ToSummary(club)),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPut("/club/home/me")]
|
||||
public IActionResult SetMyHomeClub([FromForm] long clubId)
|
||||
{
|
||||
var player = AuthStuff.GetCurrentPlayer(Request);
|
||||
if (player == null) return Unauthorized("");
|
||||
|
||||
var club = ClubsDB.GetClub(clubId);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
player.Player.PlayerExtra.HomeClubhouseId = clubId;
|
||||
PlayerDB.Players.Update(player);
|
||||
|
||||
return Ok(new { success = true, error = (string?)null, value = (object?)null });
|
||||
}
|
||||
|
||||
[HttpDelete("/club/home/me")]
|
||||
public IActionResult DeleteMyHomeClub([FromForm] long clubId)
|
||||
{
|
||||
var player = AuthStuff.GetCurrentPlayer(Request);
|
||||
if (player == null) return Unauthorized("");
|
||||
|
||||
player.Player.PlayerExtra.HomeClubhouseId = 0;
|
||||
PlayerDB.Players.Update(player);
|
||||
|
||||
return Ok(new { success = true, error = (string?)null, value = (object?)null });
|
||||
}
|
||||
|
||||
[HttpGet("/announcements/mine")]
|
||||
public IActionResult GetMyAnnouncements()
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var result = ClubsDB.GetAnnouncementsForMyClubs(id.Value);
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = "", value = result }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpGet("/announcements/club/{clubId}")]
|
||||
public IActionResult GetClubAnnouncements(long clubId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var result = ClubsDB.GetClubAnnouncements(clubId, id.Value);
|
||||
if (result == null) return NotFound("");
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = "", value = result }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost("/announcements/club/{clubId}")]
|
||||
public IActionResult CreateAnnouncement(
|
||||
long clubId,
|
||||
[FromForm] string title,
|
||||
[FromForm] string body,
|
||||
[FromForm] string? imageName,
|
||||
[FromForm] string? meta)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(title) || title.Length > 50)
|
||||
return BadRequest(new { success = false, error = "Title must be between 1 and 50 characters." });
|
||||
|
||||
if (string.IsNullOrWhiteSpace(body) || body.Length > 1000)
|
||||
return BadRequest(new { success = false, error = "Body must be between 1 and 1000 characters." });
|
||||
|
||||
var club = ClubsDB.GetClub(clubId);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
if (!ClubsDB.CanPostAnnouncement(clubId, id.Value))
|
||||
return StatusCode(403);
|
||||
|
||||
var announcement = ClubsDB.CreateAnnouncement(clubId, id.Value, title, body, imageName, meta);
|
||||
if (announcement == null) return StatusCode(500);
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = "", value = announcement.AnnouncementId }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPut("/announcements/club/{clubId}/{announcementId}")]
|
||||
public IActionResult EditAnnouncement(
|
||||
long clubId,
|
||||
long announcementId,
|
||||
[FromForm] string title,
|
||||
[FromForm] string body,
|
||||
[FromForm] string? imageName,
|
||||
[FromForm] string? meta)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(title) || title.Length > 50)
|
||||
return BadRequest(new { success = false, error = "Title must be between 1 and 50 characters." });
|
||||
|
||||
if (string.IsNullOrWhiteSpace(body) || body.Length > 1000)
|
||||
return BadRequest(new { success = false, error = "Body must be between 1 and 1000 characters." });
|
||||
|
||||
var club = ClubsDB.GetClub(clubId);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
var announcement = ClubsDB.EditAnnouncement(clubId, announcementId, id.Value, title, body, imageName, meta);
|
||||
if (announcement == null) return StatusCode(403);
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = "", value = announcement.AnnouncementId }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpDelete("/announcements/club/{clubId}/{announcementId}")]
|
||||
public IActionResult DeleteAnnouncement(long clubId, long announcementId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var club = ClubsDB.GetClub(clubId);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
bool deleted = ClubsDB.DeleteAnnouncement(clubId, announcementId, id.Value);
|
||||
if (!deleted) return StatusCode(403);
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = (string?)null, value = (object?)null }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost("/announcements/club/{clubId}/{announcementId}/read")]
|
||||
public IActionResult MarkAnnouncementRead(long clubId, long announcementId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
bool ok = ClubsDB.MarkAnnouncementRead(clubId, announcementId, id.Value);
|
||||
if (!ok) return NotFound("");
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = (string?)null, value = (object?)null }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPut("/club/{clubId}/members/{targetId}/role")]
|
||||
public async Task<IActionResult> SetMemberRole(long clubId, long targetId, [FromForm] int membershipType)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var club = ClubsDB.GetClub(clubId);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
if (!ClubsDB.IsOwnerOrCoOwner(clubId, id.Value) && club.CreatorAccountId != id.Value)
|
||||
{
|
||||
APIController.SendNonHileWebhook(id.Value, $"Attempted to set role in club {clubId} but does not have permission.");
|
||||
return StatusCode(403);
|
||||
}
|
||||
|
||||
var target = club.Members.FirstOrDefault(m => m.AccountId == targetId);
|
||||
if (target == null) return NotFound("");
|
||||
|
||||
bool ok = ClubsDB.SetMemberRole(clubId, targetId, membershipType, id.Value);
|
||||
if (!ok) return NotFound("");
|
||||
|
||||
await NotificationsController.BroadcastClubMembershipUpdate(target.MemberId, targetId, clubId, membershipType, target.JoinedAt);
|
||||
|
||||
var updated = ClubsDB.GetClub(clubId);
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = (string?)null, value = updated != null ? ClubsDB.ToDetails(updated, id.Value) : null }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPut("/club/{clubId}/members/{targetId}/kick")]
|
||||
public async Task<IActionResult> KickMember(long clubId, long targetId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var club = ClubsDB.GetClub(clubId);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
var target = club.Members.FirstOrDefault(m => m.AccountId == targetId);
|
||||
|
||||
var result = ClubsDB.KickMember(clubId, targetId, id.Value);
|
||||
if (result == null)
|
||||
{
|
||||
APIController.SendNonHileWebhook(id.Value, $"Attempted to kick {targetId} from club {clubId} but does not have permission.");
|
||||
return StatusCode(403);
|
||||
}
|
||||
|
||||
if (target != null)
|
||||
await NotificationsController.BroadcastClubMembershipUpdate(target.MemberId, targetId, clubId, 0, DateTime.UtcNow);
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = (string?)null, value = ClubsDB.ToDetails(result, id.Value) }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPut("/club/{clubId}/members/{targetId}/ban")]
|
||||
public async Task<IActionResult> BanMember(long clubId, long targetId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var club = ClubsDB.GetClub(clubId);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
var target = club.Members.FirstOrDefault(m => m.AccountId == targetId);
|
||||
|
||||
bool ok = ClubsDB.BanMember(clubId, targetId, id.Value);
|
||||
if (!ok)
|
||||
{
|
||||
APIController.SendNonHileWebhook(id.Value, $"Attempted to ban {targetId} from club {clubId} but does not have permission.");
|
||||
return StatusCode(403);
|
||||
}
|
||||
|
||||
if (target != null)
|
||||
await NotificationsController.BroadcastClubMembershipUpdate(target.MemberId, targetId, clubId, 0, DateTime.UtcNow);
|
||||
|
||||
var updated = ClubsDB.GetClub(clubId);
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = (string?)null, value = updated != null ? ClubsDB.ToDetails(updated, id.Value) : null }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPut("/club/{clubId}/members/{targetId}/unban")]
|
||||
public IActionResult UnbanMember(long clubId, long targetId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
bool ok = ClubsDB.UnbanMember(clubId, targetId, id.Value);
|
||||
if (!ok)
|
||||
{
|
||||
APIController.SendNonHileWebhook(id.Value, $"Attempted to unban {targetId} from club {clubId} but does not have permission.");
|
||||
return StatusCode(403);
|
||||
}
|
||||
|
||||
var updated = ClubsDB.GetClub(clubId);
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = (string?)null, value = updated != null ? ClubsDB.ToDetails(updated, id.Value) : null }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPut("/club/{clubId}/members/{targetId}/approve")]
|
||||
public async Task<IActionResult> ApproveMember(long clubId, long targetId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null) return Unauthorized("");
|
||||
|
||||
var club = ClubsDB.GetClub(clubId);
|
||||
if (club == null) return NotFound("");
|
||||
|
||||
var result = ClubsDB.ApproveMember(clubId, targetId, id.Value);
|
||||
if (result == null)
|
||||
{
|
||||
APIController.SendNonHileWebhook(id.Value, $"Attempted to approve {targetId} in club {clubId} but does not have permission.");
|
||||
return StatusCode(403);
|
||||
}
|
||||
|
||||
var member = result.Members.FirstOrDefault(m => m.AccountId == targetId);
|
||||
if (member != null)
|
||||
{
|
||||
await NotificationsController.BroadcastClubMembershipUpdate(member.MemberId, targetId, clubId, member.MemberType, member.JoinedAt);
|
||||
await NotificationsController.BroadcastCreatorClubSubscriptionUpdate(result.CreatorAccountId, clubId, member.MemberType);
|
||||
}
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
Content = JsonConvert.SerializeObject(new { success = true, error = (string?)null, value = ClubsDB.ToDetails(result, id.Value) }),
|
||||
ContentType = "application/json",
|
||||
StatusCode = 200
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
//using Microsoft.AspNetCore.Mvc;
|
||||
//using Vanadium.Auth;
|
||||
//using Vanadium.Classes;
|
||||
//using Vanadium.Classes.DBs;
|
||||
//using System.Text;
|
||||
//using System.Text.Json;
|
||||
//using System.Text.Json.Serialization;
|
||||
//using Vanadium.Classes;
|
||||
|
||||
//namespace Vanadium.Controllers
|
||||
//{
|
||||
// [ApiController]
|
||||
// public class PhotonController : ControllerBase
|
||||
// {
|
||||
// private readonly HttpClient _httpClient = new();
|
||||
|
||||
// private bool IsRealClient()
|
||||
// {
|
||||
// var accept = Request.Headers["Accept"].ToString();
|
||||
// var userAgent = Request.Headers["User-Agent"].ToString();
|
||||
|
||||
// return userAgent == "BestHTTP"
|
||||
// && accept.Contains("application/json")
|
||||
// && accept.Contains("image/png")
|
||||
// && accept.Contains("image/jpeg");
|
||||
// }
|
||||
|
||||
// private async Task SendFakeClientWebhook(string ip, string headersPretty, string body)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// const int maxLen = 950;
|
||||
// var truncatedHeaders = headersPretty.Length > maxLen
|
||||
// ? headersPretty.Substring(0, maxLen) + "\n... (truncated)"
|
||||
// : headersPretty;
|
||||
|
||||
// var embed = new
|
||||
// {
|
||||
// title = "⚠️ Fake Client Hit AppSettings (served decoy)",
|
||||
// color = 15158332,
|
||||
// fields = new object[]
|
||||
// {
|
||||
// new { name = "IP", value = $"`{ip}`", inline = false },
|
||||
// new { name = "Headers", value = $"```\n{truncatedHeaders}\n```", inline = false },
|
||||
// new { name = "Body", value = $"json```\n{body}\n```", inline = false }
|
||||
// },
|
||||
// timestamp = DateTime.UtcNow.ToString("O")
|
||||
// };
|
||||
// var payload = new
|
||||
// {
|
||||
// embeds = new[] { embed }
|
||||
// };
|
||||
// var content = new StringContent(
|
||||
// JsonSerializer.Serialize(payload),
|
||||
// Encoding.UTF8,
|
||||
// "application/json"
|
||||
// );
|
||||
// await _httpClient.PostAsync(ServerConfig.PhotonWebhook, content);
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// Console.WriteLine($"Fake client webhook error: {ex.Message}");
|
||||
// }
|
||||
// }
|
||||
|
||||
// [HttpGet("/photon/appSettings")]
|
||||
// public IActionResult GetPhoton()
|
||||
// {
|
||||
// return NotFound("");
|
||||
// Console.WriteLine("photon called");
|
||||
// if (!IsRealClient()) // dont touch this a fix for the photon botter botting us
|
||||
// {
|
||||
// var fakeIp = HttpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown";
|
||||
// var fakeHeaders = GetHeadersPretty();
|
||||
// var decoy = new AppSettings
|
||||
// {
|
||||
// PhotonRealtimeId = "aaae496f-ece0-4b1b-82ac-aea17d766c82",
|
||||
// PhotonVoiceId = "d1b950c8-95e4-4725-9a3b-f6fc57853484",
|
||||
// PhotonRegion = "us"
|
||||
// };
|
||||
// string decoyJson = JsonSerializer.Serialize(decoy, new JsonSerializerOptions { WriteIndented = true });
|
||||
// _ = SendFakeClientWebhook(fakeIp, fakeHeaders, decoyJson);
|
||||
// return Ok(decoy);
|
||||
// }
|
||||
|
||||
// var ip = HttpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown";
|
||||
// var settings = ServerConfig.appSettings;
|
||||
|
||||
// string settingsJson = JsonSerializer.Serialize(settings, new JsonSerializerOptions { WriteIndented = true });
|
||||
// string headersPretty = GetHeadersPretty();
|
||||
|
||||
// _ = SendAppSettingsWebhook(ip, headersPretty, settingsJson);
|
||||
// return Ok(settings);
|
||||
//}
|
||||
|
||||
// private string GetHeadersPretty()
|
||||
// {
|
||||
// var sb = new StringBuilder();
|
||||
// foreach (var header in Request.Headers)
|
||||
// {
|
||||
// sb.AppendLine($"{header.Key}: {header.Value}");
|
||||
// }
|
||||
// return sb.ToString();
|
||||
// }
|
||||
|
||||
// [HttpPost("/photon/{url}")]
|
||||
// public async Task<IActionResult> stub(string url)
|
||||
// {
|
||||
// return await HandleStub("", "/photon", url);
|
||||
// }
|
||||
|
||||
// [HttpPost("/photon_realtime/{url}")]
|
||||
// public async Task<IActionResult> stubRealtime(string url)
|
||||
// {
|
||||
// return await HandleStub("Realtime", "/photon_realtime", url);
|
||||
// }
|
||||
|
||||
// [HttpPost("/photon_voice/{url}")]
|
||||
// public async Task<IActionResult> stubVoice(string url)
|
||||
// {
|
||||
// return await HandleStub("Voice", "/photon_voice", url);
|
||||
// }
|
||||
|
||||
// private async Task<IActionResult> HandleStub(string type, string urltype, string url)
|
||||
// {
|
||||
// Request.EnableBuffering();
|
||||
// string rawBody;
|
||||
// using (var reader = new StreamReader(Request.Body, Encoding.UTF8, detectEncodingFromByteOrderMarks: false, bufferSize: 1024, leaveOpen: true))
|
||||
// {
|
||||
// rawBody = await reader.ReadToEndAsync();
|
||||
// Request.Body.Position = 0;
|
||||
// }
|
||||
// string prettyJson = rawBody;
|
||||
// try
|
||||
// {
|
||||
// if (!string.IsNullOrWhiteSpace(rawBody))
|
||||
// {
|
||||
// using var doc = JsonDocument.Parse(rawBody);
|
||||
// prettyJson = JsonSerializer.Serialize(doc, new JsonSerializerOptions { WriteIndented = true });
|
||||
// }
|
||||
// }
|
||||
// catch (JsonException)
|
||||
// {
|
||||
// }
|
||||
// Console.WriteLine($"Stub called: url={urltype}/{url}, body={rawBody}");
|
||||
// await SendStubWebhook(type, urltype, url, prettyJson);
|
||||
// return Ok(new
|
||||
// {
|
||||
// ResultCode = 0
|
||||
// });
|
||||
// }
|
||||
|
||||
// private async Task SendAppSettingsWebhook(string ip, string headersPretty, string bodyValue)
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// const int maxLen = 950;
|
||||
// var truncatedHeaders = headersPretty.Length > maxLen
|
||||
// ? headersPretty.Substring(0, maxLen) + "\n... (truncated)"
|
||||
// : headersPretty;
|
||||
|
||||
// var embed = new
|
||||
// {
|
||||
// title = "Photon GET AppSettings Called",
|
||||
// color = 15105570,
|
||||
// fields = new object[]
|
||||
// {
|
||||
// new { name = "IP", value = $"`{ip}`", inline = false },
|
||||
// new { name = "Headers", value = $"json```\n{truncatedHeaders}\n```", inline = false },
|
||||
// new { name = "Body", value = $"json```\n{bodyValue}\n```", inline = false }
|
||||
// },
|
||||
// timestamp = DateTime.UtcNow.ToString("O")
|
||||
// };
|
||||
// var payload = new
|
||||
// {
|
||||
// embeds = new[] { embed }
|
||||
// };
|
||||
// var content = new StringContent(
|
||||
// JsonSerializer.Serialize(payload),
|
||||
// Encoding.UTF8,
|
||||
// "application/json"
|
||||
// );
|
||||
// var response = await _httpClient.PostAsync(ServerConfig.PhotonWebhook, content);
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// }
|
||||
//}
|
||||
// private async Task SendStubWebhook(string type, string urltype, string url, string prettyJson)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// const int maxLen = 950;
|
||||
// var body = string.IsNullOrWhiteSpace(prettyJson) ? "(empty)" : prettyJson;
|
||||
// var truncated = body.Length > maxLen
|
||||
// ? body.Substring(0, maxLen) + "\n... (truncated)"
|
||||
// : body;
|
||||
// var bodyValue = body == "(empty)"
|
||||
// ? "(empty)"
|
||||
// : $"```json\n{truncated}\n```";
|
||||
// var embed = new
|
||||
// {
|
||||
// title = $"Photon {type} Called",
|
||||
// color = 15105570,
|
||||
// fields = new object[]
|
||||
// {
|
||||
// new { name = "URL", value = $"`{urltype}/{url}`", inline = false },
|
||||
// new { name = "Body", value = bodyValue, inline = false }
|
||||
// },
|
||||
// timestamp = DateTime.UtcNow.ToString("O")
|
||||
// };
|
||||
// var payload = new
|
||||
// {
|
||||
// embeds = new[] { embed }
|
||||
// };
|
||||
// var content = new StringContent(
|
||||
// JsonSerializer.Serialize(payload),
|
||||
// Encoding.UTF8,
|
||||
// "application/json"
|
||||
// );
|
||||
// var response = await _httpClient.PostAsync(ServerConfig.PhotonWebhook, content);
|
||||
// Console.WriteLine($"Stub webhook sent: {response.StatusCode}");
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// Console.WriteLine($"Stub webhook error: {ex.Message}");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
@@ -0,0 +1,434 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Vanadium.Auth;
|
||||
using Vanadium.Classes.DBs;
|
||||
using Vanadium.Classes;
|
||||
using static Vanadium.Classes.DBs.DBClasses.EventDBClasses;
|
||||
|
||||
namespace Vanadium.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
public partial class PlayerEventsController : ControllerBase
|
||||
{
|
||||
[HttpGet("/api/playerevents/v1/tagfilters")]
|
||||
public async Task<IActionResult> PlayerEventTags()
|
||||
{
|
||||
return Ok(System.Text.Json.JsonSerializer.Deserialize<object>(
|
||||
System.IO.File.ReadAllText(
|
||||
Path.Combine(Environment.CurrentDirectory, "Data", "APIS", "EventTags.json"))));
|
||||
}
|
||||
|
||||
[HttpGet("/api/playerevents/v1/all")]
|
||||
public async Task<IActionResult> GetAllPlayerEvents()
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null)
|
||||
return Unauthorized("");
|
||||
|
||||
var created = EventDB.GetPlayerEvents(id.Value);
|
||||
var attending = EventDB.GetAttendingEvents(id.Value);
|
||||
var hosting = EventDB.GetHostingEvents(id.Value);
|
||||
var responses = EventDB.GetResponsesForPlayer(id.Value);
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
Created = created,
|
||||
Attending = attending,
|
||||
Hosting = hosting,
|
||||
Responses = responses
|
||||
});
|
||||
}
|
||||
|
||||
[HttpGet("/api/playerevents/v1/searchlive")]
|
||||
public async Task<IActionResult> GetLiveEvents()
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null)
|
||||
return Unauthorized("");
|
||||
|
||||
var events = EventDB.GetLiveEvents();
|
||||
return Ok(events);
|
||||
}
|
||||
|
||||
[HttpGet("/api/playerevents/v1/search")]
|
||||
public async Task<IActionResult> SearchEvents(
|
||||
[FromQuery] string? query,
|
||||
[FromQuery] string? sort,
|
||||
[FromQuery] string? scheduleFilter)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null)
|
||||
return Unauthorized("");
|
||||
|
||||
var events = EventDB.SearchEvents(query, sort, scheduleFilter);
|
||||
return Ok(events);
|
||||
}
|
||||
|
||||
[HttpGet("/api/playerevents/v1/room/{roomId}")]
|
||||
public async Task<IActionResult> GetEventsForRoom(long roomId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null)
|
||||
return Unauthorized("");
|
||||
|
||||
var events = EventDB.GetEventsByRoomId(roomId);
|
||||
return Ok(events);
|
||||
}
|
||||
|
||||
[HttpGet("/api/playerevents/v1/club")]
|
||||
[HttpGet("/api/playerevents/v1/clubs")]
|
||||
public async Task<IActionResult> GetEventsForClub()
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null)
|
||||
return Unauthorized("");
|
||||
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
|
||||
[HttpGet("/api/playerevents/v1/{eventId}")]
|
||||
public async Task<IActionResult> GetPlayerEvent(long eventId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null)
|
||||
return Unauthorized("");
|
||||
|
||||
var ev = EventDB.GetPlayerEventById(eventId);
|
||||
if (ev == null)
|
||||
return NotFound("");
|
||||
|
||||
return Ok(ev);
|
||||
}
|
||||
|
||||
[HttpPost("/api/playerevents/v2")]
|
||||
public async Task<IActionResult> CreatePlayerEvent([FromBody] PlayerEventRequest request)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null)
|
||||
return Unauthorized("");
|
||||
|
||||
if (Sanitize.ContainsSwears(request.Name) || Sanitize.ContainsSwears(request.Description))
|
||||
return Ok(new PlayerEventResponse { PlayerEvent = null, Result = 14 });
|
||||
|
||||
var response = EventDB.CreatePlayerEvent(id.Value, request);
|
||||
if (response.Result != 0)
|
||||
return Ok(response);
|
||||
|
||||
var wsJson = Newtonsoft.Json.JsonConvert.SerializeObject(new Vanadium.Classes.WebSocket.WebsocketEvents.Response
|
||||
{
|
||||
Id = "PlayerEventCreated",
|
||||
Msg = response.PlayerEvent
|
||||
});
|
||||
await NotificationsController.SendToAll(wsJson);
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
[HttpDelete("/api/playerevents/v2/delete/{eventId}")]
|
||||
public async Task<IActionResult> DeletePlayerEvent(long eventId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null)
|
||||
return Unauthorized("");
|
||||
|
||||
var deleted = EventDB.DeletePlayerEvent(eventId, id.Value);
|
||||
return Ok(new { success = deleted });
|
||||
}
|
||||
|
||||
[HttpPost("/api/playerevents/v2/{eventId}/rsvp")]
|
||||
public async Task<IActionResult> RsvpPlayerEvent(long eventId, [FromBody] RsvpRequest request)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null)
|
||||
return Unauthorized("");
|
||||
|
||||
var ev = EventDB.GetPlayerEventById(eventId);
|
||||
if (ev == null)
|
||||
return NotFound("");
|
||||
|
||||
var response = EventDB.SetResponse(eventId, id.Value, request.Type);
|
||||
return Ok(new { success = true, value = response });
|
||||
}
|
||||
|
||||
[HttpGet("/api/playerevents/v2/{eventId}/rsvp")]
|
||||
public async Task<IActionResult> GetRsvp(long eventId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null)
|
||||
return Unauthorized("");
|
||||
|
||||
var response = EventDB.GetResponse(eventId, id.Value);
|
||||
var type = response?.Type ?? (int)PlayerEventResponseType.None;
|
||||
return Ok(new { type });
|
||||
}
|
||||
|
||||
[HttpGet("/api/playerevents/v2/{eventId}/responses")]
|
||||
public async Task<IActionResult> GetEventResponses(long eventId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null)
|
||||
return Unauthorized("");
|
||||
|
||||
var responses = EventDB.GetResponsesForEvent(eventId);
|
||||
return Ok(responses);
|
||||
}
|
||||
|
||||
[HttpPost("/api/playerevents/v1/respond")]
|
||||
public async Task<IActionResult> RespondToPlayerEvent([FromBody] RespondRequest request)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null)
|
||||
return Unauthorized("");
|
||||
|
||||
if (request == null || request.PlayerEventId == 0)
|
||||
return BadRequest(new { success = false, error = "PlayerEventId required." });
|
||||
|
||||
var ev = EventDB.GetPlayerEventById(request.PlayerEventId);
|
||||
if (ev == null)
|
||||
return NotFound("");
|
||||
|
||||
int typeInt = request.Type switch
|
||||
{
|
||||
"Yes" => (int)PlayerEventResponseType.Yes,
|
||||
"Interested" => (int)PlayerEventResponseType.Interested,
|
||||
"No" => (int)PlayerEventResponseType.No,
|
||||
_ => (int)PlayerEventResponseType.None
|
||||
};
|
||||
|
||||
var response = EventDB.SetResponse(request.PlayerEventId, id.Value, typeInt);
|
||||
|
||||
var updatedEvent = EventDB.GetPlayerEventById(request.PlayerEventId);
|
||||
var wsJson = Newtonsoft.Json.JsonConvert.SerializeObject(new Vanadium.Classes.WebSocket.WebsocketEvents.Response
|
||||
{
|
||||
Id = "PlayerEventResponseChanged",
|
||||
Msg = updatedEvent
|
||||
});
|
||||
await NotificationsController.SendToAll(wsJson);
|
||||
|
||||
return Ok(new { success = true, value = response });
|
||||
}
|
||||
|
||||
[HttpGet("/api/playerevents/v1/{eventId}/responses")]
|
||||
public async Task<IActionResult> GetEventResponsesV1(long eventId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null)
|
||||
return Unauthorized("");
|
||||
|
||||
return Ok(EventDB.GetResponsesForEvent(eventId));
|
||||
}
|
||||
|
||||
[HttpPut("/api/playerevents/v2/{eventId}/name")]
|
||||
[HttpPost("/api/playerevents/v2/{eventId}/name")]
|
||||
public async Task<IActionResult> EditEventName(long eventId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null)
|
||||
return Unauthorized("");
|
||||
|
||||
var name = await ReadBodyValue("name", "value");
|
||||
if (name == null)
|
||||
return BadRequest(new { success = false, error = "Name required." });
|
||||
|
||||
var ev = EventDB.EditPlayerEvent(eventId, id.Value, e => e.Name = name);
|
||||
if (ev == null) return NotFound();
|
||||
var wsJson = Newtonsoft.Json.JsonConvert.SerializeObject(new Vanadium.Classes.WebSocket.WebsocketEvents.Response
|
||||
{
|
||||
Id = "PlayerEventUpdated",
|
||||
Msg = ev
|
||||
});
|
||||
await NotificationsController.SendToAll(wsJson);
|
||||
return Ok(new { success = true, value = ev });
|
||||
}
|
||||
|
||||
[HttpPut("/api/playerevents/v2/{eventId}/description")]
|
||||
[HttpPost("/api/playerevents/v2/{eventId}/description")]
|
||||
public async Task<IActionResult> EditEventDescription(long eventId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null)
|
||||
return Unauthorized("");
|
||||
|
||||
var desc = await ReadBodyValue("description", "value");
|
||||
if (desc == null)
|
||||
return BadRequest(new { success = false, error = "Description required." });
|
||||
|
||||
var ev = EventDB.EditPlayerEvent(eventId, id.Value, e => e.Description = desc);
|
||||
if (ev == null) return NotFound();
|
||||
var wsJson = Newtonsoft.Json.JsonConvert.SerializeObject(new Vanadium.Classes.WebSocket.WebsocketEvents.Response
|
||||
{
|
||||
Id = "PlayerEventUpdated",
|
||||
Msg = ev
|
||||
});
|
||||
await NotificationsController.SendToAll(wsJson);
|
||||
return Ok(new { success = true, value = ev });
|
||||
}
|
||||
|
||||
[HttpPut("/api/playerevents/v2/{eventId}/image")]
|
||||
[HttpPost("/api/playerevents/v2/{eventId}/image")]
|
||||
public async Task<IActionResult> EditEventImage(long eventId)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null)
|
||||
return Unauthorized("");
|
||||
|
||||
var image = await ReadBodyValue("imageName", "image", "value");
|
||||
if (image == null)
|
||||
return BadRequest(new { success = false, error = "ImageName required." });
|
||||
|
||||
var ev = EventDB.EditPlayerEvent(eventId, id.Value, e => e.ImageName = image);
|
||||
if (ev == null) return NotFound();
|
||||
var wsJson = Newtonsoft.Json.JsonConvert.SerializeObject(new Vanadium.Classes.WebSocket.WebsocketEvents.Response
|
||||
{
|
||||
Id = "PlayerEventUpdated",
|
||||
Msg = ev
|
||||
});
|
||||
await NotificationsController.SendToAll(wsJson);
|
||||
return Ok(new { success = true, value = ev });
|
||||
}
|
||||
|
||||
[HttpPut("/api/playerevents/v2/{eventId}/room")]
|
||||
[HttpPost("/api/playerevents/v2/{eventId}/room")]
|
||||
public async Task<IActionResult> EditEventRoom(long eventId, [FromBody] PlayerEventRoomRequest body)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null)
|
||||
return Unauthorized("");
|
||||
|
||||
if (body == null || body.RoomId == 0)
|
||||
return BadRequest(new { success = false, error = "RoomId required." });
|
||||
|
||||
var ev = EventDB.EditPlayerEvent(eventId, id.Value, e =>
|
||||
{
|
||||
e.RoomId = body.RoomId;
|
||||
e.SubRoomId = body.SubRoomId;
|
||||
});
|
||||
if (ev == null) return NotFound();
|
||||
var wsJson = Newtonsoft.Json.JsonConvert.SerializeObject(new Vanadium.Classes.WebSocket.WebsocketEvents.Response
|
||||
{
|
||||
Id = "PlayerEventUpdated",
|
||||
Msg = ev
|
||||
});
|
||||
await NotificationsController.SendToAll(wsJson);
|
||||
return Ok(new { success = true, value = ev });
|
||||
}
|
||||
|
||||
[HttpPut("/api/playerevents/v2/{eventId}/time")]
|
||||
[HttpPost("/api/playerevents/v2/{eventId}/time")]
|
||||
public async Task<IActionResult> EditEventTime(long eventId, [FromBody] PlayerEventTimeRequest body)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null)
|
||||
return Unauthorized("");
|
||||
|
||||
if (body == null || (string.IsNullOrWhiteSpace(body.StartTime) && string.IsNullOrWhiteSpace(body.EndTime)))
|
||||
return BadRequest(new { success = false, error = "StartTime or EndTime required." });
|
||||
|
||||
DateTime? start = null, end = null;
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(body.StartTime)) start = DateTime.Parse(body.StartTime);
|
||||
if (!string.IsNullOrWhiteSpace(body.EndTime)) end = DateTime.Parse(body.EndTime);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return BadRequest(new { success = false, error = "Invalid time format." });
|
||||
}
|
||||
|
||||
var ev = EventDB.EditPlayerEvent(eventId, id.Value, e =>
|
||||
{
|
||||
if (start.HasValue) e.StartTime = start.Value;
|
||||
if (end.HasValue) e.EndTime = end.Value;
|
||||
});
|
||||
if (ev == null) return NotFound();
|
||||
var wsJson = Newtonsoft.Json.JsonConvert.SerializeObject(new Vanadium.Classes.WebSocket.WebsocketEvents.Response
|
||||
{
|
||||
Id = "PlayerEventUpdated",
|
||||
Msg = ev
|
||||
});
|
||||
await NotificationsController.SendToAll(wsJson);
|
||||
return Ok(new { success = true, value = ev });
|
||||
}
|
||||
|
||||
[HttpPut("/api/playerevents/v2/{eventId}/club")]
|
||||
[HttpPost("/api/playerevents/v2/{eventId}/club")]
|
||||
public async Task<IActionResult> EditEventClub(long eventId, [FromBody] PlayerEventClubRequest body)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null)
|
||||
return Unauthorized("");
|
||||
|
||||
var ev = EventDB.EditPlayerEvent(eventId, id.Value, e => e.ClubId = body?.ClubId);
|
||||
if (ev == null) return NotFound();
|
||||
var wsJson = Newtonsoft.Json.JsonConvert.SerializeObject(new Vanadium.Classes.WebSocket.WebsocketEvents.Response
|
||||
{
|
||||
Id = "PlayerEventUpdated",
|
||||
Msg = ev
|
||||
});
|
||||
await NotificationsController.SendToAll(wsJson);
|
||||
return Ok(new { success = true, value = ev });
|
||||
}
|
||||
|
||||
[HttpPut("/api/playerevents/v2/{eventId}/multiinstance")]
|
||||
[HttpPost("/api/playerevents/v2/{eventId}/multiinstance")]
|
||||
public async Task<IActionResult> EditEventMultiInstance(long eventId, [FromBody] PlayerEventMultiInstanceRequest body)
|
||||
{
|
||||
var id = AuthStuff.GetPlayerId(Request);
|
||||
if (id == null)
|
||||
return Unauthorized("");
|
||||
|
||||
if (body == null)
|
||||
return BadRequest(new { success = false, error = "Body required." });
|
||||
|
||||
var ev = EventDB.EditPlayerEvent(eventId, id.Value, e =>
|
||||
{
|
||||
e.IsMultiInstance = body.IsMultiInstance;
|
||||
e.SupportMultiInstanceRoomChat = body.SupportMultiInstanceRoomChat;
|
||||
});
|
||||
if (ev == null) return NotFound();
|
||||
var wsJson = Newtonsoft.Json.JsonConvert.SerializeObject(new Vanadium.Classes.WebSocket.WebsocketEvents.Response
|
||||
{
|
||||
Id = "PlayerEventUpdated",
|
||||
Msg = ev
|
||||
});
|
||||
await NotificationsController.SendToAll(wsJson);
|
||||
return Ok(new { success = true, value = ev });
|
||||
}
|
||||
|
||||
private async Task<string?> ReadBodyValue(params string[] keys)
|
||||
{
|
||||
using var reader = new StreamReader(Request.Body);
|
||||
var raw = (await reader.ReadToEndAsync())?.Trim();
|
||||
if (string.IsNullOrEmpty(raw))
|
||||
return null;
|
||||
|
||||
if (raw.StartsWith("{"))
|
||||
{
|
||||
try
|
||||
{
|
||||
using var doc = System.Text.Json.JsonDocument.Parse(raw);
|
||||
foreach (var prop in doc.RootElement.EnumerateObject())
|
||||
foreach (var k in keys)
|
||||
if (string.Equals(prop.Name, k, StringComparison.OrdinalIgnoreCase))
|
||||
return prop.Value.ValueKind == System.Text.Json.JsonValueKind.String
|
||||
? prop.Value.GetString()
|
||||
: prop.Value.ToString();
|
||||
}
|
||||
catch { }
|
||||
return null;
|
||||
}
|
||||
|
||||
if (raw.StartsWith("\""))
|
||||
{
|
||||
try { return System.Text.Json.JsonSerializer.Deserialize<string>(raw); }
|
||||
catch { return raw.Trim('"'); }
|
||||
}
|
||||
|
||||
return raw;
|
||||
}
|
||||
|
||||
public class RsvpRequest
|
||||
{
|
||||
public int Type { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user