mirror of
https://github.com/uowuo/abaddon.git
synced 2024-09-20 23:11:51 +00:00
progress 2
This commit is contained in:
parent
deb482a8db
commit
0b8c83eaa1
|
@ -16,7 +16,8 @@
|
|||
|
||||
Abaddon::Abaddon()
|
||||
: m_settings("abaddon.ini")
|
||||
, m_emojis("res/emojis.bin") {
|
||||
, m_emojis("res/emojis.bin")
|
||||
, m_discord(m_settings.GetSettingBool("discord", "memory_db", false)) { // stupid but easy
|
||||
LoadFromSettings();
|
||||
|
||||
m_discord.signal_gateway_ready().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnReady));
|
||||
|
@ -360,7 +361,7 @@ void Abaddon::ActionChatDeleteMessage(Snowflake channel_id, Snowflake id) {
|
|||
}
|
||||
|
||||
void Abaddon::ActionChatEditMessage(Snowflake channel_id, Snowflake id) {
|
||||
const auto *msg = m_discord.GetMessage(id);
|
||||
const auto msg = m_discord.GetMessage(id);
|
||||
EditMessageDialog dlg(*m_main_window);
|
||||
dlg.SetContent(msg->Content);
|
||||
auto response = dlg.run();
|
||||
|
|
|
@ -87,6 +87,8 @@ protected:
|
|||
void on_user_menu_open_dm();
|
||||
|
||||
private:
|
||||
SettingsManager m_settings;
|
||||
|
||||
DiscordClient m_discord;
|
||||
std::string m_discord_token;
|
||||
// todo make these map snowflake to attribs
|
||||
|
@ -101,6 +103,5 @@ private:
|
|||
mutable std::mutex m_mutex;
|
||||
Glib::RefPtr<Gtk::Application> m_gtk_app;
|
||||
Glib::RefPtr<Gtk::CssProvider> m_css_provider;
|
||||
SettingsManager m_settings;
|
||||
std::unique_ptr<MainWindow> m_main_window; // wah wah cant create a gtkstylecontext fuck you
|
||||
};
|
||||
|
|
|
@ -215,7 +215,7 @@ ChannelList::ChannelList() {
|
|||
// maybe will regret doing it this way
|
||||
auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
discord.signal_message_create().connect(sigc::track_obj([this, &discord](Snowflake message_id) {
|
||||
const auto *message = discord.GetMessage(message_id);
|
||||
const auto message = discord.GetMessage(message_id);
|
||||
const auto *channel = discord.GetChannel(message->ChannelID);
|
||||
if (channel == nullptr) return;
|
||||
if (channel->Type == ChannelType::DM || channel->Type == ChannelType::GROUP_DM)
|
||||
|
|
|
@ -33,22 +33,22 @@ ChatMessageItemContainer::ChatMessageItemContainer() {
|
|||
}
|
||||
|
||||
ChatMessageItemContainer *ChatMessageItemContainer::FromMessage(Snowflake id) {
|
||||
const auto *data = Abaddon::Get().GetDiscordClient().GetMessage(id);
|
||||
if (data == nullptr) return nullptr;
|
||||
const auto data = Abaddon::Get().GetDiscordClient().GetMessage(id);
|
||||
if (!data.has_value()) return nullptr;
|
||||
|
||||
auto *container = Gtk::manage(new ChatMessageItemContainer);
|
||||
container->ID = data->ID;
|
||||
container->ChannelID = data->ChannelID;
|
||||
|
||||
if (data->Content.size() > 0 || data->Type != MessageType::DEFAULT) {
|
||||
container->m_text_component = container->CreateTextComponent(data);
|
||||
container->m_text_component = container->CreateTextComponent(&*data);
|
||||
container->AttachGuildMenuHandler(container->m_text_component);
|
||||
container->m_main->add(*container->m_text_component);
|
||||
}
|
||||
|
||||
// there should only ever be 1 embed (i think?)
|
||||
if (data->Embeds.size() == 1) {
|
||||
container->m_embed_component = container->CreateEmbedComponent(data);
|
||||
container->m_embed_component = container->CreateEmbedComponent(&*data);
|
||||
container->AttachGuildMenuHandler(container->m_embed_component);
|
||||
container->m_main->add(*container->m_embed_component);
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ ChatMessageItemContainer *ChatMessageItemContainer::FromMessage(Snowflake id) {
|
|||
|
||||
// this doesnt rly make sense
|
||||
void ChatMessageItemContainer::UpdateContent() {
|
||||
const auto *data = Abaddon::Get().GetDiscordClient().GetMessage(ID);
|
||||
const auto data = Abaddon::Get().GetDiscordClient().GetMessage(ID);
|
||||
if (m_text_component != nullptr)
|
||||
UpdateTextComponent(m_text_component);
|
||||
|
||||
|
@ -93,7 +93,7 @@ void ChatMessageItemContainer::UpdateContent() {
|
|||
}
|
||||
|
||||
if (data->Embeds.size() == 1) {
|
||||
m_embed_component = CreateEmbedComponent(data);
|
||||
m_embed_component = CreateEmbedComponent(&*data);
|
||||
if (m_embed_imgurl.size() > 0) {
|
||||
m_signal_image_load.emit(m_embed_imgurl);
|
||||
}
|
||||
|
@ -115,15 +115,19 @@ void ChatMessageItemContainer::UpdateImage(std::string url, Glib::RefPtr<Gdk::Pi
|
|||
|
||||
auto it = m_img_loadmap.find(url);
|
||||
if (it != m_img_loadmap.end()) {
|
||||
int w, h;
|
||||
GetImageDimensions(it->second.second.Width, it->second.second.Height, w, h);
|
||||
it->second.first->property_pixbuf() = buf->scale_simple(w, h, Gdk::INTERP_BILINEAR);
|
||||
const auto inw = it->second.second.Width;
|
||||
const auto inh = it->second.second.Height;
|
||||
if (inw.has_value() && inh.has_value()) {
|
||||
int w, h;
|
||||
GetImageDimensions(*inw, *inh, w, h);
|
||||
it->second.first->property_pixbuf() = buf->scale_simple(w, h, Gdk::INTERP_BILINEAR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChatMessageItemContainer::UpdateAttributes() {
|
||||
const auto *data = Abaddon::Get().GetDiscordClient().GetMessage(ID);
|
||||
if (data == nullptr) return;
|
||||
const auto data = Abaddon::Get().GetDiscordClient().GetMessage(ID);
|
||||
if (!data.has_value()) return;
|
||||
|
||||
const bool deleted = data->IsDeleted();
|
||||
const bool edited = data->IsEdited();
|
||||
|
@ -176,9 +180,8 @@ Gtk::TextView *ChatMessageItemContainer::CreateTextComponent(const Message *data
|
|||
}
|
||||
|
||||
void ChatMessageItemContainer::UpdateTextComponent(Gtk::TextView *tv) {
|
||||
const auto *data = Abaddon::Get().GetDiscordClient().GetMessage(ID);
|
||||
if (data == nullptr)
|
||||
return;
|
||||
const auto data = Abaddon::Get().GetDiscordClient().GetMessage(ID);
|
||||
if (!data.has_value()) return;
|
||||
|
||||
auto b = tv->get_buffer();
|
||||
b->set_text("");
|
||||
|
@ -208,21 +211,21 @@ Gtk::Widget *ChatMessageItemContainer::CreateEmbedComponent(const Message *data)
|
|||
Gtk::Box *main = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
|
||||
const auto &embed = data->Embeds[0];
|
||||
|
||||
if (embed.Author.Name.length() > 0) {
|
||||
if (embed.Author.has_value() && embed.Author->Name.has_value()) {
|
||||
auto *author_lbl = Gtk::manage(new Gtk::Label);
|
||||
author_lbl->set_halign(Gtk::ALIGN_START);
|
||||
author_lbl->set_line_wrap(true);
|
||||
author_lbl->set_line_wrap_mode(Pango::WRAP_WORD_CHAR);
|
||||
author_lbl->set_hexpand(false);
|
||||
author_lbl->set_text(embed.Author.Name);
|
||||
author_lbl->set_text(*embed.Author->Name);
|
||||
author_lbl->get_style_context()->add_class("embed-author");
|
||||
main->pack_start(*author_lbl);
|
||||
}
|
||||
|
||||
if (embed.Title.length() > 0) {
|
||||
if (embed.Title.has_value()) {
|
||||
auto *title_label = Gtk::manage(new Gtk::Label);
|
||||
title_label->set_use_markup(true);
|
||||
title_label->set_markup("<b>" + Glib::Markup::escape_text(embed.Title) + "</b>");
|
||||
title_label->set_markup("<b>" + Glib::Markup::escape_text(*embed.Title) + "</b>");
|
||||
title_label->set_halign(Gtk::ALIGN_CENTER);
|
||||
title_label->set_hexpand(false);
|
||||
title_label->get_style_context()->add_class("embed-title");
|
||||
|
@ -233,9 +236,9 @@ Gtk::Widget *ChatMessageItemContainer::CreateEmbedComponent(const Message *data)
|
|||
main->pack_start(*title_label);
|
||||
}
|
||||
|
||||
if (embed.Description.length() > 0) {
|
||||
if (embed.Description.has_value()) {
|
||||
auto *desc_label = Gtk::manage(new Gtk::Label);
|
||||
desc_label->set_text(embed.Description);
|
||||
desc_label->set_text(*embed.Description);
|
||||
desc_label->set_line_wrap(true);
|
||||
desc_label->set_line_wrap_mode(Pango::WRAP_WORD_CHAR);
|
||||
desc_label->set_max_width_chars(50);
|
||||
|
@ -246,7 +249,7 @@ Gtk::Widget *ChatMessageItemContainer::CreateEmbedComponent(const Message *data)
|
|||
}
|
||||
|
||||
// todo: handle inline fields
|
||||
if (embed.Fields.size() > 0) {
|
||||
if (embed.Fields.has_value() && embed.Fields->size() > 0) {
|
||||
auto *flow = Gtk::manage(new Gtk::FlowBox);
|
||||
flow->set_orientation(Gtk::ORIENTATION_HORIZONTAL);
|
||||
flow->set_min_children_per_line(3);
|
||||
|
@ -257,7 +260,7 @@ Gtk::Widget *ChatMessageItemContainer::CreateEmbedComponent(const Message *data)
|
|||
flow->set_selection_mode(Gtk::SELECTION_NONE);
|
||||
main->pack_start(*flow);
|
||||
|
||||
for (const auto &field : embed.Fields) {
|
||||
for (const auto &field : *embed.Fields) {
|
||||
auto *field_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
|
||||
auto *field_lbl = Gtk::manage(new Gtk::Label);
|
||||
auto *field_val = Gtk::manage(new Gtk::Label);
|
||||
|
@ -287,42 +290,44 @@ Gtk::Widget *ChatMessageItemContainer::CreateEmbedComponent(const Message *data)
|
|||
}
|
||||
}
|
||||
|
||||
bool is_img = embed.Image.URL.size() > 0;
|
||||
bool is_thumb = embed.Thumbnail.URL.size() > 0;
|
||||
if (is_img || is_thumb) {
|
||||
auto *img = Gtk::manage(new Gtk::Image);
|
||||
img->set_halign(Gtk::ALIGN_CENTER);
|
||||
int w, h;
|
||||
if (is_img)
|
||||
GetImageDimensions(embed.Image.Width, embed.Image.Height, w, h, 200, 150);
|
||||
else
|
||||
GetImageDimensions(embed.Thumbnail.Width, embed.Thumbnail.Height, w, h, 200, 150);
|
||||
img->set_size_request(w, h);
|
||||
main->pack_start(*img);
|
||||
m_embed_img = img;
|
||||
if (is_img)
|
||||
m_embed_imgurl = embed.Image.ProxyURL;
|
||||
else
|
||||
m_embed_imgurl = embed.Thumbnail.ProxyURL;
|
||||
Glib::signal_idle().connect(sigc::bind(sigc::mem_fun(*this, &ChatMessageItemContainer::EmitImageLoad), m_embed_imgurl));
|
||||
if (embed.Image.has_value()) {
|
||||
bool is_img = embed.Image->URL.has_value();
|
||||
bool is_thumb = embed.Thumbnail.has_value();
|
||||
if (is_img || is_thumb) {
|
||||
auto *img = Gtk::manage(new Gtk::Image);
|
||||
img->set_halign(Gtk::ALIGN_CENTER);
|
||||
int w = 0, h = 0;
|
||||
if (is_img)
|
||||
GetImageDimensions(*embed.Image->Width, *embed.Image->Height, w, h, 200, 150);
|
||||
else
|
||||
GetImageDimensions(*embed.Thumbnail->Width, *embed.Thumbnail->Height, w, h, 200, 150);
|
||||
img->set_size_request(w, h);
|
||||
main->pack_start(*img);
|
||||
m_embed_img = img;
|
||||
if (is_img)
|
||||
m_embed_imgurl = *embed.Image->ProxyURL;
|
||||
else
|
||||
m_embed_imgurl = *embed.Thumbnail->ProxyURL;
|
||||
Glib::signal_idle().connect(sigc::bind(sigc::mem_fun(*this, &ChatMessageItemContainer::EmitImageLoad), m_embed_imgurl));
|
||||
}
|
||||
}
|
||||
|
||||
if (embed.Footer.Text.length() > 0) {
|
||||
if (embed.Footer.has_value()) {
|
||||
auto *footer_lbl = Gtk::manage(new Gtk::Label);
|
||||
footer_lbl->set_halign(Gtk::ALIGN_START);
|
||||
footer_lbl->set_line_wrap(true);
|
||||
footer_lbl->set_line_wrap_mode(Pango::WRAP_WORD_CHAR);
|
||||
footer_lbl->set_hexpand(false);
|
||||
footer_lbl->set_text(embed.Footer.Text);
|
||||
footer_lbl->set_text(embed.Footer->Text);
|
||||
footer_lbl->get_style_context()->add_class("embed-footer");
|
||||
main->pack_start(*footer_lbl);
|
||||
}
|
||||
|
||||
auto style = main->get_style_context();
|
||||
|
||||
if (embed.Color != -1) {
|
||||
if (embed.Color.has_value()) {
|
||||
auto provider = Gtk::CssProvider::create(); // this seems wrong
|
||||
std::string css = ".embed { border-left: 2px solid #" + IntToCSSColor(embed.Color) + "; }";
|
||||
std::string css = ".embed { border-left: 2px solid #" + IntToCSSColor(*embed.Color) + "; }";
|
||||
provider->load_from_data(css);
|
||||
style->add_provider(provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
}
|
||||
|
@ -343,7 +348,7 @@ Gtk::Widget *ChatMessageItemContainer::CreateEmbedComponent(const Message *data)
|
|||
|
||||
Gtk::Widget *ChatMessageItemContainer::CreateImageComponent(const AttachmentData &data) {
|
||||
int w, h;
|
||||
GetImageDimensions(data.Width, data.Height, w, h);
|
||||
GetImageDimensions(*data.Width, *data.Height, w, h);
|
||||
|
||||
Gtk::EventBox *ev = Gtk::manage(new Gtk::EventBox);
|
||||
Gtk::Image *widget = Gtk::manage(new Gtk::Image);
|
||||
|
@ -429,8 +434,8 @@ void ChatMessageItemContainer::HandleUserMentions(Gtk::TextView *tv) {
|
|||
replacement = "<b>@" + Glib::Markup::escape_text(user->Username) + "#" + user->Discriminator + "</b>";
|
||||
else {
|
||||
const auto role_id = user->GetHoistedRole(channel->GuildID, true);
|
||||
const auto *role = discord.GetRole(role_id);
|
||||
if (role == nullptr)
|
||||
const auto role = discord.GetRole(role_id);
|
||||
if (!role.has_value())
|
||||
replacement = "<b>@" + Glib::Markup::escape_text(user->Username) + "#" + user->Discriminator + "</b>";
|
||||
else
|
||||
replacement = "<b><span color=\"#" + IntToCSSColor(role->Color) + "\">@" + Glib::Markup::escape_text(user->Username) + "#" + user->Discriminator + "</span></b>";
|
||||
|
@ -658,7 +663,7 @@ bool ChatMessageItemContainer::OnLinkClick(GdkEventButton *ev) {
|
|||
|
||||
void ChatMessageItemContainer::ShowMenu(GdkEvent *event) {
|
||||
const auto &client = Abaddon::Get().GetDiscordClient();
|
||||
const auto *data = client.GetMessage(ID);
|
||||
const auto data = client.GetMessage(ID);
|
||||
if (data->IsDeleted()) {
|
||||
m_menu_delete_message->set_sensitive(false);
|
||||
m_menu_edit_message->set_sensitive(false);
|
||||
|
@ -685,8 +690,8 @@ void ChatMessageItemContainer::on_menu_edit_message() {
|
|||
}
|
||||
|
||||
void ChatMessageItemContainer::on_menu_copy_content() {
|
||||
const auto *msg = Abaddon::Get().GetDiscordClient().GetMessage(ID);
|
||||
if (msg != nullptr)
|
||||
const auto msg = Abaddon::Get().GetDiscordClient().GetMessage(ID);
|
||||
if (msg.has_value())
|
||||
Gtk::Clipboard::get()->set_text(msg->Content);
|
||||
}
|
||||
|
||||
|
@ -731,13 +736,18 @@ ChatMessageHeader::ChatMessageHeader(const Message *data) {
|
|||
m_timestamp = Gtk::manage(new Gtk::Label);
|
||||
m_avatar_ev = Gtk::manage(new Gtk::EventBox);
|
||||
|
||||
const auto author = Abaddon::Get().GetDiscordClient().GetUser(UserID);
|
||||
auto &img = Abaddon::Get().GetImageManager();
|
||||
auto buf = img.GetFromURLIfCached(data->Author.GetAvatarURL());
|
||||
Glib::RefPtr<Gdk::Pixbuf> buf;
|
||||
if (author.has_value())
|
||||
buf = img.GetFromURLIfCached(author->GetAvatarURL());
|
||||
|
||||
if (buf)
|
||||
m_avatar = Gtk::manage(new Gtk::Image(buf));
|
||||
else {
|
||||
m_avatar = Gtk::manage(new Gtk::Image(img.GetPlaceholder(32)));
|
||||
img.LoadFromURL(data->Author.GetAvatarURL(), sigc::mem_fun(*this, &ChatMessageHeader::OnAvatarLoad));
|
||||
if (author.has_value())
|
||||
img.LoadFromURL(author->GetAvatarURL(), sigc::mem_fun(*this, &ChatMessageHeader::OnAvatarLoad));
|
||||
}
|
||||
|
||||
get_style_context()->add_class("message-container");
|
||||
|
@ -816,10 +826,10 @@ void ChatMessageHeader::UpdateNameColor() {
|
|||
const auto role_id = discord.GetMemberHoistedRole(guild_id, UserID, true);
|
||||
const auto user = discord.GetUser(UserID);
|
||||
if (!user.has_value()) return;
|
||||
const auto *role = discord.GetRole(role_id);
|
||||
const auto role = discord.GetRole(role_id);
|
||||
|
||||
std::string md;
|
||||
if (role != nullptr)
|
||||
if (role.has_value())
|
||||
md = "<span weight='bold' color='#" + IntToCSSColor(role->Color) + "'>" + Glib::Markup::escape_text(user->Username) + "</span>";
|
||||
else
|
||||
md = "<span weight='bold' color='#eeeeee'>" + Glib::Markup::escape_text(user->Username) + "</span>";
|
||||
|
|
|
@ -157,8 +157,8 @@ ChatMessageItemContainer *ChatWindow::CreateMessageComponent(Snowflake id) {
|
|||
void ChatWindow::ProcessNewMessage(Snowflake id, bool prepend) {
|
||||
const auto &client = Abaddon::Get().GetDiscordClient();
|
||||
if (!client.IsStarted()) return; // e.g. load channel and then dc
|
||||
const auto *data = client.GetMessage(id);
|
||||
if (data == nullptr) return;
|
||||
const auto data = client.GetMessage(id);
|
||||
if (!data.has_value()) return;
|
||||
|
||||
ChatMessageHeader *last_row = nullptr;
|
||||
bool should_attach = false;
|
||||
|
@ -182,7 +182,7 @@ void ChatWindow::ProcessNewMessage(Snowflake id, bool prepend) {
|
|||
const auto user = client.GetUser(user_id);
|
||||
if (!user.has_value()) return;
|
||||
|
||||
header = Gtk::manage(new ChatMessageHeader(data));
|
||||
header = Gtk::manage(new ChatMessageHeader(&*data));
|
||||
header->signal_action_insert_mention().connect([this, user_id]() {
|
||||
m_signal_action_insert_mention.emit(user_id);
|
||||
});
|
||||
|
|
|
@ -111,7 +111,7 @@ void MemberList::UpdateMemberListInternal() {
|
|||
}
|
||||
|
||||
// process all the shit first so its in proper order
|
||||
std::map<int, const Role *> pos_to_role;
|
||||
std::map<int, Role> pos_to_role;
|
||||
std::map<int, std::vector<User>> pos_to_users;
|
||||
std::unordered_map<Snowflake, int> user_to_color;
|
||||
std::vector<Snowflake> roleless_users;
|
||||
|
@ -128,19 +128,15 @@ void MemberList::UpdateMemberListInternal() {
|
|||
auto pos_role = discord.GetRole(pos_role_id);
|
||||
auto col_role = discord.GetRole(col_role_id);
|
||||
|
||||
if (pos_role == nullptr) {
|
||||
if (!pos_role.has_value()) {
|
||||
roleless_users.push_back(id);
|
||||
continue;
|
||||
};
|
||||
|
||||
pos_to_role[pos_role->Position] = pos_role;
|
||||
pos_to_role[pos_role->Position] = *pos_role;
|
||||
pos_to_users[pos_role->Position].push_back(std::move(*user));
|
||||
if (col_role != nullptr) {
|
||||
if (ColorDistance(col_role->Color, 0xFFFFFF) < 15)
|
||||
user_to_color[id] = 0x000000;
|
||||
else
|
||||
user_to_color[id] = col_role->Color;
|
||||
}
|
||||
if (col_role.has_value())
|
||||
user_to_color[id] = col_role->Color;
|
||||
}
|
||||
|
||||
auto add_user = [this, &user_to_color](const User *data) {
|
||||
|
@ -191,9 +187,9 @@ void MemberList::UpdateMemberListInternal() {
|
|||
|
||||
for (auto it = pos_to_role.crbegin(); it != pos_to_role.crend(); it++) {
|
||||
auto pos = it->first;
|
||||
auto role = it->second;
|
||||
const auto &role = it->second;
|
||||
|
||||
add_role(role->Name);
|
||||
add_role(role.Name);
|
||||
|
||||
if (pos_to_users.find(pos) == pos_to_users.end()) continue;
|
||||
|
||||
|
|
|
@ -42,6 +42,6 @@ void Channel::update_from_json(const nlohmann::json &j) {
|
|||
JS_RD("last_pin_timestamp", LastPinTimestamp);
|
||||
}
|
||||
|
||||
const PermissionOverwrite *Channel::GetOverwrite(Snowflake id) const {
|
||||
std::optional<PermissionOverwrite> Channel::GetOverwrite(Snowflake id) const {
|
||||
return Abaddon::Get().GetDiscordClient().GetPermissionOverwrite(ID, id);
|
||||
}
|
||||
|
|
|
@ -39,5 +39,5 @@ struct Channel {
|
|||
friend void from_json(const nlohmann::json &j, Channel &m);
|
||||
void update_from_json(const nlohmann::json &j);
|
||||
|
||||
const PermissionOverwrite *GetOverwrite(Snowflake id) const;
|
||||
std::optional<PermissionOverwrite> GetOverwrite(Snowflake id) const;
|
||||
};
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
#include <cassert>
|
||||
#include "../util.hpp"
|
||||
|
||||
DiscordClient::DiscordClient()
|
||||
DiscordClient::DiscordClient(bool mem_store)
|
||||
: m_http(DiscordAPI)
|
||||
, m_decompress_buf(InflateChunkSize) {
|
||||
, m_decompress_buf(InflateChunkSize)
|
||||
, m_store(mem_store) {
|
||||
m_msg_dispatch.connect(sigc::mem_fun(*this, &DiscordClient::MessageDispatch));
|
||||
|
||||
m_websocket.signal_message().connect(sigc::mem_fun(*this, &DiscordClient::HandleGatewayMessageRaw));
|
||||
|
@ -164,7 +165,7 @@ void DiscordClient::FetchMessagesInChannelBefore(Snowflake channel_id, Snowflake
|
|||
});
|
||||
}
|
||||
|
||||
const Message *DiscordClient::GetMessage(Snowflake id) const {
|
||||
std::optional<Message> DiscordClient::GetMessage(Snowflake id) const {
|
||||
return m_store.GetMessage(id);
|
||||
}
|
||||
|
||||
|
@ -176,7 +177,7 @@ std::optional<User> DiscordClient::GetUser(Snowflake id) const {
|
|||
return m_store.GetUser(id);
|
||||
}
|
||||
|
||||
const Role *DiscordClient::GetRole(Snowflake id) const {
|
||||
std::optional<Role> DiscordClient::GetRole(Snowflake id) const {
|
||||
return m_store.GetRole(id);
|
||||
}
|
||||
|
||||
|
@ -188,7 +189,7 @@ const GuildMember *DiscordClient::GetMember(Snowflake user_id, Snowflake guild_i
|
|||
return m_store.GetGuildMemberData(guild_id, user_id);
|
||||
}
|
||||
|
||||
const PermissionOverwrite *DiscordClient::GetPermissionOverwrite(Snowflake channel_id, Snowflake id) const {
|
||||
std::optional<PermissionOverwrite> DiscordClient::GetPermissionOverwrite(Snowflake channel_id, Snowflake id) const {
|
||||
return m_store.GetPermissionOverwrite(channel_id, id);
|
||||
}
|
||||
|
||||
|
@ -200,22 +201,22 @@ Snowflake DiscordClient::GetMemberHoistedRole(Snowflake guild_id, Snowflake user
|
|||
auto *data = m_store.GetGuildMemberData(guild_id, user_id);
|
||||
if (data == nullptr) return Snowflake::Invalid;
|
||||
|
||||
std::vector<const Role *> roles;
|
||||
std::vector<Role> roles;
|
||||
for (const auto &id : data->Roles) {
|
||||
auto *role = GetRole(id);
|
||||
if (role != nullptr) {
|
||||
const auto role = GetRole(id);
|
||||
if (role.has_value()) {
|
||||
if (role->IsHoisted || (with_color && role->Color != 0))
|
||||
roles.push_back(role);
|
||||
roles.push_back(*role);
|
||||
}
|
||||
}
|
||||
|
||||
if (roles.size() == 0) return Snowflake::Invalid;
|
||||
|
||||
std::sort(roles.begin(), roles.end(), [this](const Role *a, const Role *b) -> bool {
|
||||
return a->Position > b->Position;
|
||||
std::sort(roles.begin(), roles.end(), [this](const Role &a, const Role &b) -> bool {
|
||||
return a.Position > b.Position;
|
||||
});
|
||||
|
||||
return roles[0]->ID;
|
||||
return roles[0].ID;
|
||||
}
|
||||
|
||||
Snowflake DiscordClient::GetMemberHighestRole(Snowflake guild_id, Snowflake user_id) const {
|
||||
|
@ -226,9 +227,9 @@ Snowflake DiscordClient::GetMemberHighestRole(Snowflake guild_id, Snowflake user
|
|||
if (data->Roles.size() == 1) return data->Roles[0];
|
||||
|
||||
return *std::max(data->Roles.begin(), data->Roles.end(), [this](const auto &a, const auto &b) -> bool {
|
||||
const auto *role_a = GetRole(*a);
|
||||
const auto *role_b = GetRole(*b);
|
||||
if (role_a == nullptr || role_b == nullptr) return false; // for some reason a Snowflake(0) sneaks into here
|
||||
const auto role_a = GetRole(*a);
|
||||
const auto role_b = GetRole(*b);
|
||||
if (!role_a.has_value() || !role_b.has_value()) return false; // for some reason a Snowflake(0) sneaks into here
|
||||
return role_a->Position < role_b->Position;
|
||||
});
|
||||
}
|
||||
|
@ -241,14 +242,6 @@ std::unordered_set<Snowflake> DiscordClient::GetUsersInGuild(Snowflake id) const
|
|||
return std::unordered_set<Snowflake>();
|
||||
}
|
||||
|
||||
std::unordered_set<Snowflake> DiscordClient::GetRolesInGuild(Snowflake id) const {
|
||||
std::unordered_set<Snowflake> ret;
|
||||
const auto &roles = m_store.GetRoles();
|
||||
for (const auto &[rid, rdata] : roles)
|
||||
ret.insert(rid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::unordered_set<Snowflake> DiscordClient::GetChannelsInGuild(Snowflake id) const {
|
||||
auto it = m_guild_to_channels.find(id);
|
||||
if (it != m_guild_to_channels.end())
|
||||
|
@ -278,14 +271,14 @@ Permission DiscordClient::ComputePermissions(Snowflake member_id, Snowflake guil
|
|||
if (guild->OwnerID == member_id)
|
||||
return Permission::ALL;
|
||||
|
||||
const auto *everyone = GetRole(guild_id);
|
||||
if (everyone == nullptr)
|
||||
const auto everyone = GetRole(guild_id);
|
||||
if (!everyone.has_value())
|
||||
return Permission::NONE;
|
||||
|
||||
Permission perms = everyone->Permissions;
|
||||
for (const auto role_id : member->Roles) {
|
||||
const auto *role = GetRole(role_id);
|
||||
if (role != nullptr)
|
||||
const auto role = GetRole(role_id);
|
||||
if (role.has_value())
|
||||
perms |= role->Permissions;
|
||||
}
|
||||
|
||||
|
@ -305,8 +298,8 @@ Permission DiscordClient::ComputeOverwrites(Permission base, Snowflake member_id
|
|||
return Permission::NONE;
|
||||
|
||||
Permission perms = base;
|
||||
const auto *overwrite_everyone = GetPermissionOverwrite(channel_id, channel->GuildID);
|
||||
if (overwrite_everyone != nullptr) {
|
||||
const auto overwrite_everyone = GetPermissionOverwrite(channel_id, channel->GuildID);
|
||||
if (overwrite_everyone.has_value()) {
|
||||
perms &= ~overwrite_everyone->Deny;
|
||||
perms |= overwrite_everyone->Allow;
|
||||
}
|
||||
|
@ -314,8 +307,8 @@ Permission DiscordClient::ComputeOverwrites(Permission base, Snowflake member_id
|
|||
Permission allow = Permission::NONE;
|
||||
Permission deny = Permission::NONE;
|
||||
for (const auto role_id : member->Roles) {
|
||||
const auto *overwrite = GetPermissionOverwrite(channel_id, role_id);
|
||||
if (overwrite != nullptr) {
|
||||
const auto overwrite = GetPermissionOverwrite(channel_id, role_id);
|
||||
if (overwrite.has_value()) {
|
||||
allow |= overwrite->Allow;
|
||||
deny |= overwrite->Deny;
|
||||
}
|
||||
|
@ -324,8 +317,8 @@ Permission DiscordClient::ComputeOverwrites(Permission base, Snowflake member_id
|
|||
perms &= ~deny;
|
||||
perms |= allow;
|
||||
|
||||
const auto *member_overwrite = GetPermissionOverwrite(channel_id, member_id);
|
||||
if (member_overwrite != nullptr) {
|
||||
const auto member_overwrite = GetPermissionOverwrite(channel_id, member_id);
|
||||
if (member_overwrite.has_value()) {
|
||||
perms &= ~member_overwrite->Deny;
|
||||
perms |= member_overwrite->Allow;
|
||||
}
|
||||
|
@ -338,10 +331,10 @@ bool DiscordClient::CanManageMember(Snowflake guild_id, Snowflake actor, Snowfla
|
|||
if (guild != nullptr && guild->OwnerID == target) return false;
|
||||
const auto actor_highest_id = GetMemberHighestRole(guild_id, actor);
|
||||
const auto target_highest_id = GetMemberHighestRole(guild_id, target);
|
||||
const auto *actor_highest = GetRole(actor_highest_id);
|
||||
const auto *target_highest = GetRole(target_highest_id);
|
||||
if (actor_highest == nullptr) return false;
|
||||
if (target_highest == nullptr) return true;
|
||||
const auto actor_highest = GetRole(actor_highest_id);
|
||||
const auto target_highest = GetRole(target_highest_id);
|
||||
if (!actor_highest.has_value()) return false;
|
||||
if (!target_highest.has_value()) return true;
|
||||
return actor_highest->Position > target_highest->Position;
|
||||
}
|
||||
|
||||
|
@ -581,6 +574,8 @@ void DiscordClient::ProcessNewGuild(Guild &guild) {
|
|||
return;
|
||||
}
|
||||
|
||||
m_store.BeginTransaction();
|
||||
|
||||
m_store.SetGuild(guild.ID, guild);
|
||||
for (auto &c : guild.Channels) {
|
||||
c.GuildID = guild.ID;
|
||||
|
@ -596,6 +591,8 @@ void DiscordClient::ProcessNewGuild(Guild &guild) {
|
|||
|
||||
for (auto &e : guild.Emojis)
|
||||
m_store.SetEmoji(e.ID, e);
|
||||
|
||||
m_store.EndTransaction();
|
||||
}
|
||||
|
||||
void DiscordClient::HandleGatewayReady(const GatewayMessage &msg) {
|
||||
|
@ -629,20 +626,28 @@ void DiscordClient::HandleGatewayMessageCreate(const GatewayMessage &msg) {
|
|||
|
||||
void DiscordClient::HandleGatewayMessageDelete(const GatewayMessage &msg) {
|
||||
MessageDeleteData data = msg.Data;
|
||||
auto *cur = m_store.GetMessage(data.ID);
|
||||
if (cur != nullptr)
|
||||
cur->SetDeleted();
|
||||
auto cur = m_store.GetMessage(data.ID);
|
||||
if (!cur.has_value())
|
||||
return;
|
||||
|
||||
cur->SetDeleted();
|
||||
m_store.SetMessage(data.ID, *cur);
|
||||
m_signal_message_delete.emit(data.ID, data.ChannelID);
|
||||
}
|
||||
|
||||
void DiscordClient::HandleGatewayMessageDeleteBulk(const GatewayMessage &msg) {
|
||||
MessageDeleteBulkData data = msg.Data;
|
||||
m_store.BeginTransaction();
|
||||
for (const auto &id : data.IDs) {
|
||||
auto *cur = m_store.GetMessage(id);
|
||||
if (cur != nullptr)
|
||||
cur->SetDeleted();
|
||||
auto cur = m_store.GetMessage(id);
|
||||
if (!cur.has_value())
|
||||
return;
|
||||
|
||||
cur->SetDeleted();
|
||||
m_store.SetMessage(id, *cur);
|
||||
m_signal_message_delete.emit(id, data.ChannelID);
|
||||
}
|
||||
m_store.EndTransaction();
|
||||
}
|
||||
|
||||
void DiscordClient::HandleGatewayGuildMemberUpdate(const GatewayMessage &msg) {
|
||||
|
@ -681,10 +686,12 @@ void DiscordClient::HandleGatewayChannelUpdate(const GatewayMessage &msg) {
|
|||
|
||||
void DiscordClient::HandleGatewayChannelCreate(const GatewayMessage &msg) {
|
||||
Channel data = msg.Data;
|
||||
m_store.BeginTransaction();
|
||||
m_store.SetChannel(data.ID, data);
|
||||
m_guild_to_channels[data.GuildID].insert(data.ID);
|
||||
for (const auto &p : data.PermissionOverwrites)
|
||||
m_store.SetPermissionOverwrite(data.ID, p.ID, p);
|
||||
m_store.EndTransaction();
|
||||
m_signal_channel_create.emit(data.ID);
|
||||
}
|
||||
|
||||
|
@ -717,11 +724,12 @@ void DiscordClient::HandleGatewayReconnect(const GatewayMessage &msg) {
|
|||
void DiscordClient::HandleGatewayMessageUpdate(const GatewayMessage &msg) {
|
||||
Snowflake id = msg.Data.at("id");
|
||||
|
||||
auto *current = m_store.GetMessage(id);
|
||||
if (current == nullptr)
|
||||
auto current = m_store.GetMessage(id);
|
||||
if (!current.has_value())
|
||||
return;
|
||||
|
||||
current->from_json_edited(msg.Data);
|
||||
m_store.SetMessage(id, *current);
|
||||
|
||||
m_signal_message_update.emit(id, current->ChannelID);
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ public:
|
|||
static const constexpr char *GatewayIdentity = "Discord";
|
||||
|
||||
public:
|
||||
DiscordClient();
|
||||
DiscordClient(bool mem_store = false);
|
||||
void Start();
|
||||
void Stop();
|
||||
bool IsStarted() const;
|
||||
|
@ -80,18 +80,17 @@ public:
|
|||
void FetchInviteData(std::string code, std::function<void(Invite)> cb, std::function<void(bool)> err);
|
||||
void FetchMessagesInChannel(Snowflake id, std::function<void(const std::vector<Snowflake> &)> cb);
|
||||
void FetchMessagesInChannelBefore(Snowflake channel_id, Snowflake before_id, std::function<void(const std::vector<Snowflake> &)> cb);
|
||||
const Message *GetMessage(Snowflake id) const;
|
||||
std::optional<Message> GetMessage(Snowflake id) const;
|
||||
const Channel *GetChannel(Snowflake id) const;
|
||||
std::optional<PermissionOverwrite> GetPermissionOverwrite(Snowflake channel_id, Snowflake id) const;
|
||||
std::optional<User> GetUser(Snowflake id) const;
|
||||
const Role *GetRole(Snowflake id) const;
|
||||
std::optional<Role> GetRole(Snowflake id) const;
|
||||
const Guild *GetGuild(Snowflake id) const;
|
||||
const GuildMember *GetMember(Snowflake user_id, Snowflake guild_id) const;
|
||||
const PermissionOverwrite *GetPermissionOverwrite(Snowflake channel_id, Snowflake id) const;
|
||||
const Emoji *GetEmoji(Snowflake 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;
|
||||
std::unordered_set<Snowflake> GetRolesInGuild(Snowflake id) const;
|
||||
std::unordered_set<Snowflake> GetChannelsInGuild(Snowflake id) const;
|
||||
|
||||
bool HasGuildPermission(Snowflake user_id, Snowflake guild_id, Permission perm) const;
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
#include "user.hpp"
|
||||
|
||||
struct Emoji {
|
||||
Snowflake ID; // null
|
||||
std::string Name; // null (in reactions)
|
||||
std::vector<Snowflake> Roles; // opt
|
||||
User Creator; // opt
|
||||
bool NeedsColons = false; // opt
|
||||
bool IsManaged = false; // opt
|
||||
bool IsAnimated = false; // opt
|
||||
bool IsAvailable = false; // opt
|
||||
Snowflake ID; // null
|
||||
std::string Name; // null (in reactions)
|
||||
std::optional<std::vector<Snowflake>> Roles;
|
||||
std::optional<User> Creator; // only reliable to access ID
|
||||
std::optional<bool> NeedsColons;
|
||||
std::optional<bool> IsManaged;
|
||||
std::optional<bool> IsAnimated;
|
||||
std::optional<bool> IsAvailable;
|
||||
|
||||
friend void from_json(const nlohmann::json &j, Emoji &m);
|
||||
|
||||
|
|
|
@ -1,11 +1,24 @@
|
|||
#include "message.hpp"
|
||||
|
||||
void to_json(nlohmann::json &j, const EmbedFooterData &m) {
|
||||
j["text"] = m.Text;
|
||||
JS_IF("icon_url", m.IconURL);
|
||||
JS_IF("proxy_icon_url", m.ProxyIconURL);
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json &j, EmbedFooterData &m) {
|
||||
JS_D("text", m.Text);
|
||||
JS_O("icon_url", m.IconURL);
|
||||
JS_O("proxy_icon_url", m.ProxyIconURL);
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const EmbedImageData &m) {
|
||||
JS_IF("url", m.URL);
|
||||
JS_IF("proxy_url", m.ProxyURL);
|
||||
JS_IF("height", m.Height);
|
||||
JS_IF("width", m.Width);
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json &j, EmbedImageData &m) {
|
||||
JS_O("url", m.URL);
|
||||
JS_O("proxy_url", m.ProxyURL);
|
||||
|
@ -13,6 +26,13 @@ void from_json(const nlohmann::json &j, EmbedImageData &m) {
|
|||
JS_O("width", m.Width);
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const EmbedThumbnailData &m) {
|
||||
JS_IF("url", m.URL);
|
||||
JS_IF("proxy_url", m.ProxyURL);
|
||||
JS_IF("height", m.Height);
|
||||
JS_IF("width", m.Width);
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json &j, EmbedThumbnailData &m) {
|
||||
JS_O("url", m.URL);
|
||||
JS_O("proxy_url", m.ProxyURL);
|
||||
|
@ -20,17 +40,35 @@ void from_json(const nlohmann::json &j, EmbedThumbnailData &m) {
|
|||
JS_O("width", m.Width);
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const EmbedVideoData &m) {
|
||||
JS_IF("url", m.URL);
|
||||
JS_IF("height", m.Height);
|
||||
JS_IF("width", m.Width);
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json &j, EmbedVideoData &m) {
|
||||
JS_O("url", m.URL);
|
||||
JS_O("height", m.Height);
|
||||
JS_O("width", m.Width);
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const EmbedProviderData &m) {
|
||||
JS_IF("name", m.Name);
|
||||
JS_IF("url", m.URL);
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json &j, EmbedProviderData &m) {
|
||||
JS_O("name", m.Name);
|
||||
JS_ON("url", m.URL);
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const EmbedAuthorData &m) {
|
||||
JS_IF("name", m.Name);
|
||||
JS_IF("url", m.URL);
|
||||
JS_IF("icon_url", m.IconURL);
|
||||
JS_IF("proxy_icon_url", m.ProxyIconURL);
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json &j, EmbedAuthorData &m) {
|
||||
JS_O("name", m.Name);
|
||||
JS_O("url", m.URL);
|
||||
|
@ -38,12 +76,34 @@ void from_json(const nlohmann::json &j, EmbedAuthorData &m) {
|
|||
JS_O("proxy_icon_url", m.ProxyIconURL);
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const EmbedFieldData &m) {
|
||||
j["name"] = m.Name;
|
||||
j["value"] = m.Value;
|
||||
JS_IF("inline", m.Inline);
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json &j, EmbedFieldData &m) {
|
||||
JS_D("name", m.Name);
|
||||
JS_D("value", m.Value);
|
||||
JS_O("inline", m.Inline);
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const EmbedData &m) {
|
||||
JS_IF("title", m.Title);
|
||||
JS_IF("type", m.Type);
|
||||
JS_IF("description", m.Description);
|
||||
JS_IF("url", m.URL);
|
||||
JS_IF("timestamp", m.Timestamp);
|
||||
JS_IF("color", m.Color);
|
||||
JS_IF("footer", m.Footer);
|
||||
JS_IF("image", m.Image);
|
||||
JS_IF("thumbnail", m.Thumbnail);
|
||||
JS_IF("video", m.Video);
|
||||
JS_IF("provider", m.Provider);
|
||||
JS_IF("author", m.Author);
|
||||
JS_IF("fields", m.Fields);
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json &j, EmbedData &m) {
|
||||
JS_O("title", m.Title);
|
||||
JS_O("type", m.Type);
|
||||
|
@ -60,6 +120,16 @@ void from_json(const nlohmann::json &j, EmbedData &m) {
|
|||
JS_O("fields", m.Fields);
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const AttachmentData &m) {
|
||||
j["id"] = m.ID;
|
||||
j["filename"] = m.Filename;
|
||||
j["size"] = m.Bytes;
|
||||
j["url"] = m.URL;
|
||||
j["proxy_url"] = m.ProxyURL;
|
||||
JS_IF("height", m.Height);
|
||||
JS_IF("width", m.Width);
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json &j, AttachmentData &m) {
|
||||
JS_D("id", m.ID);
|
||||
JS_D("filename", m.Filename);
|
||||
|
@ -107,7 +177,7 @@ void from_json(const nlohmann::json &j, Message &m) {
|
|||
JS_D("type", m.Type);
|
||||
// JS_O("activity", m.Activity);
|
||||
// JS_O("application", m.Application);
|
||||
// JS_O("message_reference", m.MessageReference);
|
||||
JS_O("message_reference", m.MessageReference);
|
||||
JS_O("flags", m.Flags);
|
||||
JS_O("stickers", m.Stickers);
|
||||
}
|
||||
|
|
|
@ -35,89 +35,99 @@ enum class MessageFlags {
|
|||
};
|
||||
|
||||
struct EmbedFooterData {
|
||||
std::string Text; //
|
||||
std::string IconURL; // opt
|
||||
std::string ProxyIconURL; // opt
|
||||
std::string Text;
|
||||
std::optional<std::string> IconURL;
|
||||
std::optional<std::string> ProxyIconURL;
|
||||
|
||||
friend void to_json(nlohmann::json &j, const EmbedFooterData &m);
|
||||
friend void from_json(const nlohmann::json &j, EmbedFooterData &m);
|
||||
};
|
||||
|
||||
struct EmbedImageData {
|
||||
std::string URL; // opt
|
||||
std::string ProxyURL; // opt
|
||||
int Height = 0; // opt
|
||||
int Width = 0; // opt
|
||||
std::optional<std::string> URL;
|
||||
std::optional<std::string> ProxyURL;
|
||||
std::optional<int> Height;
|
||||
std::optional<int> Width;
|
||||
|
||||
friend void to_json(nlohmann::json &j, const EmbedImageData &m);
|
||||
friend void from_json(const nlohmann::json &j, EmbedImageData &m);
|
||||
};
|
||||
|
||||
struct EmbedThumbnailData {
|
||||
std::string URL; // opt
|
||||
std::string ProxyURL; // opt
|
||||
int Height = 0; // opt
|
||||
int Width = 0; // opt
|
||||
std::optional<std::string> URL;
|
||||
std::optional<std::string> ProxyURL;
|
||||
std::optional<int> Height;
|
||||
std::optional<int> Width;
|
||||
|
||||
friend void to_json(nlohmann::json &j, const EmbedThumbnailData &m);
|
||||
friend void from_json(const nlohmann::json &j, EmbedThumbnailData &m);
|
||||
};
|
||||
|
||||
struct EmbedVideoData {
|
||||
std::string URL; // opt
|
||||
int Height = 0; // opt
|
||||
int Width = 0; // opt
|
||||
std::optional<std::string> URL;
|
||||
std::optional<int> Height;
|
||||
std::optional<int> Width;
|
||||
|
||||
friend void to_json(nlohmann::json &j, const EmbedVideoData &m);
|
||||
friend void from_json(const nlohmann::json &j, EmbedVideoData &m);
|
||||
};
|
||||
|
||||
struct EmbedProviderData {
|
||||
std::string Name; // opt
|
||||
std::string URL; // opt, null (docs wrong)
|
||||
std::optional<std::string> Name;
|
||||
std::optional<std::string> URL; // null
|
||||
|
||||
friend void to_json(nlohmann::json &j, const EmbedProviderData &m);
|
||||
friend void from_json(const nlohmann::json &j, EmbedProviderData &m);
|
||||
};
|
||||
|
||||
struct EmbedAuthorData {
|
||||
std::string Name; // opt
|
||||
std::string URL; // opt
|
||||
std::string IconURL; // opt
|
||||
std::string ProxyIconURL; // opt
|
||||
std::optional<std::string> Name;
|
||||
std::optional<std::string> URL;
|
||||
std::optional<std::string> IconURL;
|
||||
std::optional<std::string> ProxyIconURL;
|
||||
|
||||
friend void to_json(nlohmann::json &j, const EmbedAuthorData &m);
|
||||
friend void from_json(const nlohmann::json &j, EmbedAuthorData &m);
|
||||
};
|
||||
|
||||
struct EmbedFieldData {
|
||||
std::string Name; //
|
||||
std::string Value; //
|
||||
bool Inline = false; // opt
|
||||
std::string Name;
|
||||
std::string Value;
|
||||
std::optional<bool> Inline;
|
||||
|
||||
friend void to_json(nlohmann::json &j, const EmbedFieldData &m);
|
||||
friend void from_json(const nlohmann::json &j, EmbedFieldData &m);
|
||||
};
|
||||
|
||||
struct EmbedData {
|
||||
std::string Title; // opt
|
||||
std::string Type; // opt
|
||||
std::string Description; // opt
|
||||
std::string URL; // opt
|
||||
std::string Timestamp; // opt
|
||||
int Color = -1; // opt
|
||||
EmbedFooterData Footer; // opt
|
||||
EmbedImageData Image; // opt
|
||||
EmbedThumbnailData Thumbnail; // opt
|
||||
EmbedVideoData Video; // opt
|
||||
EmbedProviderData Provider; // opt
|
||||
EmbedAuthorData Author; // opt
|
||||
std::vector<EmbedFieldData> Fields; // opt
|
||||
std::optional<std::string> Title;
|
||||
std::optional<std::string> Type;
|
||||
std::optional<std::string> Description;
|
||||
std::optional<std::string> URL;
|
||||
std::optional<std::string> Timestamp;
|
||||
std::optional<int> Color;
|
||||
std::optional<EmbedFooterData> Footer;
|
||||
std::optional<EmbedImageData> Image;
|
||||
std::optional<EmbedThumbnailData> Thumbnail;
|
||||
std::optional<EmbedVideoData> Video;
|
||||
std::optional<EmbedProviderData> Provider;
|
||||
std::optional<EmbedAuthorData> Author;
|
||||
std::optional<std::vector<EmbedFieldData>> Fields;
|
||||
|
||||
friend void to_json(nlohmann::json &j, const EmbedData &m);
|
||||
friend void from_json(const nlohmann::json &j, EmbedData &m);
|
||||
};
|
||||
|
||||
struct AttachmentData {
|
||||
Snowflake ID; //
|
||||
std::string Filename; //
|
||||
int Bytes; //
|
||||
std::string URL; //
|
||||
std::string ProxyURL; //
|
||||
int Height = -1; // opt, null
|
||||
int Width = -1; // opt, null
|
||||
Snowflake ID;
|
||||
std::string Filename;
|
||||
int Bytes;
|
||||
std::string URL;
|
||||
std::string ProxyURL;
|
||||
std::optional<int> Height; // null
|
||||
std::optional<int> Width; // null
|
||||
|
||||
friend void to_json(nlohmann::json &j, const AttachmentData &m);
|
||||
friend void from_json(const nlohmann::json &j, AttachmentData &m);
|
||||
};
|
||||
|
||||
|
@ -141,7 +151,7 @@ struct Message {
|
|||
std::string EditedTimestamp; // null
|
||||
bool IsTTS;
|
||||
bool DoesMentionEveryone;
|
||||
std::vector<User> Mentions;
|
||||
std::vector<User> Mentions; // currently discarded in store
|
||||
// std::vector<Role> MentionRoles;
|
||||
// std::optional<std::vector<ChannelMentionData>> MentionChannels;
|
||||
std::vector<AttachmentData> Attachments;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
void from_json(const nlohmann::json &j, PermissionOverwrite &m) {
|
||||
JS_D("id", m.ID);
|
||||
std::string tmp;
|
||||
m.ID = j.at("type").get<int>() == 0 ? PermissionOverwrite::ROLE : PermissionOverwrite::MEMBER;
|
||||
m.Type = j.at("type").get<int>() == 0 ? PermissionOverwrite::ROLE : PermissionOverwrite::MEMBER;
|
||||
JS_D("allow", tmp);
|
||||
m.Allow = static_cast<Permission>(std::stoull(tmp));
|
||||
JS_D("deny", tmp);
|
||||
|
|
|
@ -46,9 +46,9 @@ struct Bitwise<Permission> {
|
|||
};
|
||||
|
||||
struct PermissionOverwrite {
|
||||
enum OverwriteType {
|
||||
ROLE,
|
||||
MEMBER,
|
||||
enum OverwriteType : uint8_t {
|
||||
ROLE = 0,
|
||||
MEMBER = 1,
|
||||
};
|
||||
|
||||
Snowflake ID;
|
||||
|
|
|
@ -1,12 +1,23 @@
|
|||
#include "sticker.hpp"
|
||||
|
||||
void to_json(nlohmann::json &j, const Sticker &m) {
|
||||
j["id"] = m.ID;
|
||||
j["pack_id"] = m.PackID;
|
||||
j["name"] = m.Name;
|
||||
j["description"] = m.Description;
|
||||
JS_IF("tags", m.Tags);
|
||||
JS_IF("asset", m.AssetHash);
|
||||
JS_IF("preview_asset", m.PreviewAssetHash);
|
||||
j["format_type"] = m.FormatType;
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json &j, Sticker &m) {
|
||||
JS_D("id", m.ID);
|
||||
JS_D("pack_id", m.PackID);
|
||||
JS_D("name", m.Name);
|
||||
JS_D("description", m.Description);
|
||||
JS_O("tags", m.Tags);
|
||||
JS_D("asset", m.AssetHash);
|
||||
JS_O("asset", m.AssetHash);
|
||||
JS_N("preview_asset", m.PreviewAssetHash);
|
||||
JS_D("format_type", m.FormatType);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ struct Sticker {
|
|||
std::optional<std::string> PreviewAssetHash;
|
||||
StickerFormatType FormatType;
|
||||
|
||||
friend void to_json(nlohmann::json &j, const Sticker &m);
|
||||
friend void from_json(const nlohmann::json &j, Sticker &m);
|
||||
|
||||
std::string GetURL() const;
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
#include "store.hpp"
|
||||
|
||||
using namespace std::literals::string_literals;
|
||||
|
||||
// hopefully the casting between signed and unsigned int64 doesnt cause issues
|
||||
|
||||
Store::Store() {
|
||||
m_db_path = std::filesystem::temp_directory_path() / "abaddon-store.db";
|
||||
m_db_err = sqlite3_open(m_db_path.string().c_str(), &m_db);
|
||||
Store::Store(bool mem_store) {
|
||||
if (mem_store) {
|
||||
m_db_path = ":memory:";
|
||||
m_db_err = sqlite3_open(":memory:", &m_db);
|
||||
} else {
|
||||
m_db_path = std::filesystem::temp_directory_path() / "abaddon-store.db";
|
||||
m_db_err = sqlite3_open(m_db_path.string().c_str(), &m_db);
|
||||
}
|
||||
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "error opening database: %s\n", sqlite3_errstr(m_db_err));
|
||||
return;
|
||||
|
@ -35,7 +43,8 @@ Store::~Store() {
|
|||
return;
|
||||
}
|
||||
|
||||
std::filesystem::remove(m_db_path);
|
||||
if (m_db_path != ":memory:")
|
||||
std::filesystem::remove(m_db_path);
|
||||
}
|
||||
|
||||
bool Store::IsValid() const {
|
||||
|
@ -43,10 +52,6 @@ bool Store::IsValid() const {
|
|||
}
|
||||
|
||||
void Store::SetUser(Snowflake id, const User &user) {
|
||||
if ((uint64_t)id == 0) {
|
||||
printf("???: %s\n", user.Username.c_str());
|
||||
}
|
||||
|
||||
Bind(m_set_user_stmt, 1, id);
|
||||
Bind(m_set_user_stmt, 2, user.Username);
|
||||
Bind(m_set_user_stmt, 3, user.Discriminator);
|
||||
|
@ -64,8 +69,6 @@ void Store::SetUser(Snowflake id, const User &user) {
|
|||
if (!RunInsert(m_set_user_stmt)) {
|
||||
fprintf(stderr, "user insert failed: %s\n", sqlite3_errstr(m_db_err));
|
||||
}
|
||||
|
||||
// m_users[id] = user;
|
||||
}
|
||||
|
||||
void Store::SetChannel(Snowflake id, const Channel &channel) {
|
||||
|
@ -77,11 +80,65 @@ void Store::SetGuild(Snowflake id, const Guild &guild) {
|
|||
}
|
||||
|
||||
void Store::SetRole(Snowflake id, const Role &role) {
|
||||
m_roles[id] = role;
|
||||
Bind(m_set_role_stmt, 1, id);
|
||||
Bind(m_set_role_stmt, 2, role.Name);
|
||||
Bind(m_set_role_stmt, 3, role.Color);
|
||||
Bind(m_set_role_stmt, 4, role.IsHoisted);
|
||||
Bind(m_set_role_stmt, 5, role.Position);
|
||||
Bind(m_set_role_stmt, 6, static_cast<uint64_t>(role.Permissions));
|
||||
Bind(m_set_role_stmt, 7, role.IsManaged);
|
||||
Bind(m_set_role_stmt, 8, role.IsMentionable);
|
||||
|
||||
if (!RunInsert(m_set_role_stmt))
|
||||
fprintf(stderr, "role insert failed: %s\n", sqlite3_errstr(m_db_err));
|
||||
}
|
||||
|
||||
void Store::SetMessage(Snowflake id, const Message &message) {
|
||||
m_messages[id] = message;
|
||||
Bind(m_set_msg_stmt, 1, id);
|
||||
Bind(m_set_msg_stmt, 2, message.ChannelID);
|
||||
Bind(m_set_msg_stmt, 3, message.GuildID);
|
||||
Bind(m_set_msg_stmt, 4, message.Author.ID);
|
||||
Bind(m_set_msg_stmt, 5, message.Content);
|
||||
Bind(m_set_msg_stmt, 6, message.Timestamp);
|
||||
Bind(m_set_msg_stmt, 7, message.EditedTimestamp);
|
||||
Bind(m_set_msg_stmt, 8, message.IsTTS);
|
||||
Bind(m_set_msg_stmt, 9, message.DoesMentionEveryone);
|
||||
Bind(m_set_msg_stmt, 10, "[]"s); // mentions
|
||||
{
|
||||
std::string tmp;
|
||||
tmp = nlohmann::json(message.Attachments).dump();
|
||||
Bind(m_set_msg_stmt, 11, tmp);
|
||||
}
|
||||
{
|
||||
std::string tmp = nlohmann::json(message.Embeds).dump();
|
||||
Bind(m_set_msg_stmt, 12, tmp);
|
||||
}
|
||||
Bind(m_set_msg_stmt, 13, message.IsPinned);
|
||||
Bind(m_set_msg_stmt, 14, message.WebhookID);
|
||||
Bind(m_set_msg_stmt, 15, static_cast<uint64_t>(message.Type));
|
||||
|
||||
if (message.MessageReference.has_value()) {
|
||||
std::string tmp = nlohmann::json(*message.MessageReference).dump();
|
||||
Bind(m_set_msg_stmt, 16, tmp);
|
||||
} else
|
||||
Bind(m_set_msg_stmt, 16, nullptr);
|
||||
|
||||
if (message.Flags.has_value())
|
||||
Bind(m_set_msg_stmt, 17, static_cast<uint64_t>(*message.Flags));
|
||||
else
|
||||
Bind(m_set_msg_stmt, 17, nullptr);
|
||||
|
||||
if (message.Stickers.has_value()) {
|
||||
std::string tmp = nlohmann::json(*message.Stickers).dump();
|
||||
Bind(m_set_msg_stmt, 18, tmp);
|
||||
} else
|
||||
Bind(m_set_msg_stmt, 18, nullptr);
|
||||
|
||||
Bind(m_set_msg_stmt, 19, message.IsDeleted());
|
||||
Bind(m_set_msg_stmt, 20, message.IsEdited());
|
||||
|
||||
if (!RunInsert(m_set_msg_stmt))
|
||||
fprintf(stderr, "message insert failed: %s\n", sqlite3_errstr(m_db_err));
|
||||
}
|
||||
|
||||
void Store::SetGuildMemberData(Snowflake guild_id, Snowflake user_id, const GuildMember &data) {
|
||||
|
@ -89,17 +146,146 @@ void Store::SetGuildMemberData(Snowflake guild_id, Snowflake user_id, const Guil
|
|||
}
|
||||
|
||||
void Store::SetPermissionOverwrite(Snowflake channel_id, Snowflake id, const PermissionOverwrite &perm) {
|
||||
m_permissions[channel_id][id] = perm;
|
||||
Bind(m_set_perm_stmt, 1, perm.ID);
|
||||
Bind(m_set_perm_stmt, 2, channel_id);
|
||||
Bind(m_set_perm_stmt, 3, static_cast<int>(perm.Type));
|
||||
Bind(m_set_perm_stmt, 4, static_cast<uint64_t>(perm.Allow));
|
||||
Bind(m_set_perm_stmt, 5, static_cast<uint64_t>(perm.Deny));
|
||||
|
||||
if (!RunInsert(m_set_perm_stmt))
|
||||
fprintf(stderr, "permission insert failed: %s\n", sqlite3_errstr(m_db_err));
|
||||
}
|
||||
|
||||
void Store::SetEmoji(Snowflake id, const Emoji &emoji) {
|
||||
Bind(m_set_emote_stmt, 1, id);
|
||||
Bind(m_set_emote_stmt, 2, emoji.Name);
|
||||
|
||||
if (emoji.Roles.has_value())
|
||||
Bind(m_set_emote_stmt, 3, nlohmann::json(*emoji.Roles).dump());
|
||||
else
|
||||
Bind(m_set_emote_stmt, 3, nullptr);
|
||||
|
||||
if (emoji.Creator.has_value())
|
||||
Bind(m_set_emote_stmt, 4, emoji.Creator->ID);
|
||||
else
|
||||
Bind(m_set_emote_stmt, 4, nullptr);
|
||||
|
||||
Bind(m_set_emote_stmt, 5, emoji.NeedsColons);
|
||||
Bind(m_set_emote_stmt, 6, emoji.IsManaged);
|
||||
Bind(m_set_emote_stmt, 7, emoji.IsAnimated);
|
||||
Bind(m_set_emote_stmt, 8, emoji.IsAvailable);
|
||||
|
||||
if (!RunInsert(m_set_emote_stmt))
|
||||
fprintf(stderr, "emoji insert failed: %s\n", sqlite3_errstr(m_db_err));
|
||||
|
||||
m_emojis[id] = emoji;
|
||||
}
|
||||
|
||||
std::optional<Message> Store::GetMessage(Snowflake id) const {
|
||||
Bind(m_get_msg_stmt, 1, id);
|
||||
if (!FetchOne(m_get_msg_stmt)) {
|
||||
if (m_db_err != SQLITE_DONE)
|
||||
fprintf(stderr, "error while fetching message: %s\n", sqlite3_errstr(m_db_err));
|
||||
Reset(m_get_msg_stmt);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
Message ret;
|
||||
ret.ID = id;
|
||||
Get(m_get_msg_stmt, 1, ret.ChannelID);
|
||||
Get(m_get_msg_stmt, 2, ret.GuildID);
|
||||
Get(m_get_msg_stmt, 3, ret.Author.ID); // yike
|
||||
Get(m_get_msg_stmt, 4, ret.Content);
|
||||
Get(m_get_msg_stmt, 5, ret.Timestamp);
|
||||
Get(m_get_msg_stmt, 6, ret.EditedTimestamp);
|
||||
Get(m_get_msg_stmt, 7, ret.IsTTS);
|
||||
Get(m_get_msg_stmt, 8, ret.DoesMentionEveryone);
|
||||
std::string tmps;
|
||||
Get(m_get_msg_stmt, 9, tmps);
|
||||
nlohmann::json::parse(tmps).get_to(ret.Mentions);
|
||||
Get(m_get_msg_stmt, 10, tmps);
|
||||
nlohmann::json::parse(tmps).get_to(ret.Attachments);
|
||||
Get(m_get_msg_stmt, 11, tmps);
|
||||
nlohmann::json::parse(tmps).get_to(ret.Embeds);
|
||||
Get(m_get_msg_stmt, 12, ret.IsPinned);
|
||||
Get(m_get_msg_stmt, 13, ret.WebhookID);
|
||||
uint64_t tmpi;
|
||||
Get(m_get_msg_stmt, 14, tmpi);
|
||||
ret.Type = static_cast<MessageType>(tmpi);
|
||||
Get(m_get_msg_stmt, 15, tmps);
|
||||
if (tmps != "")
|
||||
ret.MessageReference = nlohmann::json::parse(tmps).get<MessageReferenceData>();
|
||||
Get(m_get_msg_stmt, 16, tmpi);
|
||||
ret.Flags = static_cast<MessageFlags>(tmpi);
|
||||
Get(m_get_msg_stmt, 17, tmps);
|
||||
if (tmps != "")
|
||||
ret.Stickers = nlohmann::json::parse(tmps).get<std::vector<Sticker>>();
|
||||
bool tmpb = false;
|
||||
Get(m_get_msg_stmt, 18, tmpb);
|
||||
if (tmpb) ret.SetDeleted();
|
||||
Get(m_get_msg_stmt, 19, tmpb);
|
||||
if (tmpb) ret.SetEdited();
|
||||
|
||||
Reset(m_get_msg_stmt);
|
||||
|
||||
return std::optional<Message>(std::move(ret));
|
||||
}
|
||||
|
||||
std::optional<PermissionOverwrite> Store::GetPermissionOverwrite(Snowflake channel_id, Snowflake id) const {
|
||||
Bind(m_get_perm_stmt, 1, id);
|
||||
Bind(m_get_perm_stmt, 2, channel_id);
|
||||
if (!FetchOne(m_get_perm_stmt)) {
|
||||
if (m_db_err != SQLITE_DONE)
|
||||
fprintf(stderr, "error while fetching permission: %s\n", sqlite3_errstr(m_db_err));
|
||||
Reset(m_get_perm_stmt);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
PermissionOverwrite ret;
|
||||
ret.ID = id;
|
||||
uint64_t tmp;
|
||||
Get(m_get_perm_stmt, 2, tmp);
|
||||
ret.Type = static_cast<PermissionOverwrite::OverwriteType>(tmp);
|
||||
Get(m_get_perm_stmt, 3, tmp);
|
||||
ret.Allow = static_cast<Permission>(tmp);
|
||||
Get(m_get_perm_stmt, 4, tmp);
|
||||
ret.Deny = static_cast<Permission>(tmp);
|
||||
|
||||
Reset(m_get_perm_stmt);
|
||||
|
||||
return std::optional<PermissionOverwrite>(std::move(ret));
|
||||
}
|
||||
|
||||
std::optional<Role> Store::GetRole(Snowflake id) const {
|
||||
Bind(m_get_role_stmt, 1, id);
|
||||
if (!FetchOne(m_get_role_stmt)) {
|
||||
if (m_db_err != SQLITE_DONE)
|
||||
fprintf(stderr, "error while fetching role: %s\n", sqlite3_errstr(m_db_err));
|
||||
Reset(m_get_role_stmt);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
Role ret;
|
||||
ret.ID = id;
|
||||
Get(m_get_role_stmt, 1, ret.Name);
|
||||
Get(m_get_role_stmt, 2, ret.Color);
|
||||
Get(m_get_role_stmt, 3, ret.IsHoisted);
|
||||
Get(m_get_role_stmt, 4, ret.Position);
|
||||
uint64_t tmp;
|
||||
Get(m_get_role_stmt, 5, tmp);
|
||||
ret.Permissions = static_cast<Permission>(tmp);
|
||||
Get(m_get_role_stmt, 6, ret.IsManaged);
|
||||
Get(m_get_role_stmt, 7, ret.IsMentionable);
|
||||
|
||||
Reset(m_get_role_stmt);
|
||||
|
||||
return std::optional<Role>(std::move(ret));
|
||||
}
|
||||
|
||||
std::optional<User> Store::GetUser(Snowflake id) const {
|
||||
Bind(m_get_user_stmt, 1, id);
|
||||
if (!FetchOne(m_get_user_stmt)) {
|
||||
if (m_db_err != SQLITE_DONE) // not an error, just means user isnt found
|
||||
if (m_db_err != SQLITE_DONE)
|
||||
fprintf(stderr, "error while fetching user info: %s\n", sqlite3_errstr(m_db_err));
|
||||
Reset(m_get_user_stmt);
|
||||
return std::nullopt;
|
||||
|
@ -153,34 +339,6 @@ const Guild *Store::GetGuild(Snowflake id) const {
|
|||
return &it->second;
|
||||
}
|
||||
|
||||
Role *Store::GetRole(Snowflake id) {
|
||||
auto it = m_roles.find(id);
|
||||
if (it == m_roles.end())
|
||||
return nullptr;
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
const Role *Store::GetRole(Snowflake id) const {
|
||||
auto it = m_roles.find(id);
|
||||
if (it == m_roles.end())
|
||||
return nullptr;
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
Message *Store::GetMessage(Snowflake id) {
|
||||
auto it = m_messages.find(id);
|
||||
if (it == m_messages.end())
|
||||
return nullptr;
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
const Message *Store::GetMessage(Snowflake id) const {
|
||||
auto it = m_messages.find(id);
|
||||
if (it == m_messages.end())
|
||||
return nullptr;
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
GuildMember *Store::GetGuildMemberData(Snowflake guild_id, Snowflake user_id) {
|
||||
auto git = m_members.find(guild_id);
|
||||
if (git == m_members.end())
|
||||
|
@ -191,16 +349,6 @@ GuildMember *Store::GetGuildMemberData(Snowflake guild_id, Snowflake user_id) {
|
|||
return &mit->second;
|
||||
}
|
||||
|
||||
PermissionOverwrite *Store::GetPermissionOverwrite(Snowflake channel_id, Snowflake id) {
|
||||
auto cit = m_permissions.find(channel_id);
|
||||
if (cit == m_permissions.end())
|
||||
return nullptr;
|
||||
auto pit = cit->second.find(id);
|
||||
if (pit == cit->second.end())
|
||||
return nullptr;
|
||||
return &pit->second;
|
||||
}
|
||||
|
||||
Emoji *Store::GetEmoji(Snowflake id) {
|
||||
auto it = m_emojis.find(id);
|
||||
if (it != m_emojis.end())
|
||||
|
@ -218,16 +366,6 @@ const GuildMember *Store::GetGuildMemberData(Snowflake guild_id, Snowflake user_
|
|||
return &mit->second;
|
||||
}
|
||||
|
||||
const PermissionOverwrite *Store::GetPermissionOverwrite(Snowflake channel_id, Snowflake id) const {
|
||||
auto cit = m_permissions.find(channel_id);
|
||||
if (cit == m_permissions.end())
|
||||
return nullptr;
|
||||
auto pit = cit->second.find(id);
|
||||
if (pit == cit->second.end())
|
||||
return nullptr;
|
||||
return &pit->second;
|
||||
}
|
||||
|
||||
const Emoji *Store::GetEmoji(Snowflake id) const {
|
||||
auto it = m_emojis.find(id);
|
||||
if (it != m_emojis.end())
|
||||
|
@ -250,20 +388,11 @@ const Store::channels_type &Store::GetChannels() const {
|
|||
const Store::guilds_type &Store::GetGuilds() const {
|
||||
return m_guilds;
|
||||
}
|
||||
|
||||
const Store::roles_type &Store::GetRoles() const {
|
||||
return m_roles;
|
||||
}
|
||||
|
||||
void Store::ClearAll() {
|
||||
m_channels.clear();
|
||||
m_emojis.clear();
|
||||
m_guilds.clear();
|
||||
m_members.clear();
|
||||
m_messages.clear();
|
||||
m_permissions.clear();
|
||||
m_roles.clear();
|
||||
m_users.clear();
|
||||
}
|
||||
|
||||
void Store::BeginTransaction() {
|
||||
|
@ -291,11 +420,97 @@ flags INTEGER,
|
|||
premium INTEGER,
|
||||
pubflags INTEGER
|
||||
)
|
||||
)";
|
||||
|
||||
constexpr const char *create_permissions = R"(
|
||||
CREATE TABLE IF NOT EXISTS permissions (
|
||||
id INTEGER NOT NULL,
|
||||
channel_id INTEGER NOT NULL,
|
||||
type INTEGER NOT NULL,
|
||||
allow INTEGER NOT NULL,
|
||||
deny INTEGER NOT NULL
|
||||
)
|
||||
)";
|
||||
|
||||
constexpr const char *create_messages = R"(
|
||||
CREATE TABLE IF NOT EXISTS messages (
|
||||
id INTEGER PRIMARY KEY,
|
||||
channel_id INTEGER NOT NULL,
|
||||
guild_id INTEGER,
|
||||
author_id INTEGER NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
timestamp TEXT NOT NULL,
|
||||
edited_timestamp TEXT,
|
||||
tts BOOL NOT NULL,
|
||||
everyone BOOL NOT NULL,
|
||||
mentions TEXT NOT NULL, /* json */
|
||||
attachments TEXT NOT NULL, /* json */
|
||||
embeds TEXT NOT NULL, /* json */
|
||||
pinned BOOL,
|
||||
webhook_id INTEGER,
|
||||
type INTEGER,
|
||||
reference TEXT, /* json */
|
||||
flags INTEGER,
|
||||
stickers TEXT, /* json */
|
||||
/* extra */
|
||||
deleted BOOL,
|
||||
edited BOOL
|
||||
)
|
||||
)";
|
||||
|
||||
constexpr const char *create_roles = R"(
|
||||
CREATE TABLE IF NOT EXISTS roles (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
color INTEGER NOT NULL,
|
||||
hoisted BOOL NOT NULL,
|
||||
position INTEGER NOT NULL,
|
||||
permissions INTEGER NOT NULL,
|
||||
managed BOOL NOT NULL,
|
||||
mentionable BOOL NOT NULL
|
||||
)
|
||||
)";
|
||||
|
||||
constexpr const char *create_emojis = R"(
|
||||
CREATE TABLE IF NOT EXISTS emojis (
|
||||
id INTEGER PRIMARY KEY, /*though nullable, only custom emojis (with non-null ids) are stored*/
|
||||
name TEXT NOT NULL, /*same as id*/
|
||||
roles TEXT, /* json */
|
||||
creator_id INTEGER,
|
||||
colons BOOL,
|
||||
managed BOOL,
|
||||
animated BOOL,
|
||||
available BOOL
|
||||
)
|
||||
)";
|
||||
|
||||
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\n");
|
||||
fprintf(stderr, "failed to create user table: %s\n", sqlite3_errstr(m_db_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_db_err = sqlite3_exec(m_db, create_permissions, nullptr, nullptr, nullptr);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "failed to create permissions table: %s\n", sqlite3_errstr(m_db_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_db_err = sqlite3_exec(m_db, create_messages, nullptr, nullptr, nullptr);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "failed to create messages table: %s\n", sqlite3_errstr(m_db_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_db_err = sqlite3_exec(m_db, create_roles, nullptr, nullptr, nullptr);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "failed to create roles table: %s\n", sqlite3_errstr(m_db_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_db_err = sqlite3_exec(m_db, create_emojis, nullptr, nullptr, nullptr);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "faile to create emojis table: %s\n", sqlite3_errstr(m_db_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -311,17 +526,105 @@ REPLACE INTO users VALUES (
|
|||
|
||||
constexpr const char *get_user = R"(
|
||||
SELECT * FROM users WHERE id = ?
|
||||
)";
|
||||
|
||||
constexpr const char *set_perm = R"(
|
||||
REPLACE INTO permissions VALUES (
|
||||
?, ?, ?, ?, ?
|
||||
)
|
||||
)";
|
||||
|
||||
constexpr const char *get_perm = R"(
|
||||
SELECT * FROM permissions WHERE id = ? AND channel_id = ?
|
||||
)";
|
||||
|
||||
constexpr const char *set_msg = R"(
|
||||
REPLACE INTO messages VALUES (
|
||||
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
|
||||
)
|
||||
)";
|
||||
|
||||
constexpr const char *get_msg = R"(
|
||||
SELECT * FROM messages WHERE id = ?
|
||||
)";
|
||||
|
||||
constexpr const char *set_role = R"(
|
||||
REPLACE INTO roles VALUES (
|
||||
?, ?, ?, ?, ?, ?, ?, ?
|
||||
)
|
||||
)";
|
||||
|
||||
constexpr const char *get_role = R"(
|
||||
SELECT * FROM roles WHERE id = ?
|
||||
)";
|
||||
|
||||
constexpr const char *set_emoji = R"(
|
||||
REPLACE INTO emojis VALUES (
|
||||
?, ?, ?, ?, ?, ?, ?, ?
|
||||
)
|
||||
)";
|
||||
|
||||
constexpr const char *get_emoji = R"(
|
||||
SELECT * FROM emojis WHERE 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\n");
|
||||
fprintf(stderr, "failed to prepare set user statement: %s\n", sqlite3_errstr(m_db_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_db_err = sqlite3_prepare_v2(m_db, get_user, -1, &m_get_user_stmt, nullptr);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "failed to prepare get user statement\n");
|
||||
fprintf(stderr, "failed to prepare get user statement: %s\n", sqlite3_errstr(m_db_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_db_err = sqlite3_prepare_v2(m_db, set_perm, -1, &m_set_perm_stmt, nullptr);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "failed to prepare set permission statement: %s\n", sqlite3_errstr(m_db_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_db_err = sqlite3_prepare_v2(m_db, get_perm, -1, &m_get_perm_stmt, nullptr);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "failed to prepare get permission statement: %s\n", sqlite3_errstr(m_db_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_db_err = sqlite3_prepare_v2(m_db, set_msg, -1, &m_set_msg_stmt, nullptr);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "failed to prepare set message statement: %s\n", sqlite3_errstr(m_db_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_db_err = sqlite3_prepare_v2(m_db, get_msg, -1, &m_get_msg_stmt, nullptr);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "failed to prepare get message statement: %s\n", sqlite3_errstr(m_db_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_db_err = sqlite3_prepare_v2(m_db, set_role, -1, &m_set_role_stmt, nullptr);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "failed to prepare set role statement: %s\n", sqlite3_errstr(m_db_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_db_err = sqlite3_prepare_v2(m_db, get_role, -1, &m_get_role_stmt, nullptr);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "failed to prepare get role statement: %s\n", sqlite3_errstr(m_db_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_db_err = sqlite3_prepare_v2(m_db, set_emoji, -1, &m_set_emote_stmt, nullptr);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "failed to prepare set emoji statement: %s\n", sqlite3_errstr(m_db_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_db_err = sqlite3_prepare_v2(m_db, get_emoji, -1, &m_get_emote_stmt, nullptr);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "failed to prepare get emoji statement: %s\n", sqlite3_errstr(m_db_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -331,6 +634,14 @@ SELECT * FROM users WHERE id = ?
|
|||
void Store::Cleanup() {
|
||||
sqlite3_finalize(m_set_user_stmt);
|
||||
sqlite3_finalize(m_get_user_stmt);
|
||||
sqlite3_finalize(m_set_perm_stmt);
|
||||
sqlite3_finalize(m_get_perm_stmt);
|
||||
sqlite3_finalize(m_set_msg_stmt);
|
||||
sqlite3_finalize(m_get_msg_stmt);
|
||||
sqlite3_finalize(m_set_role_stmt);
|
||||
sqlite3_finalize(m_get_role_stmt);
|
||||
sqlite3_finalize(m_set_emote_stmt);
|
||||
sqlite3_finalize(m_get_emote_stmt);
|
||||
}
|
||||
|
||||
void Store::Bind(sqlite3_stmt *stmt, int index, int num) const {
|
||||
|
@ -348,7 +659,7 @@ void Store::Bind(sqlite3_stmt *stmt, int index, uint64_t num) const {
|
|||
}
|
||||
|
||||
void Store::Bind(sqlite3_stmt *stmt, int index, const std::string &str) const {
|
||||
m_db_err = sqlite3_bind_text(stmt, index, str.c_str(), -1, nullptr);
|
||||
m_db_err = sqlite3_bind_blob(stmt, index, str.c_str(), str.length(), SQLITE_TRANSIENT);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "error binding index %d: %s\n", index, sqlite3_errstr(m_db_err));
|
||||
}
|
||||
|
@ -361,10 +672,16 @@ void Store::Bind(sqlite3_stmt *stmt, int index, bool val) const {
|
|||
}
|
||||
}
|
||||
|
||||
void Store::Bind(sqlite3_stmt *stmt, int index, std::nullptr_t) const {
|
||||
m_db_err = sqlite3_bind_null(stmt, index);
|
||||
if (m_db_err != SQLITE_OK) {
|
||||
fprintf(stderr, "error binding index %d: %s\n", index, sqlite3_errstr(m_db_err));
|
||||
}
|
||||
}
|
||||
|
||||
bool Store::RunInsert(sqlite3_stmt *stmt) {
|
||||
m_db_err = sqlite3_step(stmt);
|
||||
sqlite3_reset(stmt);
|
||||
sqlite3_clear_bindings(stmt);
|
||||
Reset(stmt);
|
||||
return m_db_err == SQLITE_DONE;
|
||||
}
|
||||
|
||||
|
@ -377,6 +694,10 @@ void Store::Get(sqlite3_stmt *stmt, int index, int &out) const {
|
|||
out = sqlite3_column_int(stmt, index);
|
||||
}
|
||||
|
||||
void Store::Get(sqlite3_stmt *stmt, int index, uint64_t &out) const {
|
||||
out = sqlite3_column_int64(stmt, index);
|
||||
}
|
||||
|
||||
void Store::Get(sqlite3_stmt *stmt, int index, std::string &out) const {
|
||||
const unsigned char *ptr = sqlite3_column_text(stmt, index);
|
||||
if (ptr == nullptr)
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
class Store {
|
||||
public:
|
||||
Store();
|
||||
Store(bool mem_store = false);
|
||||
~Store();
|
||||
|
||||
bool IsValid() const;
|
||||
|
@ -30,18 +30,15 @@ public:
|
|||
|
||||
Channel *GetChannel(Snowflake id);
|
||||
Guild *GetGuild(Snowflake id);
|
||||
Role *GetRole(Snowflake id);
|
||||
Message *GetMessage(Snowflake id);
|
||||
GuildMember *GetGuildMemberData(Snowflake guild_id, Snowflake user_id);
|
||||
PermissionOverwrite *GetPermissionOverwrite(Snowflake channel_id, Snowflake id);
|
||||
Emoji *GetEmoji(Snowflake id);
|
||||
std::optional<Message> GetMessage(Snowflake id) const;
|
||||
std::optional<PermissionOverwrite> GetPermissionOverwrite(Snowflake channel_id, Snowflake id) const;
|
||||
std::optional<Role> GetRole(Snowflake id) const;
|
||||
std::optional<User> GetUser(Snowflake id) const;
|
||||
const Channel *GetChannel(Snowflake id) const;
|
||||
const Guild *GetGuild(Snowflake id) const;
|
||||
const Role *GetRole(Snowflake id) const;
|
||||
const Message *GetMessage(Snowflake id) const;
|
||||
const GuildMember *GetGuildMemberData(Snowflake guild_id, Snowflake user_id) const;
|
||||
const PermissionOverwrite *GetPermissionOverwrite(Snowflake channel_id, Snowflake id) const;
|
||||
const Emoji *GetEmoji(Snowflake id) const;
|
||||
|
||||
void ClearGuild(Snowflake id);
|
||||
|
@ -58,7 +55,6 @@ public:
|
|||
|
||||
const channels_type &GetChannels() const;
|
||||
const guilds_type &GetGuilds() const;
|
||||
const roles_type &GetRoles() const;
|
||||
|
||||
void ClearAll();
|
||||
|
||||
|
@ -66,13 +62,9 @@ public:
|
|||
void EndTransaction();
|
||||
|
||||
private:
|
||||
users_type m_users;
|
||||
channels_type m_channels;
|
||||
guilds_type m_guilds;
|
||||
roles_type m_roles;
|
||||
messages_type m_messages;
|
||||
members_type m_members;
|
||||
permission_overwrites_type m_permissions;
|
||||
emojis_type m_emojis;
|
||||
|
||||
bool CreateTables();
|
||||
|
@ -85,6 +77,7 @@ private:
|
|||
void Bind(sqlite3_stmt *stmt, int index, uint64_t num) const;
|
||||
void Bind(sqlite3_stmt *stmt, int index, const std::string &str) const;
|
||||
void Bind(sqlite3_stmt *stmt, int index, bool val) const;
|
||||
void Bind(sqlite3_stmt *stmt, int index, std::nullptr_t) const;
|
||||
bool RunInsert(sqlite3_stmt *stmt);
|
||||
bool FetchOne(sqlite3_stmt *stmt) const;
|
||||
template<typename T>
|
||||
|
@ -101,6 +94,14 @@ private:
|
|||
mutable int m_db_err;
|
||||
mutable sqlite3_stmt *m_set_user_stmt;
|
||||
mutable sqlite3_stmt *m_get_user_stmt;
|
||||
mutable sqlite3_stmt *m_set_perm_stmt;
|
||||
mutable sqlite3_stmt *m_get_perm_stmt;
|
||||
mutable sqlite3_stmt *m_set_msg_stmt;
|
||||
mutable sqlite3_stmt *m_get_msg_stmt;
|
||||
mutable sqlite3_stmt *m_set_role_stmt;
|
||||
mutable sqlite3_stmt *m_get_role_stmt;
|
||||
mutable sqlite3_stmt *m_set_emote_stmt;
|
||||
mutable sqlite3_stmt *m_get_emote_stmt;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
|
Loading…
Reference in New Issue
Block a user