Clan System, please contact me if you have any questions.

Please only contact me if you're Clan System /j
This commit is contained in:
Hipposgrumm 2025-07-29 20:44:59 -06:00
parent 1a6db72d7a
commit c14dc2258c
40 changed files with 1257 additions and 70 deletions

View File

@ -79,13 +79,13 @@ Almost everything:
- hideouts
- farms
- minigames
- clans
- MMO (using sodoff-mmo)
### What doesn't work
- play as Guest
- friends
- clans
- in-game messaging system (Terrible Mail)
@ -94,10 +94,13 @@ Almost everything:
#### Fully implemented
- AcceptMission
- AddBattleItems
- AssignRole
- AuthenticateUser
- CreateGroup
- CreatePet
- DeleteAccountNotification
- DeleteProfile
- EditGroup
- FuseItems
- GetAchievementsByUserID
- GetAllActivePetsByuserId
@ -108,12 +111,17 @@ Almost everything:
- GetDetailedChildList
- GetGameData
- GetGameDataByUser
- GetGroups
- GetGroupsByGroupType
- GetGroupsByUserID
- GetImage
- GetImageByUserId
- GetItem
- GetKeyValuePair
- GetKeyValuePairByUserID
- GetMembersByGroupID
- GetMMOServerInfoWithZone (uses resource xml as response)
- GetPendingJoinRequests
- GetPetAchievementsByUserID
- GetSelectedRaisedPet
- GetStore
@ -127,6 +135,8 @@ Almost everything:
- GetUserRoomItemPositions
- GetUserUpcomingMissionState
- IsValidApiToken_V2
- JoinGroup (V1 & V2) (User-given message for join request disabled, at least for now)
- LeaveGroup
- LoginChild
- LoginParent
- PurchaseItems (V1)
@ -152,7 +162,6 @@ Almost everything:
#### Implemented enough (probably)
- GetCommonInventory (V1 - returns the viking's inventory if it is called with a viking; otherwise returns 8 viking slots)
- GetGroupsByGroupType (only useful for Eat My Dust at the moment)
- GetQuestions (doesn't return all questions, probably doesn't need to)
- GetRules (doesn't return any rules, probably doesn't need to)
- GetSubscriptionInfo (always returns member, with end date 10 years from now)
@ -171,7 +180,6 @@ Almost everything:
- GetTopAchievementPointUsers (ignores type [all, buddy, hall of fame, ...] and mode [overall, monthly, weekly] properties)
- GetUserAchievements (used by Magic & Mythies)
- GetUserRoomList (room categories are not implemented, but it's enough for SoD)
- JoinGroup (for Eat My Dust only)
- ProcessRewardedItems (gives gems, but doesn't give gold, gold is not yet implemented)
- SellItems (gives gems, but doesn't give gold, gold is not yet implemented)
- SetUserAchievementTask (returns a real reward but still use task placeholder)

View File

@ -5,7 +5,57 @@ using sodoff.Schema;
using sodoff.Util;
namespace sodoff.Controllers.Common;
public class GroupController : Controller {
private static readonly List<RolePermission> RolePermissions;
static GroupController() {
RolePermissions = new List<RolePermission>();
for (GroupType type = GroupType.Public; type <= GroupType.Private; type++) {
// Anything commented out is not implemented.
RolePermissions.Add(new RolePermission {
GroupType = type,
Role = UserRole.Member,
Permissions = [
"Delete Own Msg",
//"Post Message"
]
});
RolePermissions.Add(new RolePermission {
GroupType = type,
Role = UserRole.Elder,
Permissions = [
//"Invite",
"Approve Join Request",
//"Post News",
//"Delete Own Msg",
//"Delete Any Msg",
//"Delete News",
//"Post Message",
"Remove Member"
]
});
RolePermissions.Add(new RolePermission {
GroupType = type,
Role = UserRole.Leader,
Permissions = [
//"Invite",
"Approve Join Request",
"Assign Leader",
"Assign Elder",
"Demote Elder",
"Edit Group",
//"Post News",
//"Delete Own Msg",
//"Delete Any Msg",
//"Delete News",
//"Post Message",
"Remove Member"
]
});
}
}
public static readonly Schema.Group EMD_Dragons = new Schema.Group {
GroupID = "8e68214a-c801-4759-8461-d01f28484134",
Name = "Dragons",
@ -24,56 +74,7 @@ public class GroupController : Controller {
public GroupController(DBContext ctx) {
this.ctx = ctx;
}
[HttpPost]
[Produces("application/xml")]
[Route("GroupWebService.asmx/JoinGroup")]
[VikingSession]
public IActionResult JoinGroup(Viking viking, [FromForm] string apiKey, [FromForm] string groupID) {
AddEMDGroups();
uint version = ClientVersion.GetVersion(apiKey);
// Only implemented for EMD so far.
if (version == ClientVersion.EMD) {
if (viking.Groups.Any(g => {
// Check for loyalty.
string id = g.GroupID.ToString();
return id == EMD_Dragons.GroupID || id == EMD_Scorpions.GroupID;
})) {
return Ok(new JoinGroupResult { GroupStatus = GroupMembershipStatus.ALREADY_MEMBER });
}
groupID = groupID.ToUpper();
Model.Group? group = ctx.Groups.FirstOrDefault(g => g.GroupID.ToString() == groupID);
if (group != null) {
group.Vikings.Add(viking);
ctx.SaveChanges();
return Ok(new JoinGroupResult { GroupStatus = GroupMembershipStatus.APPROVED });
}
}
return Ok(new JoinGroupResult { GroupStatus = GroupMembershipStatus.REJECTED });
}
[HttpPost]
[Produces("application/xml")]
[Route("GroupWebService.asmx/GetGroupsByGroupType")]
[VikingSession]
public Schema.Group[] GetGroupsByGroupType([FromForm] string apiKey, [FromForm] string groupType) {
AddEMDGroups();
List<Schema.Group> groups = new List<Schema.Group>();
foreach (Model.Group group in ctx.Groups) {
if (group.ApiKey == apiKey && group.Type.ToString() == groupType) groups.Add(new Schema.Group {
GroupID = group.GroupID.ToString(),
Name = group.Name,
Color = group.Color,
Logo = group.Logo,
Type = group.Type
});
}
return groups.ToArray();
}
private void AddEMDGroups() {
bool changed = false;
Guid DragonString = new Guid(EMD_Dragons.GroupID);
Guid ScorpionString = new Guid(EMD_Scorpions.GroupID);
@ -84,7 +85,8 @@ public class GroupController : Controller {
Color = EMD_Dragons.Color,
Logo = EMD_Dragons.Logo,
Type = GroupType.System,
ApiKey = "dd602cf1-cc98-4738-9a0a-56dde3026947"
GameID = ClientVersion.EMD,
MaxMemberLimit = int.MaxValue
});
changed = true;
}
@ -95,10 +97,451 @@ public class GroupController : Controller {
Color = EMD_Scorpions.Color,
Logo = EMD_Scorpions.Logo,
Type = GroupType.System,
ApiKey = "dd602cf1-cc98-4738-9a0a-56dde3026947"
GameID = ClientVersion.EMD,
MaxMemberLimit = int.MaxValue
});
changed = true;
}
if (changed) ctx.SaveChanges();
}
[HttpPost]
[Produces("application/xml")]
[Route("V2/GroupWebService.asmx/CreateGroup")]
[VikingSession]
public IActionResult CreateGroup(Viking viking, [FromForm] string apiKey, [FromForm] string groupCreateRequest) {
uint gameId = ClientVersion.GetGameID(apiKey);
if (viking.GroupRoles.Any(g => g.GameID == gameId)) {
return Ok(new CreateGroupResult { Success = false, Status = CreateGroupStatus.CreatorIsNotApproved });
}
CreateGroupRequest request = XmlUtil.DeserializeXml<CreateGroupRequest>(groupCreateRequest);
request.Name = request.Name.Trim();
// Cue the gauntlet of validity checks.
if (request.Type <= GroupType.System) return Ok(new CreateGroupResult { Success = false, Status = CreateGroupStatus.GroupTypeIsInvalid });
//if (request.MaxMemberLimit < 4) return Ok(new CreateGroupResult { Success = false, Status = CreateGroupStatus.GroupMaxMemberLimitInvalid }); // Not actually used by the game.
if (request.Name.Length == 0) return Ok(new CreateGroupResult { Success = false, Status = CreateGroupStatus.GroupNameIsEmpty });
if (request.Description.Length == 0) return Ok(new CreateGroupResult { Success = false, Status = CreateGroupStatus.GroupDescriptionIsEmpty });
if (viking.GroupRoles.Any(g => g.Name.Equals(request.Name, StringComparison.InvariantCultureIgnoreCase))) return Ok(new CreateGroupResult { Success = false, Status = CreateGroupStatus.GroupNameIsDuplicate });
Model.Group group = new Model.Group {
Name = request.Name,
Description = request.Description,
Logo = request.Logo,
Color = request.Color,
Type = request.Type,
CreateDate = DateTime.Now,
GameID = gameId,
MaxMemberLimit = 50,
GroupID = Guid.NewGuid(),
Vikings = new List<GroupViking>()
};
ctx.Groups.Add(group);
group.Vikings.Add(new GroupViking {
Viking = viking,
Group = group,
UserRole = UserRole.Leader,
JoinDate = group.CreateDate
});
group.LastActiveTime = group.CreateDate;
ctx.SaveChanges();
return Ok(new CreateGroupResult {
Success = true,
Status = CreateGroupStatus.Success,
Group = new Schema.Group {
Name = group.Name,
Description = group.Description,
Logo = group.Logo,
Color = group.Color,
Type = group.Type,
OwnerID = viking.Uid.ToString(),
Points = 0,//group.Points,
Active = false,//group.Vikings.Count >= 4,
MemberLimit = group.MaxMemberLimit,
GroupID = group.GroupID.ToString()
}
// TODO: Delete after 15 days of less than 4 members.
});
}
[HttpPost]
[Produces("application/xml")]
[Route("V2/GroupWebService.asmx/EditGroup")]
[VikingSession]
public IActionResult EditGroup(Viking viking, [FromForm] string apiKey, [FromForm] string groupEditRequest) {
EditGroupRequest request = XmlUtil.DeserializeXml<EditGroupRequest>(groupEditRequest);
request.Name = request.Name.Trim();
GroupViking? vikingRole = viking.GroupRoles.FirstOrDefault(gv => gv.Group.GroupID.ToString() == request.GroupID);
if (vikingRole == null) {
return Ok(new EditGroupResult { Success = false, Status = EditGroupStatus.GroupNotFound });
} else if (vikingRole.UserRole < UserRole.Elder) {
return Ok(new EditGroupResult { Success = false, Status = EditGroupStatus.PermissionDenied });
}
// Cue the gauntlet of validity checks.
if (request.Type != null && request.Type <= GroupType.System) return Ok(new EditGroupResult { Success = false, Status = EditGroupStatus.GroupTypeIsInvalid });
//if (request.MaxMemberLimit < 4) return Ok(new EditGroupResult { Success = false, Status = EditGroupStatus.GroupMaxMemberLimitInvalid }); // Not actually used by the game.
if ((request.Name?.Length ?? 0) == 0) request.Name = vikingRole.Name;
if ((request.Description?.Length ?? 0) == 0) request.Description = vikingRole.Description;
if (request.Name != vikingRole.Name && viking.GroupRoles.Any(g => g.Name.Equals(request.Name, StringComparison.InvariantCultureIgnoreCase))) return Ok(new EditGroupResult { Success = false, Status = EditGroupStatus.GroupNameIsDuplicate });
vikingRole.Group.Name = request.Name;
vikingRole.Group.Description = request.Description;
if (request.Type != null) vikingRole.Group.Type = (GroupType)request.Type;
if ((request.Color?.Length ?? 0) > 0) vikingRole.Group.Color = request.Color;
if ((request.Logo?.Length ?? 0) > 0) vikingRole.Group.Logo = request.Logo;
ctx.SaveChanges();
return Ok(new EditGroupResult {
Success = true,
Status = EditGroupStatus.Success,
NewRolePermissions = RolePermissions
});
}
[HttpPost]
[Produces("application/xml")]
[Route("GroupWebService.asmx/JoinGroup")]
[VikingSession]
public IActionResult JoinGroupV1(Viking viking, [FromForm] string apiKey, [FromForm] string groupID) {
uint gameId = ClientVersion.GetGameID(apiKey);
// Check for loyalty.
if (viking.GroupRoles.Any(g => g.GameID == gameId)) {
return Ok(new JoinGroupResult { GroupStatus = GroupMembershipStatus.SELF_BLOCKED });
}
Model.Group? group = ctx.Groups.FirstOrDefault(g => g.GroupID.ToString().Equals(groupID, StringComparison.OrdinalIgnoreCase));
if (group != null) {
// This check is only on this side to prevent people from attempting to circumvent the join limit.
if (group.Type <= GroupType.System || group.Vikings.Count < group.MaxMemberLimit) {
group.Vikings.Add(new GroupViking {
Viking = viking,
Group = group,
UserRole = UserRole.Member
});
ctx.SaveChanges();
return Ok(new JoinGroupResult { GroupStatus = GroupMembershipStatus.APPROVED });
}
}
return Ok(new JoinGroupResult { GroupStatus = GroupMembershipStatus.REJECTED });
}
[HttpPost]
[Produces("application/xml")]
[Route("V2/GroupWebService.asmx/JoinGroup")]
[VikingSession]
public IActionResult JoinGroup(Viking viking, [FromForm] string apiKey, [FromForm] string groupJoinRequest) {
uint gameId = ClientVersion.GetGameID(apiKey);
JoinGroupRequest request = XmlUtil.DeserializeXml<JoinGroupRequest>(groupJoinRequest);
Model.Group? group = ctx.Groups.FirstOrDefault(g => g.GroupID.ToString() == request.GroupID.ToUpper());
if (group != null) {
if (group.Type >= GroupType.Private) {
return Ok(new GroupJoinResult { Success = false, Status = JoinGroupStatus.GroupTypeIsNotPublic });
}
GroupViking? existing = viking.GroupRoles.FirstOrDefault(g => g.GameID == gameId);
if (existing != null) {
if (existing.Group == group)
return Ok(new GroupJoinResult { Success = false, Status = JoinGroupStatus.UserAlreadyMemberOfTheGroup });
existing.Group.Vikings.Remove(existing);
if (!existing.Group.Vikings.Any()) ctx.Groups.Remove(existing.Group);
}
if (group.Type == GroupType.MembersOnly) {
if (!group.JoinRequests.Any(r => r.Viking == viking))
group.JoinRequests.Add(new GroupJoinRequest {
Group = group,
Viking = viking,
//Message = request.Message // For future implemention, once moderation is possible.
});
ctx.SaveChanges();
return Ok(new GroupJoinResult { Success = false, Status = JoinGroupStatus.JoinRequestPending });
}
if (group.Vikings.Count < group.MaxMemberLimit) {
GroupViking joinee = new GroupViking {
Viking = viking,
Group = group,
UserRole = UserRole.Member,
JoinDate = DateTime.Now
};
group.Vikings.Add(joinee);
group.LastActiveTime = joinee.JoinDate;
ctx.SaveChanges();
return Ok(new GroupJoinResult { Success = true, Status = JoinGroupStatus.Success });
} else {
return Ok(new GroupJoinResult { Success = false, Status = JoinGroupStatus.GroupIsFull });
}
}
return Ok(new GroupJoinResult { Success = false, Status = JoinGroupStatus.Error });
}
[HttpPost]
[Produces("application/xml")]
[Route("V2/GroupWebService.asmx/LeaveGroup")]
[VikingSession]
public IActionResult LeaveGroup(Viking viking, [FromForm] string groupLeaveRequest) {
LeaveGroupRequest request = XmlUtil.DeserializeXml<LeaveGroupRequest>(groupLeaveRequest);
GroupViking? vikingRole = viking.GroupRoles.FirstOrDefault(g => g.Group.GroupID.ToString() == request.GroupID);
if (vikingRole != null) {
GroupViking? targetRole = null;
if (viking.Uid.ToString().Equals(request.UserID, StringComparison.CurrentCultureIgnoreCase)) {
targetRole = vikingRole.Group.Vikings.FirstOrDefault(gv => gv.Viking == viking);
} else if (vikingRole.UserRole >= UserRole.Elder) {
targetRole = vikingRole.Group.Vikings.FirstOrDefault(gv => gv.Viking.Uid.ToString() == request.UserID);
} else {
return Ok(new LeaveGroupResult { Success = false, Status = LeaveGroupStatus.Error });
}
if (targetRole != null) {
vikingRole.Group.Vikings.Remove(targetRole);
if (!vikingRole.Group.Vikings.Any()) ctx.Groups.Remove(vikingRole.Group);
ctx.SaveChanges();
return Ok(new LeaveGroupResult { Success = true, Status = LeaveGroupStatus.Success });
}
return Ok(new LeaveGroupResult { Success = false, Status = LeaveGroupStatus.UserNotAMemberOfTheGroup });
}
return Ok(new LeaveGroupResult { Success = false, Status = LeaveGroupStatus.Error });
}
[HttpPost]
[Produces("application/xml")]
[Route("V2/GroupWebService.asmx/GetGroups")]
public IActionResult GetGroups([FromForm] string apiKey, [FromForm] string getGroupsRequest) {
uint gameId = ClientVersion.GetGameID(apiKey);
GetGroupsRequest request = XmlUtil.DeserializeXml<GetGroupsRequest>(getGroupsRequest);
IEnumerable<Model.Group> groups = ctx.Groups;
if (request.ForUserID != null) {
Viking? target = ctx.Vikings.FirstOrDefault(v => request.ForUserID.ToUpper() == v.Uid.ToString());
if (target == null) return Ok(new GetGroupsResult { Success = false });
groups = target.GroupRoles.Select(gv => gv.Group);
} else {
groups = groups.Where(g => g.Type == GroupType.Public || g.Type == GroupType.MembersOnly);
}
if (request.Name != null) {
groups = groups.Where(g => g.Name?.Contains(request.Name, StringComparison.InvariantCultureIgnoreCase) == true);
}
int skip = 0;
if (request.PageSize != null) {
if ((request.PageNo ?? 0) > 1) skip = (int)((request.PageNo! - 1) * request.PageSize);
if (skip > 0) groups = groups.Skip(skip);
groups = groups.Take((int) request.PageSize);
}
groups = groups.Where(g => g.GameID == gameId).OrderByDescending(g => g.Points);
return Ok(new GetGroupsResult {
Success = true,
Groups = groups.Select((g, i) => {
Schema.Group group = new Schema.Group {
Name = g.Name,
Description = g.Description,
GroupID = g.GroupID.ToString(),
OwnerID = (g.Vikings.FirstOrDefault(v => v.UserRole == UserRole.Leader)?.Viking?.Uid ?? Guid.Empty).ToString(),
Color = g.Color,
Logo = g.Logo,
Type = g.Type,
Rank = i+skip+1,
MemberLimit = g.MaxMemberLimit
};
if (request.IncludeMemberCount) group.TotalMemberCount = g.Vikings.Count;
return group;
}).ToArray(),
RolePermissions = RolePermissions
});
}
[HttpPost]
[Produces("application/xml")]
[Route("V2/GroupWebService.asmx/RemoveMember")]
[VikingSession]
public IActionResult RemoveMember(Viking viking, [FromForm] string removeMemberRequest) {
RemoveMemberRequest request = XmlUtil.DeserializeXml<RemoveMemberRequest>(removeMemberRequest);
GroupViking? vikingRole = viking.GroupRoles.FirstOrDefault(g => g.Group.GroupID.ToString() == request.GroupID);
if (vikingRole != null) {
if (vikingRole.UserRole < UserRole.Elder) {
return Ok(new RemoveMemberResult { Success = false, Status = RemoveMemberStatus.UserHasNoPermission });
}
GroupViking? targetRole = vikingRole.Group.Vikings.FirstOrDefault(gv => gv.Viking.Uid.ToString() == request.RemoveUserID);
if (targetRole != null) {
vikingRole.Group.Vikings.Remove(targetRole);
if (!vikingRole.Group.Vikings.Any()) ctx.Groups.Remove(vikingRole.Group);
ctx.SaveChanges();
return Ok(new RemoveMemberResult { Success = true, Status = RemoveMemberStatus.Success });
}
return Ok(new RemoveMemberResult { Success = false, Status = RemoveMemberStatus.UserNotAMemberOfTheGroup });
}
return Ok(new RemoveMemberResult { Success = false, Status = RemoveMemberStatus.Error });
}
[HttpPost]
[Produces("application/xml")]
[Route("V2/GroupWebService.asmx/AuthorizeJoinRequest")]
[VikingSession]
public IActionResult AuthorizeJoinRequest(Viking viking, [FromForm] string apiKey, [FromForm] string authorizeJoinRequest) {
uint gameId = ClientVersion.GetGameID(apiKey);
AuthorizeJoinRequest request = XmlUtil.DeserializeXml<AuthorizeJoinRequest>(authorizeJoinRequest);
GroupViking? vikingRole = viking.GroupRoles.FirstOrDefault(g => g.Group.GroupID.ToString() == request.GroupID);
if (vikingRole != null) {
if (vikingRole.UserRole < UserRole.Elder) {
return Ok(new AuthorizeJoinResult { Success = false, Status = AuthorizeJoinStatus.ApproverHasNoPermission });
}
Viking? target = ctx.Vikings.FirstOrDefault(v => v.Uid.ToString() == request.UserID);
if (target != null) {
GroupViking? existing = target.GroupRoles.FirstOrDefault(g => g.GameID == gameId);
if (existing != null) {
if (existing.Group == vikingRole.Group) {
return Ok(new AuthorizeJoinResult { Success = false, Status = AuthorizeJoinStatus.UserAlreadyMemberOfTheGroup });
} else {
return Ok(new AuthorizeJoinResult { Success = false, Status = AuthorizeJoinStatus.UserHasNoJoinRequest });
}
}
if (vikingRole.Group.Vikings.Count < vikingRole.Group.MaxMemberLimit) {
if (request.Approved) {
GroupViking joinee = new GroupViking {
Viking = target,
Group = vikingRole.Group,
UserRole = UserRole.Member,
JoinDate = DateTime.Now
};
vikingRole.Group.Vikings.Add(joinee);
vikingRole.Group.LastActiveTime = joinee.JoinDate;
}
GroupJoinRequest? joinRequest = ctx.GroupJoinRequests.Find(target.Id, vikingRole.GroupID);
if (joinRequest != null) ctx.GroupJoinRequests.Remove(joinRequest);
ctx.SaveChanges();
return Ok(new AuthorizeJoinResult { Success = true, Status = AuthorizeJoinStatus.Success });
} else {
return Ok(new AuthorizeJoinResult { Success = false, Status = AuthorizeJoinStatus.GroupIsFull });
}
} else {
return Ok(new AuthorizeJoinResult { Success = false, Status = AuthorizeJoinStatus.Error });
}
}
return Ok(new AuthorizeJoinResult { Success = false, Status = AuthorizeJoinStatus.ApproverNotInThisGroup });
}
[HttpPost]
[Produces("application/xml")]
[Route("V2/GroupWebService.asmx/AssignRole")]
[VikingSession]
public IActionResult AssignRole(Viking viking, [FromForm] string assignRoleRequest) {
AssignRoleRequest request = XmlUtil.DeserializeXml<AssignRoleRequest>(assignRoleRequest);
GroupViking? vikingRole = viking.GroupRoles.FirstOrDefault(g => g.Group.GroupID.ToString() == request.GroupID);
if (vikingRole != null) {
if (vikingRole.UserRole < UserRole.Elder) {
return Ok(new AssignRoleResult { Success = false, Status = AssignRoleStatus.ApproverHasNoPermission });
}
GroupViking? targetRole = vikingRole.Group.Vikings.FirstOrDefault(gv => gv.Viking.Uid.ToString() == request.MemberID);
if (targetRole != null) {
if (targetRole.UserRole == request.NewRole)
return Ok(new AssignRoleResult { Success = false, Status = AssignRoleStatus.MemberAlreadyInTheRole });
if (vikingRole.UserRole == UserRole.Leader) { // Disallow leader from simply demoting themself.
if (viking == targetRole.Viking)
return Ok(new AssignRoleResult { Success = false, Status = AssignRoleStatus.ApproverHasNoPermission });
} else if (viking != targetRole.Viking || request.NewRole > vikingRole.UserRole) { // Disallow Elders from promoting themselves to leader, or promoting anyone else to elder, but allow them to demote themselves.
return Ok(new AssignRoleResult { Success = false, Status = AssignRoleStatus.ApproverHasNoPermission });
}
targetRole.UserRole = request.NewRole;
if (request.NewRole == UserRole.Leader) vikingRole.UserRole = UserRole.Elder; // This is the only way a leader can demote themself.
ctx.SaveChanges();
return Ok(new AssignRoleResult { Success = true, Status = AssignRoleStatus.Success });
} else {
return Ok(new AssignRoleResult { Success = false, Status = AssignRoleStatus.MemberNotPartOfTheGroup });
}
}
return Ok(new AssignRoleResult { Success = false, Status = AssignRoleStatus.ApproverNotMemberOfTheGroup });
}
[HttpPost]
[Produces("application/xml")]
[Route("V2/GroupWebService.asmx/GetPendingJoinRequest")]
[VikingSession]
public IActionResult GetPendingJoinRequests(Viking viking, [FromForm] string getPendingJoinRequest) {
GetPendingJoinRequest request = XmlUtil.DeserializeXml<GetPendingJoinRequest>(getPendingJoinRequest);
GroupViking? vikingRole = viking.GroupRoles.FirstOrDefault(g => g.Group.GroupID.ToString() == request.GroupID);
if (vikingRole?.UserRole >= UserRole.Elder) {
return Ok(new GetPendingJoinResult {
Success = true,
Requests = vikingRole.Group.JoinRequests
.Select(r => {
PendingJoinRequest req = new PendingJoinRequest {
UserID = r.Viking.Uid.ToString(),
GroupID = vikingRole.Group.GroupID.ToString(),
StatusID = GroupJoinRequestStatus.Pending,
Message = r.Message ?? "Hello! Please invite me to your Crew!" // Defualt from Math Blaster btw
};
req.FromUserID = req.UserID;
return req;
}).ToArray()
});
}
return Ok(new GetPendingJoinResult { Success = false });
}
[HttpPost]
[Produces("application/xml")]
[Route("GroupWebService.asmx/GetGroupsByUserID")]
public Schema.Group[] GetGroupsByUserID([FromForm] string apiKey, [FromForm] string userId) {
uint gameId = ClientVersion.GetGameID(apiKey);
Viking? viking = ctx.Vikings.FirstOrDefault(v => v.Uid.ToString() == userId);
if (viking == null) return [];
return viking.GroupRoles.Where(gv => gv.GameID == gameId).Select(gv => new Schema.Group {
GroupID = gv.Group.GroupID.ToString(),
Name = gv.Name,
Color = gv.Color,
Logo = gv.Logo,
MemberLimit = gv.Group.MaxMemberLimit
}).ToArray();
}
[HttpPost]
[Produces("application/xml")]
[Route("GroupWebService.asmx/GetGroupsByGroupType")]
public Schema.Group[] GetGroupsByGroupType([FromForm] string apiKey, [FromForm] string groupType) {
uint gameId = ClientVersion.GetGameID(apiKey);
List<Schema.Group> groups = new List<Schema.Group>();
foreach (Model.Group group in ctx.Groups) {
if (group.GameID == gameId && group.Type.ToString() == groupType) groups.Add(new Schema.Group {
GroupID = group.GroupID.ToString(),
Name = group.Name,
Color = group.Color,
Logo = group.Logo,
Type = group.Type,
MemberLimit = group.MaxMemberLimit
});
}
return groups.ToArray();
}
[HttpPost]
[Produces("application/xml")]
[Route("GroupWebService.asmx/GetMembersByGroupID")]
public GroupMember[] GetMembersByGroupID([FromForm] string groupID) {
groupID = groupID.ToUpper();
Model.Group? group = ctx.Groups.FirstOrDefault(
g => g.GroupID.ToString() == groupID
);
if (group == null) return [];
return group.Vikings.Select(v => new GroupMember{
DisplayName = v.Viking.AvatarSerialized != null
? XmlUtil.DeserializeXml<AvatarData>(v.Viking.AvatarSerialized).DisplayName
: v.Viking.Name,
UserID = v.Viking.Uid.ToString(),
JoinDate = v.JoinDate,
RoleID = (int) v.UserRole,
Online = false, // There's no way to check this.
Rank = 0,
GroupID = group.GroupID.ToString(),
Points = group.Points
}).ToArray();
}
}

View File

@ -152,18 +152,18 @@ public class ProfileController : Controller {
UserGameCurrency currency = achievementService.GetUserCurrency(viking);
ICollection<Model.Group> groups = viking.Groups;
ICollection<GroupViking> groups = viking.GroupRoles;
UserProfileGroupData[] groupData = new UserProfileGroupData[groups.Count];
int i = 0;
foreach (Model.Group group in groups) {
foreach (GroupViking group in groups) {
groupData[i] = new UserProfileGroupData {
GroupID = group.GroupID.ToString(),
GroupID = group.Group.GroupID.ToString(),
Name = group.Name,
Color = group.Color,
Logo = group.Logo,
TypeID = (int)group.Type,
RoleID = 0
RoleID = group.UserRole
};
i++;
}

View File

@ -1,6 +1,7 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using sodoff.Configuration;
using System.Text.Json;
namespace sodoff.Model;
public class DBContext : DbContext {
@ -26,6 +27,8 @@ public class DBContext : DbContext {
public DbSet<Neighborhood> Neighborhoods { get; set; } = null!;
// we had a brief debate on whether it's neighborhoods or neighborheed
public DbSet<Group> Groups { get; set; } = null!;
public DbSet<GroupViking> GroupViking { get; set; } = null!;
public DbSet<GroupJoinRequest> GroupJoinRequests { get; set; } = null!;
public DbSet<Rating> Ratings { get; set; } = null!;
public DbSet<RatingRank> RatingRanks { get; set; } = null!;
public DbSet<UserMissionData> UserMissionData { get; set; } = null!;
@ -66,6 +69,9 @@ public class DBContext : DbContext {
}
protected override void OnModelCreating(ModelBuilder builder) {
builder.Entity<GroupViking>().HasKey(["VikingID", "GroupID"]);
builder.Entity<GroupJoinRequest>().HasKey(["VikingID", "GroupID"]);
// Sessions
builder.Entity<Session>().HasOne(s => s.User)
.WithMany(e => e.Sessions)
@ -144,8 +150,8 @@ public class DBContext : DbContext {
builder.Entity<Viking>().HasOne(v => v.Neighborhood)
.WithOne(e => e.Viking);
builder.Entity<Viking>().HasMany(v => v.Groups)
.WithMany(e => e.Vikings);
builder.Entity<Viking>().HasMany(v => v.GroupRoles)
.WithOne(g => g.Viking);
builder.Entity<Viking>().HasMany(v => v.Ratings)
.WithOne(r => r.Viking);
@ -279,7 +285,15 @@ public class DBContext : DbContext {
// Groups
builder.Entity<Group>().HasMany(r => r.Vikings)
.WithMany(e => e.Groups);
.WithOne(v => v.Group);
builder.Entity<GroupViking>().HasOne(r => r.Group)
.WithMany(g => g.Vikings);
builder.Entity<GroupViking>().HasOne(r => r.Viking)
.WithMany(g => g.GroupRoles);
builder.Entity<Group>().HasMany(r => r.JoinRequests)
.WithOne(r => r.Group);
builder.Entity<GroupJoinRequest>().HasOne(r => r.Group)
.WithMany(g => g.JoinRequests);
// Rating
builder.Entity<Rating>().HasOne(r => r.Viking)

View File

@ -3,23 +3,33 @@ using System.ComponentModel.DataAnnotations;
namespace sodoff.Model;
// Implementation for EMD, add whatever else if needed
public class Group {
[Key]
public int Id { get; set; }
[Required]
public Guid GroupID { get; set; }
public string Name { get; set; }
public string? Name { get; set; }
public string? Description { get; set; }
public GroupType Type { get; set; }
public string Color { get; set; }
public string? Logo { get; set; }
public string Logo { get; set; }
public string? Color { get; set; }
public string ApiKey { get; set; }
public int Points { get; set; }
public virtual ICollection<Viking> Vikings { get; set; } = null!;
public DateTime CreateDate { get; set; }
public DateTime? LastActiveTime { get; set; }
public uint GameID { get; set; }
public int MaxMemberLimit { get; set; }
public virtual ICollection<GroupViking> Vikings { get; set; } = null!;
public virtual ICollection<GroupJoinRequest> JoinRequests { get; set; } = null!;
}

View File

@ -0,0 +1,15 @@
using System.ComponentModel.DataAnnotations;
namespace sodoff.Model;
public class GroupJoinRequest {
[Key]
public int VikingID { get; set; }
[Key]
public int GroupID { get; set; }
public string? Message { get; set; }
public virtual Viking Viking { get; set; } = null!;
public virtual Group Group { get; set; } = null!;
}

35
src/Model/GroupViking.cs Normal file
View File

@ -0,0 +1,35 @@
using sodoff.Schema;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace sodoff.Model;
public class GroupViking {
[Key]
public int VikingID { get; set; }
[Key]
public int GroupID { get; set; }
public UserRole UserRole { get; set; }
public DateTime JoinDate { get; set; }
public virtual Viking Viking { get; set; } = null!;
public virtual Group Group { get; set; } = null!;
[NotMapped]
public string Name { get { return Group.Name; } }
[NotMapped]
public string? Description { get { return Group.Description; } }
[NotMapped]
public GroupType Type { get { return Group.Type; } }
[NotMapped]
public string Logo { get { return Group.Logo; } }
[NotMapped]
public string Color { get { return Group.Color; } }
[NotMapped]
public uint GameID { get { return Group.GameID; } }
}

View File

@ -39,7 +39,7 @@ public class Viking {
public virtual ICollection<Party> Parties { get; set; } = null!;
public virtual ICollection<MMORole> MMORoles { get; set; } = null!;
public virtual Neighborhood? Neighborhood { get; set; } = null!;
public virtual ICollection<Group> Groups { get; set; } = null!;
public virtual ICollection<GroupViking> GroupRoles { get; set; } = null!;
public virtual ICollection<Rating> Ratings { get; set; } = null!;
public virtual Dragon? SelectedDragon { get; set; }
public virtual ICollection<UserMissionData> UserMissions { get; set; } = null!;

View File

@ -0,0 +1,25 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "AssignRoleRequest", IsNullable = true)]
[Serializable]
public class AssignRoleRequest {
[XmlElement(ElementName = "UserID")]
public string UserID;
[XmlElement(ElementName = "MemberID")]
public string MemberID;
[XmlElement(ElementName = "NewRole")]
public UserRole NewRole;
[XmlElement(ElementName = "GroupID")]
public string GroupID;
[XmlElement(ElementName = "ProductGroupID")]
public int? ProductGroupID;
[XmlElement(ElementName = "ProductID")]
public int? ProductID;
}

View File

@ -0,0 +1,16 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "AssignRoleResult", IsNullable = true)]
[Serializable]
public class AssignRoleResult {
[XmlElement(ElementName = "Success")]
public bool Success;
[XmlElement(ElementName = "InitiatorNewRole", IsNullable = true)]
public UserRole? InitiatorNewRole;
[XmlElement(ElementName = "Status")]
public AssignRoleStatus Status;
}

View File

@ -0,0 +1,18 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
public enum AssignRoleStatus {
[XmlEnum("1")]
Success = 1,
[XmlEnum("2")]
Error,
[XmlEnum("3")]
ApproverNotMemberOfTheGroup,
[XmlEnum("4")]
ApproverHasNoPermission,
[XmlEnum("5")]
MemberAlreadyInTheRole,
[XmlEnum("6")]
MemberNotPartOfTheGroup
}

View File

@ -0,0 +1,25 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "AuthorizeJoinRequest", IsNullable = true)]
[Serializable]
public class AuthorizeJoinRequest {
[XmlElement(ElementName = "Approved")]
public bool Approved;
[XmlElement(ElementName = "JoineeID")]
public string JoineeID;
[XmlElement(ElementName = "UserID")]
public string UserID;
[XmlElement(ElementName = "GroupID")]
public string GroupID;
[XmlElement(ElementName = "ProductGroupID")]
public int? ProductGroupID;
[XmlElement(ElementName = "ProductID")]
public int? ProductID;
}

View File

@ -0,0 +1,13 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "AuthorizeJoinResult", IsNullable = true)]
[Serializable]
public class AuthorizeJoinResult {
[XmlElement(ElementName = "Success")]
public bool Success;
[XmlElement(ElementName = "Status")]
public AuthorizeJoinStatus Status;
}

View File

@ -0,0 +1,24 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
public enum AuthorizeJoinStatus {
[XmlEnum("1")]
Success = 1,
[XmlEnum("2")]
Error,
[XmlEnum("3")]
GroupIsFull,
[XmlEnum("4")]
GroupTypeIsNotPublic,
[XmlEnum("5")]
UserAlreadyMemberOfTheGroup,
[XmlEnum("6")]
GroupTypeIsPublic,
[XmlEnum("7")]
ApproverNotInThisGroup,
[XmlEnum("8")]
ApproverHasNoPermission,
[XmlEnum("9")]
UserHasNoJoinRequest
}

View File

@ -0,0 +1,40 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "CreateGroupRequest", IsNullable = true)]
[Serializable]
public class CreateGroupRequest {
[XmlElement(ElementName = "Name")]
public string Name;
[XmlElement(ElementName = "Description")]
public string Description;
[XmlElement(ElementName = "Type")]
public GroupType Type;
[XmlElement(ElementName = "Logo")]
public string Logo;
[XmlElement(ElementName = "Color")]
public string Color;
[XmlElement(ElementName = "UserID")]
public string UserID;
[XmlElement(ElementName = "DefaultLeaderID")]
public string DefaultLeaderID;
[XmlElement(ElementName = "ParentGroupID")]
public string ParentGroupID;
[XmlElement(ElementName = "ProductGroupID")]
public int? ProductGroupID;
[XmlElement(ElementName = "ProductID")]
public int? ProductID;
[XmlElement(ElementName = "MaxMemberLimit")]
public int? MaxMemberLimit;
}

