diff --git a/Backend/Remora.Discord.API.Abstractions/API/Objects/Teams/ITeamMember.cs b/Backend/Remora.Discord.API.Abstractions/API/Objects/Teams/ITeamMember.cs
index ef16ccd5fa..b367d977a0 100644
--- a/Backend/Remora.Discord.API.Abstractions/API/Objects/Teams/ITeamMember.cs
+++ b/Backend/Remora.Discord.API.Abstractions/API/Objects/Teams/ITeamMember.cs
@@ -51,4 +51,9 @@ public interface ITeamMember
/// Gets the user that's part of the team.
///
IPartialUser User { get; }
+
+ ///
+ /// Gets the user's role.
+ ///
+ TeamMemberRole Role { get; }
}
diff --git a/Backend/Remora.Discord.API.Abstractions/API/Objects/Teams/TeamMemberRole.cs b/Backend/Remora.Discord.API.Abstractions/API/Objects/Teams/TeamMemberRole.cs
new file mode 100644
index 0000000000..611858f98f
--- /dev/null
+++ b/Backend/Remora.Discord.API.Abstractions/API/Objects/Teams/TeamMemberRole.cs
@@ -0,0 +1,55 @@
+//
+// TeamMemberRole.cs
+//
+// Author:
+// Jarl Gullberg
+//
+// Copyright (c) Jarl Gullberg
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+namespace Remora.Discord.API.Abstractions.Objects;
+
+///
+/// Enumerates various roles a team member can have.
+///
+public enum TeamMemberRole
+{
+ ///
+ /// Owners are the most permissible role, and can take destructive, irreversible actions like deleting team-owned
+ /// apps or the team itself. Teams are limited to 1 owner.
+ ///
+ Owner,
+
+ ///
+ /// Admins have similar access as owners, except they cannot take destructive actions on the team or team-owned
+ /// apps.
+ ///
+ Admin,
+
+ ///
+ /// Developers can access information about team-owned apps, like the client secret or public key. They can also
+ /// take limited actions on team-owned apps, like configuring interaction endpoints or resetting the bot token.
+ /// Members with the Developer role *cannot* manage the team or its members, or take destructive actions on
+ /// team-owned apps.
+ ///
+ Developer,
+
+ ///
+ /// Read-only members can access information about a team and any team-owned apps. Some examples include getting the
+ /// IDs of applications and exporting payout records.
+ ///
+ ReadOnly
+}
diff --git a/Backend/Remora.Discord.API/API/Objects/Teams/TeamMember.cs b/Backend/Remora.Discord.API/API/Objects/Teams/TeamMember.cs
index 8a6b5a6d6b..cba10f1b91 100644
--- a/Backend/Remora.Discord.API/API/Objects/Teams/TeamMember.cs
+++ b/Backend/Remora.Discord.API/API/Objects/Teams/TeamMember.cs
@@ -36,5 +36,6 @@ public record TeamMember
MembershipState MembershipState,
IReadOnlyList Permissions,
Snowflake TeamID,
- IPartialUser User
+ IPartialUser User,
+ TeamMemberRole Role
) : ITeamMember;
diff --git a/Backend/Remora.Discord.API/Extensions/ServiceCollectionExtensions.cs b/Backend/Remora.Discord.API/Extensions/ServiceCollectionExtensions.cs
index d6d45b9f09..d56fa7ebbc 100644
--- a/Backend/Remora.Discord.API/Extensions/ServiceCollectionExtensions.cs
+++ b/Backend/Remora.Discord.API/Extensions/ServiceCollectionExtensions.cs
@@ -1197,7 +1197,8 @@ private static JsonSerializerOptions AddOAuth2ObjectConverters(this JsonSerializ
private static JsonSerializerOptions AddTeamObjectConverters(this JsonSerializerOptions options)
{
options.AddDataObjectConverter();
- options.AddDataObjectConverter();
+ options.AddDataObjectConverter()
+ .WithPropertyConverter(m => m.Role, new StringEnumConverter(new SnakeCaseNamingPolicy()));
return options;
}
diff --git a/Tests/Remora.Discord.Tests/Samples/Objects/APPLICATION/APPLICATION.json b/Tests/Remora.Discord.Tests/Samples/Objects/APPLICATION/APPLICATION.json
index 1770afc53a..62d0fdae0b 100644
--- a/Tests/Remora.Discord.Tests/Samples/Objects/APPLICATION/APPLICATION.json
+++ b/Tests/Remora.Discord.Tests/Samples/Objects/APPLICATION/APPLICATION.json
@@ -27,7 +27,8 @@
"discriminator": "9999",
"id": "999999999999999999",
"username": "none"
- }
+ },
+ "role": "read_only"
}
],
"name": "none",
diff --git a/Tests/Remora.Discord.Tests/Samples/Objects/APPLICATION/APPLICATION.optionals.json b/Tests/Remora.Discord.Tests/Samples/Objects/APPLICATION/APPLICATION.optionals.json
index 58e0f0808c..44497c1265 100644
--- a/Tests/Remora.Discord.Tests/Samples/Objects/APPLICATION/APPLICATION.optionals.json
+++ b/Tests/Remora.Discord.Tests/Samples/Objects/APPLICATION/APPLICATION.optionals.json
@@ -21,7 +21,8 @@
"discriminator": "9999",
"id": "999999999999999999",
"username": "none"
- }
+ },
+ "role": "read_only"
}
],
"name": "none",
diff --git a/Tests/Remora.Discord.Tests/Samples/Objects/INVITE/INVITE.json b/Tests/Remora.Discord.Tests/Samples/Objects/INVITE/INVITE.json
index eba9c17494..a723144730 100644
--- a/Tests/Remora.Discord.Tests/Samples/Objects/INVITE/INVITE.json
+++ b/Tests/Remora.Discord.Tests/Samples/Objects/INVITE/INVITE.json
@@ -41,7 +41,8 @@
"global_name": "none",
"id": "999999999999999999",
"username": "none"
- }
+ },
+ "role": "read_only"
}
],
"name": "none",
diff --git a/Tests/Remora.Discord.Tests/Samples/Objects/INVITE/INVITE.nulls.json b/Tests/Remora.Discord.Tests/Samples/Objects/INVITE/INVITE.nulls.json
index 776a891c96..a46d1d68f9 100644
--- a/Tests/Remora.Discord.Tests/Samples/Objects/INVITE/INVITE.nulls.json
+++ b/Tests/Remora.Discord.Tests/Samples/Objects/INVITE/INVITE.nulls.json
@@ -41,7 +41,8 @@
"global_name": "none",
"id": "999999999999999999",
"username": "none"
- }
+ },
+ "role": "read_only"
}
],
"name": "none",
diff --git a/Tests/Remora.Discord.Tests/Samples/Objects/TEAM/TEAM.json b/Tests/Remora.Discord.Tests/Samples/Objects/TEAM/TEAM.json
index 62f181dc00..95b5d0b7b6 100644
--- a/Tests/Remora.Discord.Tests/Samples/Objects/TEAM/TEAM.json
+++ b/Tests/Remora.Discord.Tests/Samples/Objects/TEAM/TEAM.json
@@ -13,7 +13,8 @@
"discriminator": "9999",
"id": "999999999999999999",
"avatar": "68b329da9893e34099c7d8ad5cb9c940"
- }
+ },
+ "role": "read_only"
}
],
"name": "none",
diff --git a/Tests/Remora.Discord.Tests/Samples/Objects/TEAM/TEAM.nulls.json b/Tests/Remora.Discord.Tests/Samples/Objects/TEAM/TEAM.nulls.json
index 51139709e6..a60eb7d9dd 100644
--- a/Tests/Remora.Discord.Tests/Samples/Objects/TEAM/TEAM.nulls.json
+++ b/Tests/Remora.Discord.Tests/Samples/Objects/TEAM/TEAM.nulls.json
@@ -13,7 +13,8 @@
"discriminator": "9999",
"id": "999999999999999999",
"avatar": "68b329da9893e34099c7d8ad5cb9c940"
- }
+ },
+ "role": "read_only"
}
],
"name": "none",
diff --git a/Tests/Remora.Discord.Tests/Samples/Objects/TEAM_MEMBER/TEAM_MEMBER.json b/Tests/Remora.Discord.Tests/Samples/Objects/TEAM_MEMBER/TEAM_MEMBER.json
index 1276507d1d..2470252fab 100644
--- a/Tests/Remora.Discord.Tests/Samples/Objects/TEAM_MEMBER/TEAM_MEMBER.json
+++ b/Tests/Remora.Discord.Tests/Samples/Objects/TEAM_MEMBER/TEAM_MEMBER.json
@@ -9,5 +9,6 @@
"discriminator": "9999",
"id": "999999999999999999",
"avatar": "68b329da9893e34099c7d8ad5cb9c940"
- }
+ },
+ "role": "read_only"
}