Skip to content

Commit 4832c9e

Browse files
committed
add role permissions
1 parent 6efbe5f commit 4832c9e

12 files changed

+289
-38
lines changed

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ find_package(OpenSSL REQUIRED)
7878
if(VCPKG_TOOLCHAIN)
7979
find_package(unofficial-sodium CONFIG REQUIRED)
8080
find_package(Opus CONFIG REQUIRED)
81-
81+
8282
target_link_libraries(${PROJECT_NAME}
8383
unofficial-sodium::sodium
8484
Opus::opus

Discord.C++/Guild.cpp

+27
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "ChannelHelper.h"
77
#include "Emoji.h"
8+
#include "Exceptions.h"
89
#include "Role.h"
910
#include "VoiceChannel.h"
1011
#include "static.h"
@@ -199,6 +200,32 @@ void DiscordCPP::Guild::unban(const User& user) {
199200
api_call(url, "DEL");
200201
}
201202

203+
DiscordCPP::Permissions DiscordCPP::Guild::get_member_permissions(const Member& member) {
204+
if (owner_id.has_value() && owner_id.value() == member.get_id()) {
205+
return Permissions::All();
206+
}
207+
208+
std::map<std::string, Permissions> permission_map;
209+
for (const Role& role : roles) {
210+
permission_map.insert({role.get_id(), role.get_permissions()});
211+
}
212+
213+
Permissions permissions;
214+
for (std::string role : member.get_roles()) {
215+
if (permission_map.find(role) == permission_map.end()) {
216+
throw DiscordException("unknown role " + role + " for member " + member.get_id() + " in guild " + get_id());
217+
}
218+
219+
if (permission_map.at(role).has_permission(Permissions::ADMINISTRATOR)) {
220+
return Permissions::All();
221+
}
222+
223+
permissions.add(permission_map.at(role));
224+
}
225+
226+
return permissions;
227+
}
228+
202229
std::optional<DiscordCPP::User> DiscordCPP::Guild::get_owner() {
203230
if (!owner.has_value() && owner_id.has_value()) {
204231
owner.emplace(owner_id.value(), get_token());

Discord.C++/Guild.h

+4
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,10 @@ class Guild : public DiscordObject {
150150
/// unbans the given User from this Guild
151151
DLL_EXPORT void unban(const User& user);
152152

153+
/** @return the members permissions in the guild
154+
@throws DiscordException if an unknown role is encountered */
155+
DLL_EXPORT Permissions get_member_permissions(const Member& member);
156+
153157
/// @return the guild's name
154158
DLL_EXPORT std::string get_name() { return name; }
155159
/// @return the guild's icon hash

Discord.C++/Interaction.cpp

+23-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "Interaction.h"
22

33
#include "Embed.h"
4+
#include "Guild.h"
45

56
DiscordCPP::Interaction::Interaction(const json& data, const std::string& token)
67
: DiscordCPP::DiscordObject(token, data.at("id").get<std::string>()),
@@ -26,6 +27,19 @@ DiscordCPP::Interaction::Interaction(const json& data, const std::string& token)
2627
guild_locale = get_optional<std::string>(data, "guild_locale");
2728
}
2829

30+
DiscordCPP::Interaction::Interaction(const Interaction& old)
31+
: DiscordCPP::DiscordObject(old) {
32+
if (old.guild != nullptr) {
33+
guild = new Guild(*old.guild);
34+
}
35+
}
36+
37+
DiscordCPP::Interaction::~Interaction() {
38+
if (guild != nullptr) {
39+
delete guild;
40+
}
41+
}
42+
2943
void DiscordCPP::Interaction::reply(const std::string& content, const bool tts) {
3044
std::string url = "/interactions/" + get_id() + "/" + token + "/callback";
3145

@@ -37,8 +51,8 @@ void DiscordCPP::Interaction::reply(const std::string& content, const bool tts)
3751
//
3852
{"content", content},
3953
{"tts", tts} //
40-
} //
41-
} //
54+
} //
55+
} //
4256
};
4357