View File

@ -0,0 +1,16 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "CreateGroupResult", IsNullable = true)]
[Serializable]
public class CreateGroupResult {
[XmlElement(ElementName = "Success")]
public bool Success;
[XmlElement(ElementName = "Status")]
public CreateGroupStatus Status;
[XmlElement(ElementName = "Group")]
public Group Group;
}

View File

@ -0,0 +1,32 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
public enum CreateGroupStatus {
[XmlEnum("1")]
Success = 1,
[XmlEnum("2")]
Error,
[XmlEnum("3")]
GroupNameInvalid,
[XmlEnum("4")]
GroupDescriptionInvalid,
[XmlEnum("5")]
GroupNameIsDuplicate,
[XmlEnum("6")]
GroupOwnerHasInSufficientCurrency,
[XmlEnum("7")]
UnableToGetCreatorDetails,
[XmlEnum("8")]
CreatorIsNotApproved,
[XmlEnum("9")]
GroupNameIsEmpty,
[XmlEnum("10")]
GroupDescriptionIsEmpty,
[XmlEnum("11")]
GroupTypeIsInvalid,
[XmlEnum("12")]
GroupMaxMemberLimitInvalid,
[XmlEnum("13")]
AutomaticItemPurchaseFailed
}

View File

@ -0,0 +1,37 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "EditGroupRequest", IsNullable = true)]
[Serializable]
public class EditGroupRequest {
[XmlElement(ElementName = "GroupID")]
public string GroupID;
[XmlElement(ElementName = "UserID")]
public string UserID;
[XmlElement(ElementName = "Name")]
public string Name;
[XmlElement(ElementName = "Description")]
public string Description;
[XmlElement(ElementName = "Type")]
public GroupType? Type;
[XmlElement(ElementName = "Logo")]
public string Logo;
[XmlElement(ElementName = "Color")]
public string Color;
[XmlElement(ElementName = "ProductGroupID")]
public int? ProductGroupID;
[XmlElement(ElementName = "ProductID")]
public int? ProductID;
[XmlElement(ElementName = "MaxMemberLimit")]
public int? MaxMemberLimit;
}

