using System.ComponentModel.DataAnnotations; namespace DorkNet.Server.Data.Entities; /// /// A "Group" / club — wire type RecNet.Group /// (Cpp2IL_CS/.../RecNet/Group.cs) for the legacy /// api/groups/v1/* surface, and the newer RecNet.Club /// (Cpp2IL_ISIL/.../PLILLKHMNDA.txt) for the /// clubs.localhost/club/* surface used by 2020.12. Both wire /// shapes are projected from this one entity by the respective /// controllers; field names + types match each client deserializer /// so the watch round-trips cleanly. /// /// The 2020.12 Club wire keys (per ISIL deserializer): /// ClubId, Name, Description, MainImageName, State, CreatorAccountId, /// Category, Visibility, Joinability, AllowJuniors, MemberCount, /// IsRRO, ClubhouseRoomId, ClubType. /// MemberCount is derived live from /// at projection time so we never have to keep a denormalised counter /// in sync; the other fields are persisted columns on this row. /// public class ClubEntity { /// Mirrors wire field GroupId / ClubId. public long Id { get; set; } [MaxLength(128)] public string Name { get; set; } = string.Empty; [MaxLength(2000)] public string Description { get; set; } = string.Empty; /// Mirrors wire CreatorId (legacy) / CreatorAccountId /// (Int32 in the 2020.12 payload). Cast to int in the wire mappers. public long CreatorPlayerId { get; set; } /// Legacy ImageName for api/groups/v1/*. The 2020.12 /// Club wire field is MainImageName — same column, two projection /// names. [MaxLength(256)] public string ImageName { get; set; } = string.Empty; /// GroupBanStatus enum: 0=GoodStanding, 1=InReview, /// 2=TempLock, 3=Permaban. public int BanStatus { get; set; } = 0; /// Club state enum on the 2020.12 wire (State). /// 0=Active, 1=Disbanded, 2=Suspended. Defaults to Active so legacy /// rows created via api/groups/v1/* still surface as live. public int State { get; set; } = 0; /// Primary category-tag name surfaced in the 2020.12 Club /// wire Category field. Empty string is valid — the watch /// renders "uncategorized" when blank. [MaxLength(64)] public string Category { get; set; } = string.Empty; /// Club visibility enum on the wire (Visibility). /// 0=Public, 1=Unlisted, 2=Private. public int Visibility { get; set; } = 0; /// Club joinability enum on the wire (Joinability). /// 0=Open, 1=InviteOnly, 2=AskToJoin — confirmed from the 2023 dump /// (enum FEHIHCMDOLN). This comment previously had 1 and 2 swapped, which /// is the reading the requesttojoin handler was fixed away from. public int Joinability { get; set; } = 0; /// Drives the wire AllowJuniors bool. True means /// junior accounts can join + see member-only content. public bool AllowJuniors { get; set; } = true; /// Drives the wire IsRRO bool — Rec Room Original /// stamp on first-party clubs. Default false; admin-toggle only. public bool IsRRO { get; set; } = false; /// Drives the wire nullable ClubhouseRoomId. When /// set, the watch shows a "Go to clubhouse" CTA on the club /// detail screen that routes to this room's standard goto flow. public long? ClubhouseRoomId { get; set; } /// Drives the wire ClubType int. 0=Standard, /// 1=Featured. The legacy api/groups/v1 surface ignores this; the /// 2020.12 watch uses it to sort featured clubs to the top of /// browse. public int ClubType { get; set; } = 0; /// Minimum account level required to join, surfaced as the wire /// MinLevel and set by PUT club/{id}/minlevel. 0 = no gate. public int MinLevel { get; set; } = 0; /// Whether the club's chat channel is available. Drives the wire /// ClubChatEnabled and is the negation of what /// GET club/{id}/hasDisabledClubChat answers. public bool ClubChatEnabled { get; set; } = true; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; } /// One row per (club, player). Permissions is the /// GroupMembershipPermissions flags enum (Member=0, Moderator=24, /// CoOwner=124, Owner=127, Pending=128 for join-requests on private /// groups). public class ClubMembershipEntity { public long Id { get; set; } public long ClubId { get; set; } public long PlayerId { get; set; } /// GroupMembershipPermissions flags enum value. public int Permissions { get; set; } = 0; public DateTime JoinedAt { get; set; } = DateTime.UtcNow; }