4458
api_call(url, "POST", data, "application/json");
@@ -74,3 +88,10 @@ void DiscordCPP::Interaction::update_reply(Embed embed) {
7488

7589
api_call(url, "PATCH", data, "application/json");
7690
}
91+
92+
std::optional<DiscordCPP::Guild> DiscordCPP::Interaction::get_guild() {
93+
if (guild_id.has_value() && guild == nullptr) {
94+
guild = new Guild(nullptr, guild_id.value(), get_token());
95+
}
96+
return (guild != nullptr) ? std::optional<Guild>{*guild} : std::nullopt;
97+
}

Discord.C++/Interaction.h

+17-10
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
namespace DiscordCPP {
1111

12+
class Guild;
13+
1214
class Interaction : public DiscordObject {
1315
public:
1416
enum Type {
@@ -31,6 +33,7 @@ class Interaction : public DiscordObject {
3133
std::optional<InteractionData> data;
3234
/// The guild the interaction was sent from.
3335
std::optional<std::string> guild_id;
36+
Guild* guild = nullptr;
3437
/// The channel the interaction was sent from.
3538
std::optional<std::string> channel_id;
3639
/// The member that sent the interaction.
@@ -46,6 +49,8 @@ class Interaction : public DiscordObject {
4649

4750
public:
4851
DLL_EXPORT Interaction(const json& data, const std::string& token);
52+
DLL_EXPORT Interaction(const Interaction& old);
53+
DLL_EXPORT ~Interaction();
4954

5055
/// Send a Message as a reply to this interaction.
5156
DLL_EXPORT void reply(const std::string& content, const bool tts = false);
@@ -58,25 +63,27 @@ class Interaction : public DiscordObject {
5863
DLL_EXPORT void update_reply(Embed embed);
5964

6065
/// @return ID of the application this interaction is for.
61-
DLL_EXPORT std::string get_application_id() { return application_id; }
66+
DLL_EXPORT std::string get_application_id() const { return application_id; }
6267
/// @return The type of the invoked command.
63-
DLL_EXPORT Type get_type() { return type; }
68+
DLL_EXPORT Type get_type() const { return type; }
6469
/// @return The command data payload.
65-
DLL_EXPORT std::optional<InteractionData> get_data() { return data; }
70+
DLL_EXPORT std::optional<InteractionData> get_data() const { return data; }
71+
/// @return The guild the interaction was sent from.
72+
DLL_EXPORT std::optional<std::string> get_guild_id() const { return guild_id; }
6673
/// @return The guild the interaction was sent from.
67-
DLL_EXPORT std::optional<std::string> get_guild_id() { return guild_id; }
74+
DLL_EXPORT std::optional<DiscordCPP::Guild> get_guild();
6875
/// @return The channel the interaction was sent from.
69-
DLL_EXPORT std::optional<std::string> get_channel_id() { return channel_id; }
76+
DLL_EXPORT std::optional<std::string> get_channel_id() const { return channel_id; }
7077
/// @return The member that sent the interaction.
71-
DLL_EXPORT std::optional<Member> get_member() { return member; }
78+
DLL_EXPORT std::optional<Member> get_member() const { return member; }
7279
/// @return The user that sent the interaction.
73-
DLL_EXPORT std::optional<User> get_user() { return user; }
80+
DLL_EXPORT std::optional<User> get_user() const { return user; }
7481
/// @return For components, the message they were attached to.
75-
DLL_EXPORT std::optional<Message> get_message() { return message; }
82+
DLL_EXPORT std::optional<Message> get_message() const { return message; }
7683
/// @return The selected locale of the user who sent this interaction.
77-
DLL_EXPORT std::optional<std::string> get_locale() { return locale; }
84+
DLL_EXPORT std::optional<std::string> get_locale() const { return locale; }
7885
/// @return The guild's preferred locale.
79-
DLL_EXPORT std::optional<std::string> get_guild_locale() { return guild_locale; }
86+
DLL_EXPORT std::optional<std::string> get_guild_locale() const { return guild_locale; }
8087
};
8188

8289
} // namespace DiscordCPP

Discord.C++/Member.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
#include "Member.h"
22

33
DiscordCPP::Member::Member(const json& data, const std::string& token) : User(data.at("user"), token) {
4-
nick = get_or_else<std::string>(data, "nick", "");
54
nick = get_or_else<std::string>(data, "nick", "");
65
deaf = get_or_else<bool>(data, "deaf", false);
76
mute = get_or_else<bool>(data, "mute", false);
8-
// roles
7+
8+
if (has_value(data, "roles")) {
9+
for (const json& role : data.at("roles")) {
10+
role_ids.push_back(role.get<std::string>());
11+
}
12+
}
913
}
1014

1115
DiscordCPP::Member::operator std::string() {

Discord.C++/Member.h

+12-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#pragma once
2-
#include <iostream>
32

43
#include "User.h"
54
#include "static.h"
@@ -10,7 +9,8 @@ class Member : public User {
109
private:
1110
/// the member's nickname
1211
std::string nick;
13-
// vector<Role> roles;
12+
/// the member's roles
13+
std::vector<std::string> role_ids;
1414
/// when the member joined the server
1515
std::string joined_at; // ISO8601 timestamp
1616
/// true, if the member is defeaned
@@ -25,14 +25,16 @@ class Member : public User {
2525
///@return Nickname (Username if not present) as std::string
2626
DLL_EXPORT explicit operator std::string() override;
2727

28-
/// the member's nickname
29-
DLL_EXPORT std::string get_nick() { return nick; }
30-
/// when the member joined the server
31-
DLL_EXPORT std::string get_joined_at() { return joined_at; }
32-
/// true, if the member is defeaned
33-
DLL_EXPORT bool is_deaf() { return deaf; }
34-
/// true, if the member is muted
35-
DLL_EXPORT bool is_mute() { return mute; }
28+
/// @return the member's nickname
29+
DLL_EXPORT std::string get_nick() const { return nick; }
30+
/// @return the member's roles
31+
DLL_EXPORT std::vector<std::string> get_roles() const { return role_ids; }
32+
/// @return when the member joined the server
33+
DLL_EXPORT std::string get_joined_at() const { return joined_at; }
34+
/// @return true, if the member is defeaned
35+
DLL_EXPORT bool is_deaf() const { return deaf; }
36+
/// @return true, if the member is muted
37+
DLL_EXPORT bool is_mute() const { return mute; }
3638
};
3739

3840
} // namespace DiscordCPP

Discord.C++/Permissions.cpp

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#include "Permissions.h"
2+
3+
DiscordCPP::Permissions DiscordCPP::Permissions::All() {
4+
Permissions permissions;
5+
permissions.permissions = UINT64_MAX;
6+
return permissions;
7+
}
8+
9+
DiscordCPP::Permissions::Permissions(const std::string& permissions) {
10+
std::istringstream iss(permissions);
11+
iss.exceptions(std::ios::failbit | std::ios::badbit);
12+
iss >> this->permissions;
13+
}
14+
15+
void DiscordCPP::Permissions::add(const Permission& permission) {
16+
permissions |= (1 << permission);
17+
}
18+
19+
void DiscordCPP::Permissions::add(const Permissions& permissions) {
20+
this->permissions |= permissions.permissions;
21+
}
22+
23+
bool DiscordCPP::Permissions::has_permission(Permission permission) {
24+
return permissions & (1 << permission);
25+
}
26+
27+
bool DiscordCPP::Permissions::has_all_permissions(std::vector<Permission> permissions) {
28+
for (auto permission : permissions) {
29+
if (!has_permission(permission)) {
30+
return false;
31+
}
32+
}
33+
return true;
34+
}
35+
36+
bool DiscordCPP::Permissions::has_any_permission(std::vector<Permission> permissions) {
37+
for (auto permission : permissions) {
38+
if (has_permission(permission)) {
39+
return true;
40+
}
41+
}
42+
return false;
43+
}

0 commit comments

Comments
 (0)