View File

@ -0,0 +1,16 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "EditGroupResult", IsNullable = true)]
[Serializable]
public class EditGroupResult {
[XmlElement(ElementName = "Success")]
public bool Success;
[XmlElement(ElementName = "Status")]
public EditGroupStatus Status;
[XmlElement(ElementName = "NewRolePermissions", IsNullable = true)]
public List<RolePermission> NewRolePermissions;
}

View File

@ -0,0 +1,28 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
public enum EditGroupStatus {
[XmlEnum("1")]
Success = 1,
[XmlEnum("2")]
Error,
[XmlEnum("3")]
UnableToGetUserDetails,
[XmlEnum("4")]
GroupNameInvalid,
[XmlEnum("5")]
GroupDescriptionInvalid,
[XmlEnum("6")]
GroupNameIsDuplicate,
[XmlEnum("7")]
GroupTypeIsInvalid,
[XmlEnum("8")]
PermissionDenied,
[XmlEnum("9")]
GroupNotFound,
[XmlEnum("10")]
GroupMaxMemberLimitInvalid,
[XmlEnum("11")]
GroupOwnerHasInSufficientCurrency
}

View File

@ -0,0 +1,40 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "GetGroupsRequest", IsNullable = true)]
[Serializable]
public class GetGroupsRequest {
[XmlElement(ElementName = "UserID")]
public string UserID;
[XmlElement(ElementName = "ForUserID")]
public string ForUserID;
[XmlElement(ElementName = "GroupID")]
public Guid? GroupID;
[XmlElement(ElementName = "Name")]
public string Name;
[XmlElement(ElementName = "ProductID")]
public int? ProductID;
[XmlElement(ElementName = "ProductGroupID")]
public int? ProductGroupID;
[XmlElement(ElementName = "IncludeMemberCount")]
public bool IncludeMemberCount;
[XmlElement(ElementName = "IncludeMinFields")]
public bool IncludeMinFields;
[XmlElement(ElementName = "PageNo")]
public int? PageNo;
[XmlElement(ElementName = "PageSize")]
public int? PageSize;
[XmlElement(ElementName = "GroupsFilter")]
public GroupsFilter GroupsFilter;
}

