Skip to content

Commit

Permalink
feat: allow disabling of guild and channel caches (#895)
Browse files Browse the repository at this point in the history
  • Loading branch information
braindigitalis authored Sep 27, 2023
1 parent 98f73c9 commit 90f63df
Show file tree
Hide file tree
Showing 23 changed files with 484 additions and 335 deletions.
78 changes: 75 additions & 3 deletions include/dpp/cluster.h

Large diffs are not rendered by default.

32 changes: 32 additions & 0 deletions include/dpp/message.h
Original file line number Diff line number Diff line change
Expand Up @@ -1172,6 +1172,38 @@ struct DPP_EXPORT cache_policy_t {
* @brief Caching policy for roles
*/
cache_policy_setting_t role_policy = cp_aggressive;

/**
* @brief Caching policy for roles
*/
cache_policy_setting_t channel_policy = cp_aggressive;

/**
* @brief Caching policy for roles
*/
cache_policy_setting_t guild_policy = cp_aggressive;
};

/**
* @brief Contains a set of predefined cache policies for use when constructing a dpp::cluster
*/
namespace cache_policy {

/**
* @brief A shortcut constant for all caching enabled for use in dpp::cluster constructor
*/
inline constexpr cache_policy_t cpol_default = { cp_aggressive, cp_aggressive, cp_aggressive, cp_aggressive, cp_aggressive };

/**
* @brief A shortcut constant for a more balanced caching policy for use in dpp::cluster constructor
*/
inline constexpr cache_policy_t cpol_balanced = { cp_lazy, cp_lazy, cp_lazy, cp_aggressive, cp_aggressive };

/**
* @brief A shortcut constant for all caching disabled for use in dpp::cluster constructor
*/
inline constexpr cache_policy_t cpol_none = { cp_none, cp_none, cp_none, cp_none, cp_none };

};

/**
Expand Down
2 changes: 1 addition & 1 deletion src/dpp/discordvoiceclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,8 @@ discord_voice_client::discord_voice_client(dpp::cluster* _cluster, snowflake _ch
: websocket_client(_host.substr(0, _host.find(":")), _host.substr(_host.find(":") + 1, _host.length()), "/?v=4", OP_TEXT),
runner(nullptr),
connect_time(0),
port(0),
mixer(std::make_unique<audio_mixer>()),
port(0),
ssrc(0),
timescale(1000000),
paused(false),
Expand Down
51 changes: 32 additions & 19 deletions src/dpp/events/channel_create.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,28 +38,41 @@ using namespace dpp;
*/
void channel_create::handle(discord_client* client, json &j, const std::string &raw) {
json& d = j["d"];
dpp::channel newchannel;
dpp::channel* c = nullptr;
dpp::guild* g = nullptr;

dpp::channel* c = dpp::find_channel(snowflake_not_null(&d, "id"));
if (!c) {
c = new dpp::channel();
}
c->fill_from_json(&d);
dpp::get_channel_cache()->store(c);
if (c->recipients.size()) {
for (auto & u : c->recipients) {
client->creator->set_dm_channel(u, c->id);
if (client->creator->cache_policy.channel_policy == cp_none) {
newchannel.fill_from_json(&d);
c = &newchannel;
g = dpp::find_guild(c->guild_id);
if (c->recipients.size()) {
for (auto & u : c->recipients) {
client->creator->set_dm_channel(u, c->id);
}
}
}
dpp::guild* g = dpp::find_guild(c->guild_id);
if (g) {
g->channels.push_back(c->id);

if (!client->creator->on_channel_create.empty()) {
dpp::channel_create_t cc(client, raw);
cc.created = c;
cc.creating_guild = g;
client->creator->on_channel_create.call(cc);
} else {
c = dpp::find_channel(snowflake_not_null(&d, "id"));
if (!c) {
c = new dpp::channel();
}
c->fill_from_json(&d);
dpp::get_channel_cache()->store(c);
if (c->recipients.size()) {
for (auto & u : c->recipients) {
client->creator->set_dm_channel(u, c->id);
}
}
g = dpp::find_guild(c->guild_id);
if (g) {
g->channels.push_back(c->id);
}
}
if (!client->creator->on_channel_create.empty()) {
dpp::channel_create_t cc(client, raw);
cc.created = c;
cc.creating_guild = g;
client->creator->on_channel_create.call(cc);
}
}

Expand Down
16 changes: 8 additions & 8 deletions src/dpp/events/channel_delete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,24 +40,24 @@ using namespace dpp;
*/
void channel_delete::handle(discord_client* client, json &j, const std::string &raw) {
json& d = j["d"];
dpp::guild* g = nullptr;
dpp::channel* c = dpp::find_channel(snowflake_not_null(&d, "id"));
if (c) {
dpp::guild* g = dpp::find_guild(c->guild_id);
g = dpp::find_guild(c->guild_id);
if (g) {
auto gc = std::find(g->channels.begin(), g->channels.end(), c->id);
if (gc != g->channels.end()) {
g->channels.erase(gc);
}

if (!client->creator->on_channel_delete.empty()) {
dpp::channel_delete_t cd(client, raw);
cd.deleted = c;
cd.deleting_guild = g;
client->creator->on_channel_delete.call(cd);
}
}
dpp::get_channel_cache()->remove(c);
}
if (!client->creator->on_channel_delete.empty()) {
dpp::channel_delete_t cd(client, raw);
cd.deleted = c;
cd.deleting_guild = g;
client->creator->on_channel_delete.call(cd);
}
}

}};
23 changes: 15 additions & 8 deletions src/dpp/events/channel_update.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,23 @@ using namespace dpp;
*/
void channel_update::handle(discord_client* client, json &j, const std::string &raw) {
json& d = j["d"];
dpp::channel* c = dpp::find_channel(from_string<uint64_t>(d["id"].get<std::string>()));
if (c) {
c->fill_from_json(&d);
if (!client->creator->on_channel_update.empty()) {
dpp::channel_update_t cu(client, raw);
cu.updated = c;
cu.updating_guild = dpp::find_guild(c->guild_id);
client->creator->on_channel_update.call(cu);
channel newchannel;
channel* c = nullptr;
if (client->creator->cache_policy.channel_policy == cp_none) {
newchannel.fill_from_json(&d);
c = &newchannel;
} else {
c = dpp::find_channel(snowflake_not_null(&d, "id"));
if (c) {
c->fill_from_json(&d);
}
}
if (!client->creator->on_channel_update.empty()) {
dpp::channel_update_t cu(client, raw);
cu.updated = c;
cu.updating_guild = dpp::find_guild(c->guild_id);
client->creator->on_channel_update.call(cu);
}
}

}};
165 changes: 89 additions & 76 deletions src/dpp/events/guild_create.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,97 +42,110 @@ using namespace dpp;
*/
void guild_create::handle(discord_client* client, json &j, const std::string &raw) {
json& d = j["d"];
bool newguild = false;
if (snowflake_not_null(&d, "id") == 0)
dpp::guild newguild;
dpp::guild* g = nullptr;

if (snowflake_not_null(&d, "id") == 0) {
/* This shouldnt ever happen, but it has been seen in the wild i guess?
* Either way a guild with invalid or missing ID doesnt want to cause events.
*/
return;
dpp::guild* g = dpp::find_guild(snowflake_not_null(&d, "id"));
if (!g) {
g = new dpp::guild();
newguild = true;
}
g->fill_from_json(client, &d);
g->shard_id = client->shard_id;
if (!g->is_unavailable() && newguild) {
if (client->creator->cache_policy.role_policy != dpp::cp_none) {
/* Store guild roles */
g->roles.clear();
g->roles.reserve(d["roles"].size());
for (auto & role : d["roles"]) {
dpp::role *r = dpp::find_role(snowflake_not_null(&role, "id"));
if (!r) {
r = new dpp::role();

if (client->creator->cache_policy.guild_policy == cp_none) {
newguild.fill_from_json(client, &d);
g = &newguild;
} else {
bool is_new_guild = false;
g = dpp::find_guild(snowflake_not_null(&d, "id"));
if (!g) {
g = new dpp::guild();
is_new_guild = true;
}
g->fill_from_json(client, &d);
g->shard_id = client->shard_id;
if (!g->is_unavailable() && is_new_guild) {
if (client->creator->cache_policy.role_policy != dpp::cp_none) {
/* Store guild roles */
g->roles.clear();
g->roles.reserve(d["roles"].size());
for (auto & role : d["roles"]) {
dpp::role *r = dpp::find_role(snowflake_not_null(&role, "id"));
if (!r) {
r = new dpp::role();
}
r->fill_from_json(g->id, &role);
dpp::get_role_cache()->store(r);
g->roles.push_back(r->id);
}
r->fill_from_json(g->id, &role);
dpp::get_role_cache()->store(r);
g->roles.push_back(r->id);
}
}

/* Store guild channels */
g->channels.clear();
g->channels.reserve(d["channels"].size());
for (auto & channel : d["channels"]) {
dpp::channel* c = dpp::find_channel(snowflake_not_null(&channel, "id"));
if (!c) {
c = new dpp::channel();
/* Store guild channels */
g->channels.clear();
g->channels.reserve(d["channels"].size());
for (auto & channel : d["channels"]) {
dpp::channel* c = dpp::find_channel(snowflake_not_null(&channel, "id"));
if (!c) {
c = new dpp::channel();
}
c->fill_from_json(&channel);
c->guild_id = g->id;
dpp::get_channel_cache()->store(c);
g->channels.push_back(c->id);
}
c->fill_from_json(&channel);
c->guild_id = g->id;
dpp::get_channel_cache()->store(c);
g->channels.push_back(c->id);
}

/* Store guild threads */
g->threads.clear();
g->threads.reserve(d["threads"].size());
for (auto & channel : d["threads"]) {
g->threads.push_back(snowflake_not_null(&channel, "id"));
}
/* Store guild threads */
g->threads.clear();
g->threads.reserve(d["threads"].size());
for (auto & channel : d["threads"]) {
g->threads.push_back(snowflake_not_null(&channel, "id"));
}

/* Store guild members */
if (client->creator->cache_policy.user_policy == cp_aggressive) {
g->members.reserve(d["members"].size());
for (auto & user : d["members"]) {
snowflake userid = snowflake_not_null(&(user["user"]), "id");
/* Only store ones we don't have already otherwise gm will leak */
if (g->members.find(userid) == g->members.end()) {
dpp::user* u = dpp::find_user(userid);
if (!u) {
u = new dpp::user();
u->fill_from_json(&(user["user"]));
dpp::get_user_cache()->store(u);
} else {
u->refcount++;
/* Store guild members */
if (client->creator->cache_policy.user_policy == cp_aggressive) {
g->members.reserve(d["members"].size());
for (auto & user : d["members"]) {
snowflake userid = snowflake_not_null(&(user["user"]), "id");
/* Only store ones we don't have already otherwise gm will leak */
if (g->members.find(userid) == g->members.end()) {
dpp::user* u = dpp::find_user(userid);
if (!u) {
u = new dpp::user();
u->fill_from_json(&(user["user"]));
dpp::get_user_cache()->store(u);
} else {
u->refcount++;
}
dpp::guild_member gm;
gm.fill_from_json(&user, g->id, userid);
g->members[userid] = gm;
}
dpp::guild_member gm;
gm.fill_from_json(&user, g->id, userid);
g->members[userid] = gm;
}
}
}
if (client->creator->cache_policy.emoji_policy != dpp::cp_none) {
/* Store emojis */
g->emojis.reserve(d["emojis"].size());
g->emojis = {};
for (auto & emoji : d["emojis"]) {
dpp::emoji* e = dpp::find_emoji(snowflake_not_null(&emoji, "id"));
if (!e) {
e = new dpp::emoji();
e->fill_from_json(&emoji);
dpp::get_emoji_cache()->store(e);
if (client->creator->cache_policy.emoji_policy != dpp::cp_none) {
/* Store emojis */
g->emojis.reserve(d["emojis"].size());
g->emojis = {};
for (auto & emoji : d["emojis"]) {
dpp::emoji* e = dpp::find_emoji(snowflake_not_null(&emoji, "id"));
if (!e) {
e = new dpp::emoji();
e->fill_from_json(&emoji);
dpp::get_emoji_cache()->store(e);
}
g->emojis.push_back(e->id);
}
g->emojis.push_back(e->id);
}
}
}
dpp::get_guild_cache()->store(g);
if (newguild && g->id && (client->intents & dpp::i_guild_members)) {
if (client->creator->cache_policy.user_policy == cp_aggressive) {
json chunk_req = json({{"op", 8}, {"d", {{"guild_id",std::to_string(g->id)},{"query",""},{"limit",0}}}});
if (client->intents & dpp::i_guild_presences) {
chunk_req["d"]["presences"] = true;
dpp::get_guild_cache()->store(g);
if (is_new_guild && g->id && (client->intents & dpp::i_guild_members)) {
if (client->creator->cache_policy.user_policy == cp_aggressive) {
json chunk_req = json({{"op", 8}, {"d", {{"guild_id",std::to_string(g->id)},{"query",""},{"limit",0}}}});
if (client->intents & dpp::i_guild_presences) {
chunk_req["d"]["presences"] = true;
}
client->queue_message(client->jsonobj_to_string(chunk_req));
}
client->queue_message(client->jsonobj_to_string(chunk_req));
}
}

Expand Down
11 changes: 6 additions & 5 deletions src/dpp/events/guild_delete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,12 @@ void guild_delete::handle(discord_client* client, json &j, const std::string &ra
g->flags |= dpp::g_unavailable;
}

if (!client->creator->on_guild_delete.empty()) {
dpp::guild_delete_t gd(client, raw);
gd.deleted = g;
client->creator->on_guild_delete.call(gd);
}
}

if (!client->creator->on_guild_delete.empty()) {
dpp::guild_delete_t gd(client, raw);
gd.deleted = g;
client->creator->on_guild_delete.call(gd);
}
}

Expand Down
Loading

0 comments on commit 90f63df

Please sign in to comment.