forked from OpenGamers/abaddon
add bans to guild settings, tweak some other things
This commit is contained in:
parent
5d1db982cb
commit
a010aa11a5
20
css/main.css
20
css/main.css
@ -175,13 +175,31 @@
|
||||
.app-window button {
|
||||
background: @secondary_color;
|
||||
color: @text_color;
|
||||
border: 1px solid #1c2e40;
|
||||
text-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.app-window button:checked {
|
||||
border-top: 0px;
|
||||
border-left: 0px;
|
||||
border-right: 0px;
|
||||
border-bottom: 3px solid #39a2ed;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.app-window button:not(:checked) {
|
||||
border: 3px #0000ff;
|
||||
}
|
||||
|
||||
.app-window.background {
|
||||
background: @background_color;
|
||||
}
|
||||
|
||||
.app-window treeview {
|
||||
color: @text_color;
|
||||
background: @secondary_color;
|
||||
}
|
||||
|
||||
.app-window listbox {
|
||||
background: @background_color;
|
||||
}
|
||||
|
6
discord/ban.cpp
Normal file
6
discord/ban.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include "ban.hpp"
|
||||
|
||||
void from_json(const nlohmann::json &j, BanData &m) {
|
||||
JS_N("reason", m.Reason);
|
||||
JS_D("user", m.User);
|
||||
}
|
10
discord/ban.hpp
Normal file
10
discord/ban.hpp
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include "user.hpp"
|
||||
|
||||
struct BanData {
|
||||
std::string Reason; // null
|
||||
UserData User; // access id
|
||||
|
||||
friend void from_json(const nlohmann::json &j, BanData &m);
|
||||
};
|
@ -179,6 +179,10 @@ std::optional<GuildMember> DiscordClient::GetMember(Snowflake user_id, Snowflake
|
||||
return m_store.GetGuildMember(guild_id, user_id);
|
||||
}
|
||||
|
||||
std::optional<BanData> DiscordClient::GetBan(Snowflake guild_id, Snowflake user_id) const {
|
||||
return m_store.GetBan(guild_id, user_id);
|
||||
}
|
||||
|
||||
std::optional<PermissionOverwrite> DiscordClient::GetPermissionOverwrite(Snowflake channel_id, Snowflake id) const {
|
||||
return m_store.GetPermissionOverwrite(channel_id, id);
|
||||
}
|
||||
@ -467,6 +471,49 @@ void DiscordClient::SetGuildIcon(Snowflake id, const std::string &data, sigc::sl
|
||||
});
|
||||
}
|
||||
|
||||
void DiscordClient::UnbanUser(Snowflake guild_id, Snowflake user_id) {
|
||||
UnbanUser(guild_id, user_id, [](const auto) {});
|
||||
}
|
||||
|
||||
void DiscordClient::UnbanUser(Snowflake guild_id, Snowflake user_id, sigc::slot<void(bool success)> callback) {
|
||||
sigc::signal<void, bool> signal;
|
||||
signal.connect(callback);
|
||||
m_http.MakeDELETE("/guilds/" + std::to_string(guild_id) + "/bans/" + std::to_string(user_id), [this, callback](const cpr::Response &response) {
|
||||
callback(response.status_code == 204);
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<BanData> DiscordClient::GetBansInGuild(Snowflake guild_id) {
|
||||
return m_store.GetBans(guild_id);
|
||||
}
|
||||
|
||||
void DiscordClient::FetchGuildBan(Snowflake guild_id, Snowflake user_id, sigc::slot<void(BanData)> callback) {
|
||||
sigc::signal<void, BanData> signal;
|
||||
signal.connect(callback);
|
||||
m_http.MakeGET("/guilds/" + std::to_string(guild_id) + "/bans/" + std::to_string(user_id), [this, callback, guild_id](const cpr::Response &response) {
|
||||
if (response.status_code != 200) return;
|
||||
auto ban = nlohmann::json::parse(response.text).get<BanData>();
|
||||
m_store.SetBan(guild_id, ban.User.ID, ban);
|
||||
m_store.SetUser(ban.User.ID, ban.User);
|
||||
callback(ban);
|
||||
});
|
||||
}
|
||||
|
||||
void DiscordClient::FetchGuildBans(Snowflake guild_id, sigc::slot<void(std::vector<BanData>)> callback) {
|
||||
sigc::signal<void, std::vector<BanData>> signal;
|
||||
signal.connect(callback);
|
||||
m_http.MakeGET("/guilds/" + std::to_string(guild_id) + "/bans", [this, callback, guild_id](const cpr::Response &response) {
|
||||
auto bans = nlohmann::json::parse(response.text).get<std::vector<BanData>>();
|
||||
m_store.BeginTransaction();
|
||||
for (const auto &ban : bans) {
|
||||
m_store.SetBan(guild_id, ban.User.ID, ban);
|
||||
m_store.SetUser(ban.User.ID, ban.User);
|
||||
}
|
||||
m_store.EndTransaction();
|
||||
callback(bans);
|
||||
});
|
||||
}
|
||||
|
||||
void DiscordClient::UpdateToken(std::string token) {
|
||||
if (!IsStarted()) {
|
||||
m_token = token;
|
||||
@ -623,6 +670,12 @@ void DiscordClient::HandleGatewayMessage(std::string str) {
|
||||
case GatewayEvent::TYPING_START: {
|
||||
HandleGatewayTypingStart(m);
|
||||
} break;
|
||||
case GatewayEvent::GUILD_BAN_REMOVE: {
|
||||
HandleGatewayGuildBanRemove(m);
|
||||
} break;
|
||||
case GatewayEvent::GUILD_BAN_ADD: {
|
||||
HandleGatewayGuildBanAdd(m);
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
@ -724,7 +777,7 @@ void DiscordClient::HandleGatewayMessageDeleteBulk(const GatewayMessage &msg) {
|
||||
for (const auto &id : data.IDs) {
|
||||
auto cur = m_store.GetMessage(id);
|
||||
if (!cur.has_value())
|
||||
return;
|
||||
continue;
|
||||
|
||||
cur->SetDeleted();
|
||||
m_store.SetMessage(id, *cur);
|
||||
@ -930,6 +983,23 @@ void DiscordClient::HandleGatewayTypingStart(const GatewayMessage &msg) {
|
||||
m_signal_typing_start.emit(data.UserID, data.ChannelID);
|
||||
}
|
||||
|
||||
void DiscordClient::HandleGatewayGuildBanRemove(const GatewayMessage &msg) {
|
||||
GuildBanRemoveObject data = msg.Data;
|
||||
m_store.SetUser(data.User.ID, data.User);
|
||||
m_store.ClearBan(data.GuildID, data.User.ID);
|
||||
m_signal_guild_ban_remove.emit(data.GuildID, data.User.ID);
|
||||
}
|
||||
|
||||
void DiscordClient::HandleGatewayGuildBanAdd(const GatewayMessage &msg) {
|
||||
GuildBanAddObject data = msg.Data;
|
||||
BanData ban;
|
||||
ban.Reason = "";
|
||||
ban.User = data.User;
|
||||
m_store.SetUser(data.User.ID, data.User);
|
||||
m_store.SetBan(data.GuildID, data.User.ID, ban);
|
||||
m_signal_guild_ban_add.emit(data.GuildID, data.User.ID);
|
||||
}
|
||||
|
||||
void DiscordClient::HandleGatewayReconnect(const GatewayMessage &msg) {
|
||||
m_signal_disconnected.emit(true);
|
||||
inflateEnd(&m_zstream);
|
||||
@ -1151,6 +1221,8 @@ void DiscordClient::LoadEventMap() {
|
||||
m_event_map["CHANNEL_RECIPIENT_ADD"] = GatewayEvent::CHANNEL_RECIPIENT_ADD;
|
||||
m_event_map["CHANNEL_RECIPIENT_REMOVE"] = GatewayEvent::CHANNEL_RECIPIENT_REMOVE;
|
||||
m_event_map["TYPING_START"] = GatewayEvent::TYPING_START;
|
||||
m_event_map["GUILD_BAN_REMOVE"] = GatewayEvent::GUILD_BAN_REMOVE;
|
||||
m_event_map["GUILD_BAN_ADD"] = GatewayEvent::GUILD_BAN_ADD;
|
||||
}
|
||||
|
||||
DiscordClient::type_signal_gateway_ready DiscordClient::signal_gateway_ready() {
|
||||
@ -1232,3 +1304,11 @@ DiscordClient::type_signal_typing_start DiscordClient::signal_typing_start() {
|
||||
DiscordClient::type_signal_guild_member_update DiscordClient::signal_guild_member_update() {
|
||||
return m_signal_guild_member_update;
|
||||
}
|
||||
|
||||
DiscordClient::type_signal_guild_ban_remove DiscordClient::signal_guild_ban_remove() {
|
||||
return m_signal_guild_ban_remove;
|
||||
}
|
||||
|
||||
DiscordClient::type_signal_guild_ban_add DiscordClient::signal_guild_ban_add() {
|
||||
return m_signal_guild_ban_add;
|
||||
}
|
||||
|
@ -86,6 +86,7 @@ public:
|
||||
std::optional<RoleData> GetRole(Snowflake id) const;
|
||||
std::optional<GuildData> GetGuild(Snowflake id) const;
|
||||
std::optional<GuildMember> GetMember(Snowflake user_id, Snowflake guild_id) const;
|
||||
std::optional<BanData> GetBan(Snowflake guild_id, Snowflake user_id) const;
|
||||
Snowflake GetMemberHoistedRole(Snowflake guild_id, Snowflake user_id, bool with_color = false) const;
|
||||
Snowflake GetMemberHighestRole(Snowflake guild_id, Snowflake user_id) const;
|
||||
std::unordered_set<Snowflake> GetUsersInGuild(Snowflake id) const;
|
||||
@ -114,6 +115,13 @@ public:
|
||||
void SetGuildName(Snowflake id, const Glib::ustring &name, sigc::slot<void(bool success)> callback);
|
||||
void SetGuildIcon(Snowflake id, const std::string &data);
|
||||
void SetGuildIcon(Snowflake id, const std::string &data, sigc::slot<void(bool success)> callback);
|
||||
void UnbanUser(Snowflake guild_id, Snowflake user_id);
|
||||
void UnbanUser(Snowflake guild_id, Snowflake user_id, sigc::slot<void(bool success)> callback);
|
||||
|
||||
// FetchGuildBans fetches all bans+reasons via api, this func fetches stored bans (so usually just GUILD_BAN_ADD data)
|
||||
std::vector<BanData> GetBansInGuild(Snowflake guild_id);
|
||||
void FetchGuildBan(Snowflake guild_id, Snowflake user_id, sigc::slot<void(BanData)> callback);
|
||||
void FetchGuildBans(Snowflake guild_id, sigc::slot<void(std::vector<BanData>)> callback);
|
||||
|
||||
void UpdateToken(std::string token);
|
||||
void SetUserAgent(std::string agent);
|
||||
@ -151,6 +159,8 @@ private:
|
||||
void HandleGatewayChannelRecipientAdd(const GatewayMessage &msg);
|
||||
void HandleGatewayChannelRecipientRemove(const GatewayMessage &msg);
|
||||
void HandleGatewayTypingStart(const GatewayMessage &msg);
|
||||
void HandleGatewayGuildBanRemove(const GatewayMessage &msg);
|
||||
void HandleGatewayGuildBanAdd(const GatewayMessage &msg);
|
||||
void HandleGatewayReconnect(const GatewayMessage &msg);
|
||||
void HeartbeatThread();
|
||||
void SendIdentify();
|
||||
@ -217,9 +227,11 @@ public:
|
||||
typedef sigc::signal<void, Snowflake> type_signal_role_delete;
|
||||
typedef sigc::signal<void, Snowflake, Glib::ustring> type_signal_reaction_add;
|
||||
typedef sigc::signal<void, Snowflake, Glib::ustring> type_signal_reaction_remove;
|
||||
typedef sigc::signal<void, Snowflake, Snowflake> type_signal_typing_start; // user id, channel id
|
||||
typedef sigc::signal<void, Snowflake, Snowflake> type_signal_typing_start; // user id, channel id
|
||||
typedef sigc::signal<void, Snowflake, Snowflake> type_signal_guild_member_update; // guild id, user id
|
||||
typedef sigc::signal<void, bool> type_signal_disconnected; // bool true if reconnecting
|
||||
typedef sigc::signal<void, Snowflake, Snowflake> type_signal_guild_ban_remove; // guild id, user id
|
||||
typedef sigc::signal<void, Snowflake, Snowflake> type_signal_guild_ban_add; // guild id, user id
|
||||
typedef sigc::signal<void, bool> type_signal_disconnected; // bool true if reconnecting
|
||||
typedef sigc::signal<void> type_signal_connected;
|
||||
|
||||
type_signal_gateway_ready signal_gateway_ready();
|
||||
@ -240,6 +252,8 @@ public:
|
||||
type_signal_reaction_remove signal_reaction_remove();
|
||||
type_signal_typing_start signal_typing_start();
|
||||
type_signal_guild_member_update signal_guild_member_update();
|
||||
type_signal_guild_ban_remove signal_guild_ban_remove();
|
||||
type_signal_guild_ban_add signal_guild_ban_add();
|
||||
type_signal_disconnected signal_disconnected();
|
||||
type_signal_connected signal_connected();
|
||||
|
||||
@ -262,6 +276,8 @@ protected:
|
||||
type_signal_reaction_remove m_signal_reaction_remove;
|
||||
type_signal_typing_start m_signal_typing_start;
|
||||
type_signal_guild_member_update m_signal_guild_member_update;
|
||||
type_signal_guild_ban_remove m_signal_guild_ban_remove;
|
||||
type_signal_guild_ban_add m_signal_guild_ban_add;
|
||||
type_signal_disconnected m_signal_disconnected;
|
||||
type_signal_connected m_signal_connected;
|
||||
};
|
||||
|
@ -252,3 +252,13 @@ void to_json(nlohmann::json &j, const ModifyGuildObject &m) {
|
||||
JS_IF("name", m.Name);
|
||||
JS_IF("icon", m.IconData);
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json &j, GuildBanRemoveObject &m) {
|
||||
JS_D("guild_id", m.GuildID);
|
||||
JS_D("user", m.User);
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json &j, GuildBanAddObject &m) {
|
||||
JS_D("guild_id", m.GuildID);
|
||||
JS_D("user", m.User);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "emoji.hpp"
|
||||
#include "activity.hpp"
|
||||
#include "sticker.hpp"
|
||||
#include "ban.hpp"
|
||||
|
||||
// most stuff below should just be objects that get processed and thrown away immediately
|
||||
|
||||
@ -54,6 +55,8 @@ enum class GatewayEvent : int {
|
||||
CHANNEL_RECIPIENT_ADD,
|
||||
CHANNEL_RECIPIENT_REMOVE,
|
||||
TYPING_START,
|
||||
GUILD_BAN_REMOVE,
|
||||
GUILD_BAN_ADD,
|
||||
};
|
||||
|
||||
struct GatewayMessage {
|
||||
@ -353,3 +356,17 @@ struct ModifyGuildObject {
|
||||
|
||||
friend void to_json(nlohmann::json &j, const ModifyGuildObject &m);
|
||||
};
|
||||
|
||||
struct GuildBanRemoveObject {
|
||||
Snowflake GuildID;
|
||||
UserData User;
|
||||
|
||||
friend void from_json(const nlohmann::json &j, GuildBanRemoveObject &m);
|
||||
};
|
||||
|
||||
struct GuildBanAddObject {
|
||||
Snowflake GuildID;
|
||||
UserData User;
|
||||
|
||||
friend void from_json(const nlohmann::json &j, GuildBanAddObject &m);
|
||||
};
|
||||
|
@ -51,6 +51,15 @@ bool Store::IsValid() const {
|
||||
return m_db_err == SQLITE_OK;
|
||||
}
|
||||
|
||||
void Store::SetBan(Snowflake guild_id, Snowflake user_id, const BanData &ban) {
|
||||
Bind(m_set_ban_stmt, 1, guild_id);
|
||||
Bind(m_set_ban_stmt, 2, user_id);
|
||||
Bind(m_set_ban_stmt, 3, ban.Reason);
|
||||
|
||||
if (!RunInsert(m_set_ban_stmt))
|
||||
fprintf(stderr, "ban insert failed: %s\n", sqlite3_errstr(m_db_err));
|
||||
}
|
||||
|
||||
void Store::SetChannel(Snowflake id, const ChannelData &chan) {
|
||||
Bind(m_set_chan_stmt, 1, id);
|
||||
Bind(m_set_chan_stmt, 2, static_cast<int>(chan.Type));
|
||||
@ -273,6 +282,41 @@ void Store::SetUser(Snowflake id, const UserData &user) {
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<BanData> Store::GetBan(Snowflake guild_id, Snowflake user_id) const {
|
||||
Bind(m_get_ban_stmt, 1, guild_id);
|
||||
Bind(m_get_ban_stmt, 2, user_id);
|
||||
if (!FetchOne(m_get_ban_stmt)) {
|
||||
if (m_db_err != SQLITE_DONE)
|
||||
fprintf(stderr, "error while fetching ban: %s\n", sqlite3_errstr(m_db_err));
|
||||
Reset(m_get_ban_stmt);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
BanData ret;
|
||||
ret.User.ID = user_id;
|
||||
Get(m_get_ban_stmt, 2, ret.Reason);
|
||||
|
||||
Reset(m_get_ban_stmt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<BanData> Store::GetBans(Snowflake guild_id) const {
|
||||
Bind(m_get_bans_stmt, 1, guild_id);
|
||||
|
||||
std::vector<BanData> ret;
|
||||
while (FetchOne(m_get_bans_stmt)) {
|
||||
auto &ban = ret.emplace_back();
|
||||
Get(m_get_bans_stmt, 1, ban.User.ID);
|
||||
Get(m_get_bans_stmt, 2, ban.Reason);
|
||||
}
|
||||
|
||||
Reset(m_get_bans_stmt);
|
||||
|
||||
if (m_db_err != SQLITE_DONE)
|
||||
fprintf(stderr, "error while fetching bans: %s\n", sqlite3_errstr(m_db_err));
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::optional<ChannelData> Store::GetChannel(Snowflake id) const {
|
||||
Bind(m_get_chan_stmt, 1, id);
|
||||
if (!FetchOne(m_get_chan_stmt)) {
|
||||
@ -595,6 +639,16 @@ void Store::ClearChannel(Snowflake id) {
|
||||
m_channels.erase(id);
|
||||
}
|
||||
|
||||
void Store::ClearBan(Snowflake guild_id, Snowflake user_id) {
|
||||
Bind(m_clear_ban_stmt, 1, guild_id);
|
||||
Bind(m_clear_ban_stmt, 2, user_id);
|
||||
|
||||
if ((m_db_err = sqlite3_step(m_clear_ban_stmt)) != SQLITE_DONE)
|
||||
printf("clearing ban failed: %s\n", sqlite3_errstr(m_db_err));
|
||||
|
||||
Reset(m_clear_ban_stmt);
|
||||
}
|
||||
|
||||
const std::unordered_set<Snowflake> &Store::GetChannels() const {
|
||||
return m_channels;
|
||||
}
|
||||
@ -779,6 +833,15 @@ bool Store::CreateTables() {
|
||||
)
|
||||
)";
|
||||
|
||||
constexpr const char *create_bans = R"(
|
||||
CREATE TABLE IF NOT EXISTS bans (
|
||||
guild_id INTEGER NOT NULL,
|
||||
user_id INTEGER NOT NULL,
|
||||
reason TEXT,
|
||||
PRIMARY KEY(user_id, guild_id)
|
||||
)
|
||||
)";
|
||||
|
||||
m_db_err = sqlite3_exec(m_db, create_users, nullptr, nullptr, nullptr);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "failed to create user table: %s\n", sqlite3_errstr(m_db_err));
|
||||
@ -827,6 +890,12 @@ bool Store::CreateTables() {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_db_err = sqlite3_exec(m_db, create_bans, nullptr, nullptr, nullptr);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "failed to create bans table: %s\n", sqlite3_errstr(m_db_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -911,6 +980,24 @@ bool Store::CreateStatements() {
|
||||
SELECT * FROM channels WHERE id = ?
|
||||
)";
|
||||
|
||||
constexpr const char *set_ban = R"(
|
||||
REPLACE INTO bans VALUES (
|
||||
?, ?, ?
|
||||
)
|
||||
)";
|
||||
|
||||
constexpr const char *get_ban = R"(
|
||||
SELECT * FROM bans WHERE guild_id = ? AND user_id = ?
|
||||
)";
|
||||
|
||||
constexpr const char *clear_ban = R"(
|
||||
DELETE FROM bans WHERE guild_id = ? AND user_id = ?
|
||||
)";
|
||||
|
||||
constexpr const char *get_bans = R"(
|
||||
SELECT * FROM bans WHERE guild_id = ?
|
||||
)";
|
||||
|
||||
m_db_err = sqlite3_prepare_v2(m_db, set_user, -1, &m_set_user_stmt, nullptr);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "failed to prepare set user statement: %s\n", sqlite3_errstr(m_db_err));
|
||||
@ -1007,6 +1094,30 @@ bool Store::CreateStatements() {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_db_err = sqlite3_prepare_v2(m_db, set_ban, -1, &m_set_ban_stmt, nullptr);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "failed to prepare set ban statement: %s\n", sqlite3_errstr(m_db_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_db_err = sqlite3_prepare_v2(m_db, get_ban, -1, &m_get_ban_stmt, nullptr);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "failed to prepare get ban statement: %s\n", sqlite3_errstr(m_db_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_db_err = sqlite3_prepare_v2(m_db, clear_ban, -1, &m_clear_ban_stmt, nullptr);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "failed to prepare clear ban statement: %s\n", sqlite3_errstr(m_db_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_db_err = sqlite3_prepare_v2(m_db, get_bans, -1, &m_get_bans_stmt, nullptr);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "failed to prepare get bans statement: %s\n", sqlite3_errstr(m_db_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1027,6 +1138,10 @@ void Store::Cleanup() {
|
||||
sqlite3_finalize(m_get_guild_stmt);
|
||||
sqlite3_finalize(m_set_chan_stmt);
|
||||
sqlite3_finalize(m_get_chan_stmt);
|
||||
sqlite3_finalize(m_set_ban_stmt);
|
||||
sqlite3_finalize(m_get_ban_stmt);
|
||||
sqlite3_finalize(m_clear_ban_stmt);
|
||||
sqlite3_finalize(m_get_bans_stmt);
|
||||
}
|
||||
|
||||
void Store::Bind(sqlite3_stmt *stmt, int index, int num) const {
|
||||
|
@ -26,6 +26,7 @@ public:
|
||||
void SetGuildMember(Snowflake guild_id, Snowflake user_id, const GuildMember &data);
|
||||
void SetPermissionOverwrite(Snowflake channel_id, Snowflake id, const PermissionOverwrite &perm);
|
||||
void SetEmoji(Snowflake id, const EmojiData &emoji);
|
||||
void SetBan(Snowflake guild_id, Snowflake user_id, const BanData &ban);
|
||||
|
||||
// slap const on everything even tho its not *really* const
|
||||
|
||||
@ -37,9 +38,12 @@ public:
|
||||
std::optional<PermissionOverwrite> GetPermissionOverwrite(Snowflake channel_id, Snowflake id) const;
|
||||
std::optional<RoleData> GetRole(Snowflake id) const;
|
||||
std::optional<UserData> GetUser(Snowflake id) const;
|
||||
std::optional<BanData> GetBan(Snowflake guild_id, Snowflake user_id) const;
|
||||
std::vector<BanData> GetBans(Snowflake guild_id) const;
|
||||
|
||||
void ClearGuild(Snowflake id);
|
||||
void ClearChannel(Snowflake id);
|
||||
void ClearBan(Snowflake guild_id, Snowflake user_id);
|
||||
|
||||
using users_type = std::unordered_map<Snowflake, UserData>;
|
||||
using channels_type = std::unordered_map<Snowflake, ChannelData>;
|
||||
@ -104,6 +108,10 @@ private:
|
||||
mutable sqlite3_stmt *m_get_guild_stmt;
|
||||
mutable sqlite3_stmt *m_set_chan_stmt;
|
||||
mutable sqlite3_stmt *m_get_chan_stmt;
|
||||
mutable sqlite3_stmt *m_set_ban_stmt;
|
||||
mutable sqlite3_stmt *m_get_ban_stmt;
|
||||
mutable sqlite3_stmt *m_clear_ban_stmt;
|
||||
mutable sqlite3_stmt *m_get_bans_stmt;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
136
windows/guildsettings/banspane.cpp
Normal file
136
windows/guildsettings/banspane.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
#include "banspane.hpp"
|
||||
#include "../../abaddon.hpp"
|
||||
|
||||
// gtk_list_store_set_value: assertion 'column >= 0 && column < priv->n_columns' failed
|
||||
// dont care to figure out why this happens cuz it doesnt seem to break anything
|
||||
|
||||
GuildSettingsBansPane::GuildSettingsBansPane(Snowflake id)
|
||||
: GuildID(id)
|
||||
, m_menu_unban("Unban")
|
||||
, m_menu_copy_id("Copy ID")
|
||||
, m_model(Gtk::ListStore::create(m_columns)) {
|
||||
set_name("guild-bans-pane");
|
||||
set_hexpand(true);
|
||||
set_vexpand(true);
|
||||
|
||||
auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
|
||||
discord.signal_guild_ban_add().connect(sigc::mem_fun(*this, &GuildSettingsBansPane::OnBanAdd));
|
||||
discord.signal_guild_ban_remove().connect(sigc::mem_fun(*this, &GuildSettingsBansPane::OnBanRemove));
|
||||
|
||||
const auto self_id = discord.GetUserData().ID;
|
||||
const auto can_ban = discord.HasGuildPermission(self_id, GuildID, Permission::BAN_MEMBERS);
|
||||
|
||||
if (can_ban) {
|
||||
discord.FetchGuildBans(id, sigc::mem_fun(*this, &GuildSettingsBansPane::OnGuildBansFetch));
|
||||
} else {
|
||||
for (const auto &ban : discord.GetBansInGuild(id))
|
||||
OnGuildBanFetch(ban);
|
||||
}
|
||||
|
||||
m_menu_unban.signal_activate().connect(sigc::mem_fun(*this, &GuildSettingsBansPane::OnMenuUnban));
|
||||
m_menu_copy_id.signal_activate().connect(sigc::mem_fun(*this, &GuildSettingsBansPane::OnMenuCopyID));
|
||||
m_menu_unban.show();
|
||||
m_menu_copy_id.show();
|
||||
m_menu.append(m_menu_unban);
|
||||
m_menu.append(m_menu_copy_id);
|
||||
|
||||
m_view.signal_button_press_event().connect(sigc::mem_fun(*this, &GuildSettingsBansPane::OnTreeButtonPress), false);
|
||||
m_view.show();
|
||||
add(m_view);
|
||||
|
||||
m_view.set_model(m_model);
|
||||
m_view.append_column("User", m_columns.m_col_user);
|
||||
m_view.append_column("Reason", m_columns.m_col_reason);
|
||||
}
|
||||
|
||||
void GuildSettingsBansPane::OnGuildBanFetch(const BanData &ban) {
|
||||
const auto user = Abaddon::Get().GetDiscordClient().GetUser(ban.User.ID);
|
||||
auto &row = *m_model->append();
|
||||
row[m_columns.m_col_id] = ban.User.ID;
|
||||
if (user.has_value())
|
||||
row[m_columns.m_col_user] = user->Username + "#" + user->Discriminator;
|
||||
else
|
||||
row[m_columns.m_col_user] = "<@" + std::to_string(ban.User.ID) + ">";
|
||||
|
||||
row[m_columns.m_col_reason] = ban.Reason;
|
||||
}
|
||||
|
||||
void GuildSettingsBansPane::OnGuildBansFetch(const std::vector<BanData> &bans) {
|
||||
for (const auto &ban : bans) {
|
||||
const auto user = Abaddon::Get().GetDiscordClient().GetUser(ban.User.ID);
|
||||
auto &row = *m_model->append();
|
||||
row[m_columns.m_col_id] = user->ID;
|
||||
row[m_columns.m_col_user] = user->Username + "#" + user->Discriminator;
|
||||
row[m_columns.m_col_reason] = ban.Reason;
|
||||
}
|
||||
}
|
||||
|
||||
void GuildSettingsBansPane::OnMenuUnban() {
|
||||
auto selected_row = *m_view.get_selection()->get_selected();
|
||||
if (selected_row) {
|
||||
Snowflake id = selected_row[m_columns.m_col_id];
|
||||
auto cb = [this](bool success) {
|
||||
if (!success) {
|
||||
Gtk::MessageDialog dlg("Failed to unban user", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
||||
dlg.run();
|
||||
}
|
||||
};
|
||||
Abaddon::Get().GetDiscordClient().UnbanUser(GuildID, id, sigc::track_obj(cb, *this));
|
||||
}
|
||||
}
|
||||
|
||||
void GuildSettingsBansPane::OnMenuCopyID() {
|
||||
auto selected_row = *m_view.get_selection()->get_selected();
|
||||
if (selected_row)
|
||||
Gtk::Clipboard::get()->set_text(std::to_string(static_cast<Snowflake>(selected_row[m_columns.m_col_id])));
|
||||
}
|
||||
|
||||
bool GuildSettingsBansPane::OnTreeButtonPress(GdkEventButton *event) {
|
||||
if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_SECONDARY) {
|
||||
auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
const auto self_id = discord.GetUserData().ID;
|
||||
const auto can_ban = discord.HasGuildPermission(self_id, GuildID, Permission::BAN_MEMBERS);
|
||||
m_menu_unban.set_sensitive(can_ban);
|
||||
auto selection = m_view.get_selection();
|
||||
Gtk::TreeModel::Path path;
|
||||
if (m_view.get_path_at_pos(event->x, event->y, path)) {
|
||||
m_view.get_selection()->select(path);
|
||||
m_menu.popup_at_pointer(reinterpret_cast<GdkEvent *>(event));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GuildSettingsBansPane::OnBanRemove(Snowflake guild_id, Snowflake user_id) {
|
||||
if (guild_id != GuildID) return;
|
||||
for (auto &child : m_model->children()) {
|
||||
if (static_cast<Snowflake>(child[m_columns.m_col_id]) == user_id) {
|
||||
m_model->erase(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GuildSettingsBansPane::OnBanAdd(Snowflake guild_id, Snowflake user_id) {
|
||||
if (guild_id != GuildID) return;
|
||||
auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
if (discord.HasGuildPermission(discord.GetUserData().ID, guild_id, Permission::BAN_MEMBERS)) {
|
||||
discord.FetchGuildBan(guild_id, user_id, sigc::mem_fun(*this, &GuildSettingsBansPane::OnGuildBanFetch));
|
||||
} else {
|
||||
auto user = *discord.GetUser(user_id);
|
||||
auto &row = *m_model->append();
|
||||
row[m_columns.m_col_id] = user_id;
|
||||
row[m_columns.m_col_user] = user.Username + "#" + user.Discriminator;
|
||||
row[m_columns.m_col_reason] = "";
|
||||
}
|
||||
}
|
||||
|
||||
GuildSettingsBansPane::ModelColumns::ModelColumns() {
|
||||
add(m_col_id);
|
||||
add(m_col_user);
|
||||
add(m_col_reason);
|
||||
}
|
38
windows/guildsettings/banspane.hpp
Normal file
38
windows/guildsettings/banspane.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
#include <gtkmm.h>
|
||||
#include "../../discord/snowflake.hpp"
|
||||
#include "../../discord/ban.hpp"
|
||||
|
||||
class GuildSettingsBansPane : public Gtk::ScrolledWindow {
|
||||
public:
|
||||
GuildSettingsBansPane(Snowflake id);
|
||||
|
||||
private:
|
||||
void OnGuildBanFetch(const BanData &ban);
|
||||
void OnGuildBansFetch(const std::vector<BanData> &bans);
|
||||
void OnMenuUnban();
|
||||
void OnMenuCopyID();
|
||||
bool OnTreeButtonPress(GdkEventButton *event);
|
||||
void OnBanRemove(Snowflake guild_id, Snowflake user_id);
|
||||
void OnBanAdd(Snowflake guild_id, Snowflake user_id);
|
||||
|
||||
Gtk::TreeView m_view;
|
||||
|
||||
Snowflake GuildID;
|
||||
|
||||
class ModelColumns : public Gtk::TreeModel::ColumnRecord {
|
||||
public:
|
||||
ModelColumns();
|
||||
|
||||
Gtk::TreeModelColumn<Glib::ustring> m_col_user;
|
||||
Gtk::TreeModelColumn<Glib::ustring> m_col_reason;
|
||||
Gtk::TreeModelColumn<Snowflake> m_col_id;
|
||||
};
|
||||
|
||||
ModelColumns m_columns;
|
||||
Glib::RefPtr<Gtk::ListStore> m_model;
|
||||
|
||||
Gtk::Menu m_menu;
|
||||
Gtk::MenuItem m_menu_unban;
|
||||
Gtk::MenuItem m_menu_copy_id;
|
||||
};
|
@ -12,10 +12,6 @@ GuildSettingsInfoPane::GuildSettingsInfoPane(Snowflake id)
|
||||
const auto can_modify = discord.HasGuildPermission(self_id, id, Permission::MANAGE_GUILD);
|
||||
|
||||
set_name("guild-info-pane");
|
||||
set_margin_top(10);
|
||||
set_margin_bottom(10);
|
||||
set_margin_left(10);
|
||||
set_margin_top(10);
|
||||
|
||||
m_guild_name.set_sensitive(can_modify);
|
||||
m_guild_name.set_text(guild.Name);
|
||||
|
@ -4,7 +4,8 @@
|
||||
GuildSettingsWindow::GuildSettingsWindow(Snowflake id)
|
||||
: m_main(Gtk::ORIENTATION_VERTICAL)
|
||||
, GuildID(id)
|
||||
, m_pane_info(id) {
|
||||
, m_pane_info(id)
|
||||
, m_pane_bans(id) {
|
||||
auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
const auto guild = *discord.GetGuild(id);
|
||||
|
||||
@ -34,8 +35,15 @@ GuildSettingsWindow::GuildSettingsWindow(Snowflake id)
|
||||
m_switcher.show();
|
||||
|
||||
m_pane_info.show();
|
||||
m_pane_bans.show();
|
||||
|
||||
m_stack.set_margin_top(10);
|
||||
m_stack.set_margin_bottom(10);
|
||||
m_stack.set_margin_left(10);
|
||||
m_stack.set_margin_right(10);
|
||||
|
||||
m_stack.add(m_pane_info, "info", "Info");
|
||||
m_stack.add(m_pane_bans, "bans", "Bans");
|
||||
m_stack.show();
|
||||
|
||||
m_main.add(m_switcher);
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <gtkmm.h>
|
||||
#include "../discord/snowflake.hpp"
|
||||
#include "guildsettings/infopane.hpp"
|
||||
#include "guildsettings/banspane.hpp"
|
||||
|
||||
class GuildSettingsWindow : public Gtk::Window {
|
||||
public:
|
||||
@ -13,6 +14,7 @@ private:
|
||||
Gtk::StackSwitcher m_switcher;
|
||||
|
||||
GuildSettingsInfoPane m_pane_info;
|
||||
GuildSettingsBansPane m_pane_bans;
|
||||
|
||||
Snowflake GuildID;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user