View File

@ -0,0 +1,16 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "GetGroupsResult", IsNullable = true)]
[Serializable]
public class GetGroupsResult {
[XmlElement(ElementName = "Success")]
public bool Success;
[XmlElement(ElementName = "Groups")]
public Group[] Groups;
[XmlElement(ElementName = "RolePermissions", IsNullable = true)]
public List<RolePermission> RolePermissions;
}

View File

@ -0,0 +1,16 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "GetPendingJoinRequest", IsNullable = true)]
[Serializable]
public class GetPendingJoinRequest {
[XmlElement(ElementName = "UserID")]
public string UserID;
[XmlElement(ElementName = "GroupID")]
public string GroupID;
[XmlElement(ElementName = "ProductGroupID")]
public int? ProductGroupID;
}

View File

@ -0,0 +1,14 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "GetPendingJoinResult", IsNullable = true)]
[Serializable]
public class GetPendingJoinResult {
// Token: 0x04000A48 RID: 2632
[XmlElement(ElementName = "Success")]
public bool Success;
[XmlElement(ElementName = "Requests")]
public PendingJoinRequest[] Requests;
}

View File

@ -0,0 +1,16 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
public enum GroupJoinRequestStatus {
[XmlEnum("1")]
Pending = 1,
[XmlEnum("2")]
Approved,
[XmlEnum("3")]
Rejected,
[XmlEnum("4")]
Cancelled,
[XmlEnum("5")]
PendingAccountOwnerRequest
}

View File

@ -0,0 +1,15 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "GroupJoinResult", IsNullable = true)]
[Serializable]
public class GroupJoinResult {
// Token: 0x040009C3 RID: 2499
[XmlElement(ElementName = "Success")]
public bool Success;
// Token: 0x040009C4 RID: 2500
[XmlElement(ElementName = "Status")]
public JoinGroupStatus Status;
}

35
src/Schema/GroupMember.cs Normal file
View File

@ -0,0 +1,35 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "GroupMember", IsNullable = true)]
[Serializable]
public class GroupMember {
[XmlElement(ElementName = "UserID", IsNullable = false)]
public string UserID;
[XmlElement(ElementName = "GroupID", IsNullable = false)]
public string GroupID;
[XmlElement(ElementName = "DisplayName", IsNullable = false)]
public string DisplayName;
[XmlElement(ElementName = "JoinDate")]
public DateTime JoinDate;
[XmlElement(ElementName = "Online")]
public bool Online;
[XmlElement(ElementName = "RoleID", IsNullable = true)]
public int? RoleID;
[XmlElement(ElementName = "Points", IsNullable = true)]
public int? Points;
[XmlElement(ElementName = "Rank", IsNullable = true)]
public int? Rank;
[XmlElement(ElementName = "RankTrend", IsNullable = true)]
public int? RankTrend;
}

View File

@ -0,0 +1,16 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "GroupsFilter", IsNullable = true)]
[Serializable]
public class GroupsFilter {
[XmlElement(ElementName = "GroupType")]
public GroupType? GroupType;
[XmlElement(ElementName = "Locale")]
public string Locale;
[XmlElement(ElementName = "PointTypeID")]
public int? PointTypeID;
}

View File

@ -0,0 +1,31 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "JoinGroupRequest", IsNullable = true)]
[Serializable]
public class JoinGroupRequest {
[XmlElement(ElementName = "UserID")]
public string UserID;
[XmlElement(ElementName = "GroupID")]
public string GroupID;
[XmlElement(ElementName = "ProductGroupID")]
public int? ProductGroupID;
[XmlElement(ElementName = "ProductID")]
public int? ProductID;
[XmlElement(ElementName = "Message")]
public string Message;
[XmlElement(ElementName = "JoinRequestStatus")]
public GroupJoinRequestStatus? JoinRequestStatus;
[XmlElement(ElementName = "JoinByInvite")]
public bool JoinByInvite;
[XmlElement(ElementName = "InviterID")]
public string InviterID;
}

View File

@ -0,0 +1,28 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
public enum JoinGroupStatus {
[XmlEnum("1")]
Success = 1,
[XmlEnum("2")]
Error,
[XmlEnum("3")]
GroupIsFull,
[XmlEnum("4")]
GroupTypeIsNotPublic,
[XmlEnum("5")]
UserAlreadyMemberOfTheGroup,
[XmlEnum("6")]
GroupTypeIsPublic,
[XmlEnum("7")]
MessageInvalid,
[XmlEnum("8")]
JoinRequestPending,
[XmlEnum("9")]
InviteNeededToJoin,
[XmlEnum("10")]
NoValidInvite,
[XmlEnum("11")]
InviterHasNoPermission
}

View File

@ -0,0 +1,19 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "LeaveGroupRequest", IsNullable = true)]
[Serializable]
public class LeaveGroupRequest {
[XmlElement(ElementName = "UserID")]
public string UserID;
[XmlElement(ElementName = "GroupID")]
public string GroupID;
[XmlElement(ElementName = "ProductGroupID")]
public int? ProductGroupID;
[XmlElement(ElementName = "ProductID")]
public int? ProductID;
}

View File

@ -0,0 +1,13 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "LeaveGroupResult", IsNullable = true)]
[Serializable]
public class LeaveGroupResult {
[XmlElement(ElementName = "Success")]
public bool Success;
[XmlElement(ElementName = "Status")]
public LeaveGroupStatus Status;
}

View File

@ -0,0 +1,12 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
public enum LeaveGroupStatus {
[XmlEnum("1")]
Success = 1,
[XmlEnum("2")]
Error,
[XmlEnum("3")]
UserNotAMemberOfTheGroup
}

View File

@ -0,0 +1,22 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "PendingJoinRequest", IsNullable = true)]
[Serializable]
public class PendingJoinRequest {
[XmlElement(ElementName = "UserID")]
public string UserID;
[XmlElement(ElementName = "GroupID")]
public string GroupID;
[XmlElement(ElementName = "FromUserID")]
public string FromUserID;
[XmlElement(ElementName = "Message")]
public string Message;
[XmlElement(ElementName = "StatusID", IsNullable = true)]
public GroupJoinRequestStatus? StatusID;
}

View File

@ -0,0 +1,22 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "RemoveMemberRequest", IsNullable = true)]
[Serializable]
public class RemoveMemberRequest {
[XmlElement(ElementName = "RemoveUserID")]
public string RemoveUserID;
[XmlElement(ElementName = "UserID")]
public string UserID;
[XmlElement(ElementName = "GroupID")]
public string GroupID;
[XmlElement(ElementName = "ProductGroupID")]
public int? ProductGroupID;
[XmlElement(ElementName = "ProductID")]
public int? ProductID;
}

View File

@ -0,0 +1,13 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "RemoveMemberResult", IsNullable = true)]
[Serializable]
public class RemoveMemberResult {
[XmlElement(ElementName = "Success")]
public bool Success;
[XmlElement(ElementName = "Status")]
public RemoveMemberStatus Status;
}

View File

@ -0,0 +1,16 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
public enum RemoveMemberStatus {
[XmlEnum("1")]
Success = 1,
[XmlEnum("2")]
Error,
[XmlEnum("3")]
UserNotAMemberOfTheGroup,
[XmlEnum("4")]
UserHasNoPermission,
[XmlEnum("5")]
InvalidParameters
}

View File

@ -0,0 +1,16 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "RP", IsNullable = true)]
[Serializable]
public class RolePermission {
[XmlElement(ElementName = "G")]
public GroupType GroupType;
[XmlElement(ElementName = "R")]
public UserRole Role;
[XmlElement(ElementName = "P")]
public List<string> Permissions;
}

View File

@ -9,7 +9,7 @@ public class UserProfileGroupData
public string GroupID;
[XmlElement(ElementName = "RoleID", IsNullable = true)]
public int? RoleID;
public UserRole? RoleID;
[XmlElement(ElementName = "TypeID", IsNullable = true)]
public int? TypeID;

12
src/Schema/UserRole.cs Normal file
View File

@ -0,0 +1,12 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
public enum UserRole {
[XmlEnum("1")]
Member = 1,
[XmlEnum("2")]
Elder,
[XmlEnum("3")]
Leader
}