display reactions + click to add/remove
This commit is contained in:
20
abaddon.cpp
20
abaddon.cpp
@@ -35,6 +35,8 @@ Abaddon::Abaddon()
|
|||||||
m_discord.signal_channel_update().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnChannelUpdate));
|
m_discord.signal_channel_update().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnChannelUpdate));
|
||||||
m_discord.signal_channel_create().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnChannelCreate));
|
m_discord.signal_channel_create().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnChannelCreate));
|
||||||
m_discord.signal_guild_update().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnGuildUpdate));
|
m_discord.signal_guild_update().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnGuildUpdate));
|
||||||
|
m_discord.signal_reaction_add().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnReactionAdd));
|
||||||
|
m_discord.signal_reaction_remove().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnReactionRemove));
|
||||||
}
|
}
|
||||||
|
|
||||||
Abaddon::~Abaddon() {
|
Abaddon::~Abaddon() {
|
||||||
@@ -98,6 +100,8 @@ int Abaddon::StartGTK() {
|
|||||||
m_main_window->GetChatWindow()->signal_action_chat_load_history().connect(sigc::mem_fun(*this, &Abaddon::ActionChatLoadHistory));
|
m_main_window->GetChatWindow()->signal_action_chat_load_history().connect(sigc::mem_fun(*this, &Abaddon::ActionChatLoadHistory));
|
||||||
m_main_window->GetChatWindow()->signal_action_channel_click().connect(sigc::mem_fun(*this, &Abaddon::ActionChannelOpened));
|
m_main_window->GetChatWindow()->signal_action_channel_click().connect(sigc::mem_fun(*this, &Abaddon::ActionChannelOpened));
|
||||||
m_main_window->GetChatWindow()->signal_action_insert_mention().connect(sigc::mem_fun(*this, &Abaddon::ActionInsertMention));
|
m_main_window->GetChatWindow()->signal_action_insert_mention().connect(sigc::mem_fun(*this, &Abaddon::ActionInsertMention));
|
||||||
|
m_main_window->GetChatWindow()->signal_action_reaction_add().connect(sigc::mem_fun(*this, &Abaddon::ActionReactionAdd));
|
||||||
|
m_main_window->GetChatWindow()->signal_action_reaction_remove().connect(sigc::mem_fun(*this, &Abaddon::ActionReactionRemove));
|
||||||
|
|
||||||
ActionReloadCSS();
|
ActionReloadCSS();
|
||||||
|
|
||||||
@@ -203,6 +207,14 @@ void Abaddon::DiscordOnGuildUpdate(Snowflake guild_id) {
|
|||||||
m_main_window->UpdateChannelsUpdateGuild(guild_id);
|
m_main_window->UpdateChannelsUpdateGuild(guild_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Abaddon::DiscordOnReactionAdd(Snowflake message_id, const Glib::ustring ¶m) {
|
||||||
|
m_main_window->UpdateChatReactionAdd(message_id, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Abaddon::DiscordOnReactionRemove(Snowflake message_id, const Glib::ustring ¶m) {
|
||||||
|
m_main_window->UpdateChatReactionAdd(message_id, param);
|
||||||
|
}
|
||||||
|
|
||||||
const SettingsManager &Abaddon::GetSettings() const {
|
const SettingsManager &Abaddon::GetSettings() const {
|
||||||
return m_settings;
|
return m_settings;
|
||||||
}
|
}
|
||||||
@@ -423,6 +435,14 @@ void Abaddon::ActionSetStatus() {
|
|||||||
m_discord.UpdateStatus(status, false, activity);
|
m_discord.UpdateStatus(status, false, activity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Abaddon::ActionReactionAdd(Snowflake id, const Glib::ustring ¶m) {
|
||||||
|
m_discord.AddReaction(id, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Abaddon::ActionReactionRemove(Snowflake id, const Glib::ustring ¶m) {
|
||||||
|
m_discord.RemoveReaction(id, param);
|
||||||
|
}
|
||||||
|
|
||||||
void Abaddon::ActionReloadCSS() {
|
void Abaddon::ActionReloadCSS() {
|
||||||
try {
|
try {
|
||||||
Gtk::StyleContext::remove_provider_for_screen(Gdk::Screen::get_default(), m_css_provider);
|
Gtk::StyleContext::remove_provider_for_screen(Gdk::Screen::get_default(), m_css_provider);
|
||||||
|
@@ -43,6 +43,8 @@ public:
|
|||||||
void ActionKickMember(Snowflake user_id, Snowflake guild_id);
|
void ActionKickMember(Snowflake user_id, Snowflake guild_id);
|
||||||
void ActionBanMember(Snowflake user_id, Snowflake guild_id);
|
void ActionBanMember(Snowflake user_id, Snowflake guild_id);
|
||||||
void ActionSetStatus();
|
void ActionSetStatus();
|
||||||
|
void ActionReactionAdd(Snowflake id, const Glib::ustring ¶m);
|
||||||
|
void ActionReactionRemove(Snowflake id, const Glib::ustring ¶m);
|
||||||
|
|
||||||
void ActionReloadCSS();
|
void ActionReloadCSS();
|
||||||
|
|
||||||
@@ -65,6 +67,8 @@ public:
|
|||||||
void DiscordOnChannelUpdate(Snowflake channel_id);
|
void DiscordOnChannelUpdate(Snowflake channel_id);
|
||||||
void DiscordOnChannelCreate(Snowflake channel_id);
|
void DiscordOnChannelCreate(Snowflake channel_id);
|
||||||
void DiscordOnGuildUpdate(Snowflake guild_id);
|
void DiscordOnGuildUpdate(Snowflake guild_id);
|
||||||
|
void DiscordOnReactionAdd(Snowflake message_id, const Glib::ustring ¶m);
|
||||||
|
void DiscordOnReactionRemove(Snowflake message_id, const Glib::ustring ¶m);
|
||||||
|
|
||||||
const SettingsManager &GetSettings() const;
|
const SettingsManager &GetSettings() const;
|
||||||
|
|
||||||
|
@@ -76,6 +76,11 @@ ChatMessageItemContainer *ChatMessageItemContainer::FromMessage(Snowflake id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data->Reactions.has_value() && data->Reactions->size() > 0) {
|
||||||
|
container->m_reactions_component = container->CreateReactionsComponent(&*data);
|
||||||
|
container->m_main->add(*container->m_reactions_component);
|
||||||
|
}
|
||||||
|
|
||||||
container->UpdateAttributes();
|
container->UpdateAttributes();
|
||||||
|
|
||||||
return container;
|
return container;
|
||||||
@@ -125,6 +130,18 @@ void ChatMessageItemContainer::UpdateImage(std::string url, Glib::RefPtr<Gdk::Pi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChatMessageItemContainer::UpdateReactions() {
|
||||||
|
if (m_reactions_component != nullptr)
|
||||||
|
delete m_reactions_component;
|
||||||
|
|
||||||
|
const auto data = Abaddon::Get().GetDiscordClient().GetMessage(ID);
|
||||||
|
if (data->Reactions.has_value() && data->Reactions->size() > 0) {
|
||||||
|
m_reactions_component = CreateReactionsComponent(&*data);
|
||||||
|
m_reactions_component->show_all();
|
||||||
|
m_main->add(*m_reactions_component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ChatMessageItemContainer::UpdateAttributes() {
|
void ChatMessageItemContainer::UpdateAttributes() {
|
||||||
const auto data = Abaddon::Get().GetDiscordClient().GetMessage(ID);
|
const auto data = Abaddon::Get().GetDiscordClient().GetMessage(ID);
|
||||||
if (!data.has_value()) return;
|
if (!data.has_value()) return;
|
||||||
@@ -395,6 +412,89 @@ Gtk::Widget *ChatMessageItemContainer::CreateStickerComponent(const Sticker &dat
|
|||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Gtk::Widget *ChatMessageItemContainer::CreateReactionsComponent(const Message *data) {
|
||||||
|
auto *flow = Gtk::manage(new Gtk::FlowBox);
|
||||||
|
flow->set_orientation(Gtk::ORIENTATION_HORIZONTAL);
|
||||||
|
flow->set_min_children_per_line(5);
|
||||||
|
flow->set_max_children_per_line(20);
|
||||||
|
flow->set_halign(Gtk::ALIGN_START);
|
||||||
|
flow->set_hexpand(false);
|
||||||
|
flow->set_column_spacing(2);
|
||||||
|
flow->set_selection_mode(Gtk::SELECTION_NONE);
|
||||||
|
|
||||||
|
auto &imgr = Abaddon::Get().GetImageManager();
|
||||||
|
auto &emojis = Abaddon::Get().GetEmojis();
|
||||||
|
const auto &placeholder = imgr.GetPlaceholder(16);
|
||||||
|
|
||||||
|
for (const auto &reaction : *data->Reactions) {
|
||||||
|
auto *ev = Gtk::manage(new Gtk::EventBox);
|
||||||
|
auto *box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
|
||||||
|
box->get_style_context()->add_class("reaction-box");
|
||||||
|
ev->add(*box);
|
||||||
|
flow->add(*ev);
|
||||||
|
|
||||||
|
bool is_stock = !reaction.Emoji.ID.IsValid();
|
||||||
|
|
||||||
|
bool has_reacted = reaction.HasReactedWith;
|
||||||
|
if (has_reacted)
|
||||||
|
box->get_style_context()->add_class("reacted");
|
||||||
|
|
||||||
|
ev->signal_button_press_event().connect([this, has_reacted, is_stock, reaction](GdkEventButton *event) -> bool {
|
||||||
|
if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_PRIMARY) {
|
||||||
|
Glib::ustring param; // escaped in client
|
||||||
|
if (is_stock)
|
||||||
|
param = reaction.Emoji.Name;
|
||||||
|
else
|
||||||
|
param = std::to_string(reaction.Emoji.ID);
|
||||||
|
if (has_reacted)
|
||||||
|
m_signal_action_reaction_remove.emit(param);
|
||||||
|
else
|
||||||
|
m_signal_action_reaction_add.emit(param);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
ev->signal_realize().connect([ev]() {
|
||||||
|
auto window = ev->get_window();
|
||||||
|
auto display = window->get_display();
|
||||||
|
auto cursor = Gdk::Cursor::create(display, "pointer");
|
||||||
|
window->set_cursor(cursor);
|
||||||
|
});
|
||||||
|
|
||||||
|
// image
|
||||||
|
if (is_stock) { // unicode/stock
|
||||||
|
const auto &pb = emojis.GetPixBuf(reaction.Emoji.Name);
|
||||||
|
auto *img = Gtk::manage(new Gtk::Image(pb->scale_simple(16, 16, Gdk::INTERP_BILINEAR)));
|
||||||
|
img->set_can_focus(false);
|
||||||
|
box->add(*img);
|
||||||
|
} else { // custom
|
||||||
|
const auto &pb = imgr.GetFromURLIfCached(reaction.Emoji.GetURL());
|
||||||
|
Gtk::Image *img;
|
||||||
|
if (pb) {
|
||||||
|
img = Gtk::manage(new Gtk::Image(pb->scale_simple(16, 16, Gdk::INTERP_BILINEAR)));
|
||||||
|
} else {
|
||||||
|
img = Gtk::manage(new Gtk::Image(placeholder));
|
||||||
|
// can track_obj PLEASE work ???
|
||||||
|
imgr.LoadFromURL(reaction.Emoji.GetURL(), sigc::bind<0>(sigc::mem_fun(*this, &ChatMessageItemContainer::ReactionUpdateImage), img));
|
||||||
|
}
|
||||||
|
img->set_can_focus(false);
|
||||||
|
box->add(*img);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto *lbl = Gtk::manage(new Gtk::Label(std::to_string(reaction.Count)));
|
||||||
|
lbl->set_margin_left(5);
|
||||||
|
lbl->get_style_context()->add_class("reaction-count");
|
||||||
|
box->add(*lbl);
|
||||||
|
}
|
||||||
|
|
||||||
|
return flow;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatMessageItemContainer::ReactionUpdateImage(Gtk::Image *img, const Glib::RefPtr<Gdk::Pixbuf> &pb) {
|
||||||
|
img->property_pixbuf() = pb->scale_simple(16, 16, Gdk::INTERP_BILINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
void ChatMessageItemContainer::HandleImage(const AttachmentData &data, Gtk::Image *img, std::string url) {
|
void ChatMessageItemContainer::HandleImage(const AttachmentData &data, Gtk::Image *img, std::string url) {
|
||||||
m_img_loadmap[url] = std::make_pair(img, data);
|
m_img_loadmap[url] = std::make_pair(img, data);
|
||||||
// ask the chatwindow to call UpdateImage because dealing with lifetimes sucks
|
// ask the chatwindow to call UpdateImage because dealing with lifetimes sucks
|
||||||
@@ -715,6 +815,14 @@ ChatMessageItemContainer::type_signal_channel_click ChatMessageItemContainer::si
|
|||||||
return m_signal_action_channel_click;
|
return m_signal_action_channel_click;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChatMessageItemContainer::type_signal_action_reaction_add ChatMessageItemContainer::signal_action_reaction_add() {
|
||||||
|
return m_signal_action_reaction_add;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatMessageItemContainer::type_signal_action_reaction_remove ChatMessageItemContainer::signal_action_reaction_remove() {
|
||||||
|
return m_signal_action_reaction_remove;
|
||||||
|
}
|
||||||
|
|
||||||
ChatMessageItemContainer::type_signal_image_load ChatMessageItemContainer::signal_image_load() {
|
ChatMessageItemContainer::type_signal_image_load ChatMessageItemContainer::signal_image_load() {
|
||||||
return m_signal_image_load;
|
return m_signal_image_load;
|
||||||
}
|
}
|
||||||
|
@@ -14,6 +14,7 @@ public:
|
|||||||
void UpdateAttributes();
|
void UpdateAttributes();
|
||||||
void UpdateContent();
|
void UpdateContent();
|
||||||
void UpdateImage(std::string url, Glib::RefPtr<Gdk::Pixbuf> buf);
|
void UpdateImage(std::string url, Glib::RefPtr<Gdk::Pixbuf> buf);
|
||||||
|
void UpdateReactions();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool EmitImageLoad(std::string url);
|
bool EmitImageLoad(std::string url);
|
||||||
@@ -25,6 +26,8 @@ protected:
|
|||||||
Gtk::Widget *CreateImageComponent(const AttachmentData &data);
|
Gtk::Widget *CreateImageComponent(const AttachmentData &data);
|
||||||
Gtk::Widget *CreateAttachmentComponent(const AttachmentData &data); // non-image attachments
|
Gtk::Widget *CreateAttachmentComponent(const AttachmentData &data); // non-image attachments
|
||||||
Gtk::Widget *CreateStickerComponent(const Sticker &data);
|
Gtk::Widget *CreateStickerComponent(const Sticker &data);
|
||||||
|
Gtk::Widget *CreateReactionsComponent(const Message *data);
|
||||||
|
void ReactionUpdateImage(Gtk::Image *img, const Glib::RefPtr<Gdk::Pixbuf> &pb);
|
||||||
void HandleImage(const AttachmentData &data, Gtk::Image *img, std::string url);
|
void HandleImage(const AttachmentData &data, Gtk::Image *img, std::string url);
|
||||||
|
|
||||||
void OnEmbedImageLoad(const Glib::RefPtr<Gdk::Pixbuf> &pixbuf);
|
void OnEmbedImageLoad(const Glib::RefPtr<Gdk::Pixbuf> &pixbuf);
|
||||||
@@ -75,6 +78,7 @@ protected:
|
|||||||
|
|
||||||
Gtk::TextView *m_text_component = nullptr;
|
Gtk::TextView *m_text_component = nullptr;
|
||||||
Gtk::Widget *m_embed_component = nullptr;
|
Gtk::Widget *m_embed_component = nullptr;
|
||||||
|
Gtk::Widget *m_reactions_component = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef sigc::signal<void, std::string> type_signal_image_load;
|
typedef sigc::signal<void, std::string> type_signal_image_load;
|
||||||
@@ -82,10 +86,14 @@ public:
|
|||||||
typedef sigc::signal<void> type_signal_action_delete;
|
typedef sigc::signal<void> type_signal_action_delete;
|
||||||
typedef sigc::signal<void> type_signal_action_edit;
|
typedef sigc::signal<void> type_signal_action_edit;
|
||||||
typedef sigc::signal<void, Snowflake> type_signal_channel_click;
|
typedef sigc::signal<void, Snowflake> type_signal_channel_click;
|
||||||
|
typedef sigc::signal<void, Glib::ustring> type_signal_action_reaction_add;
|
||||||
|
typedef sigc::signal<void, Glib::ustring> type_signal_action_reaction_remove;
|
||||||
|
|
||||||
type_signal_action_delete signal_action_delete();
|
type_signal_action_delete signal_action_delete();
|
||||||
type_signal_action_edit signal_action_edit();
|
type_signal_action_edit signal_action_edit();
|
||||||
type_signal_channel_click signal_action_channel_click();
|
type_signal_channel_click signal_action_channel_click();
|
||||||
|
type_signal_action_reaction_add signal_action_reaction_add();
|
||||||
|
type_signal_action_reaction_remove signal_action_reaction_remove();
|
||||||
|
|
||||||
type_signal_image_load signal_image_load();
|
type_signal_image_load signal_image_load();
|
||||||
|
|
||||||
@@ -93,6 +101,8 @@ private:
|
|||||||
type_signal_action_delete m_signal_action_delete;
|
type_signal_action_delete m_signal_action_delete;
|
||||||
type_signal_action_edit m_signal_action_edit;
|
type_signal_action_edit m_signal_action_edit;
|
||||||
type_signal_channel_click m_signal_action_channel_click;
|
type_signal_channel_click m_signal_action_channel_click;
|
||||||
|
type_signal_action_reaction_add m_signal_action_reaction_add;
|
||||||
|
type_signal_action_reaction_remove m_signal_action_reaction_remove;
|
||||||
|
|
||||||
type_signal_image_load m_signal_image_load;
|
type_signal_image_load m_signal_image_load;
|
||||||
};
|
};
|
||||||
|
@@ -128,6 +128,14 @@ Snowflake ChatWindow::GetOldestListedMessage() {
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChatWindow::UpdateReactions(Snowflake id) {
|
||||||
|
auto it = m_id_to_widget.find(id);
|
||||||
|
if (it == m_id_to_widget.end()) return;
|
||||||
|
auto *widget = dynamic_cast<ChatMessageItemContainer *>(it->second);
|
||||||
|
if (widget == nullptr) return;
|
||||||
|
widget->UpdateReactions();
|
||||||
|
}
|
||||||
|
|
||||||
Snowflake ChatWindow::GetActiveChannel() const {
|
Snowflake ChatWindow::GetActiveChannel() const {
|
||||||
return m_active_channel;
|
return m_active_channel;
|
||||||
}
|
}
|
||||||
@@ -206,6 +214,12 @@ void ChatWindow::ProcessNewMessage(Snowflake id, bool prepend) {
|
|||||||
content->signal_action_edit().connect([this, id] {
|
content->signal_action_edit().connect([this, id] {
|
||||||
m_signal_action_message_edit.emit(m_active_channel, id);
|
m_signal_action_message_edit.emit(m_active_channel, id);
|
||||||
});
|
});
|
||||||
|
content->signal_action_reaction_add().connect([this, id](const Glib::ustring ¶m) {
|
||||||
|
m_signal_action_reaction_add.emit(id, param);
|
||||||
|
});
|
||||||
|
content->signal_action_reaction_remove().connect([this, id](const Glib::ustring ¶m) {
|
||||||
|
m_signal_action_reaction_remove.emit(id, param);
|
||||||
|
});
|
||||||
content->signal_image_load().connect([this, id](std::string url) {
|
content->signal_image_load().connect([this, id](std::string url) {
|
||||||
auto &mgr = Abaddon::Get().GetImageManager();
|
auto &mgr = Abaddon::Get().GetImageManager();
|
||||||
mgr.LoadFromURL(url, [this, id, url](Glib::RefPtr<Gdk::Pixbuf> buf) {
|
mgr.LoadFromURL(url, [this, id, url](Glib::RefPtr<Gdk::Pixbuf> buf) {
|
||||||
@@ -339,3 +353,11 @@ ChatWindow::type_signal_action_insert_mention ChatWindow::signal_action_insert_m
|
|||||||
ChatWindow::type_signal_action_open_user_menu ChatWindow::signal_action_open_user_menu() {
|
ChatWindow::type_signal_action_open_user_menu ChatWindow::signal_action_open_user_menu() {
|
||||||
return m_signal_action_open_user_menu;
|
return m_signal_action_open_user_menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChatWindow::type_signal_action_reaction_add ChatWindow::signal_action_reaction_add() {
|
||||||
|
return m_signal_action_reaction_add;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatWindow::type_signal_action_reaction_remove ChatWindow::signal_action_reaction_remove() {
|
||||||
|
return m_signal_action_reaction_remove;
|
||||||
|
}
|
||||||
|
@@ -23,6 +23,7 @@ public:
|
|||||||
void AddNewHistory(const std::vector<Snowflake> &id); // prepend messages
|
void AddNewHistory(const std::vector<Snowflake> &id); // prepend messages
|
||||||
void InsertChatInput(std::string text);
|
void InsertChatInput(std::string text);
|
||||||
Snowflake GetOldestListedMessage(); // oldest message that is currently in the ListBox
|
Snowflake GetOldestListedMessage(); // oldest message that is currently in the ListBox
|
||||||
|
void UpdateReactions(Snowflake id);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ChatMessageItemContainer *CreateMessageComponent(Snowflake id); // to be inserted into header's content box
|
ChatMessageItemContainer *CreateMessageComponent(Snowflake id); // to be inserted into header's content box
|
||||||
@@ -72,6 +73,8 @@ public:
|
|||||||
typedef sigc::signal<void, Snowflake> type_signal_action_channel_click;
|
typedef sigc::signal<void, Snowflake> type_signal_action_channel_click;
|
||||||
typedef sigc::signal<void, Snowflake> type_signal_action_insert_mention;
|
typedef sigc::signal<void, Snowflake> type_signal_action_insert_mention;
|
||||||
typedef sigc::signal<void, const GdkEvent *, Snowflake, Snowflake> type_signal_action_open_user_menu;
|
typedef sigc::signal<void, const GdkEvent *, Snowflake, Snowflake> type_signal_action_open_user_menu;
|
||||||
|
typedef sigc::signal<void, Snowflake, Glib::ustring> type_signal_action_reaction_add;
|
||||||
|
typedef sigc::signal<void, Snowflake, Glib::ustring> type_signal_action_reaction_remove;
|
||||||
|
|
||||||
type_signal_action_message_delete signal_action_message_delete();
|
type_signal_action_message_delete signal_action_message_delete();
|
||||||
type_signal_action_message_edit signal_action_message_edit();
|
type_signal_action_message_edit signal_action_message_edit();
|
||||||
@@ -80,6 +83,8 @@ public:
|
|||||||
type_signal_action_channel_click signal_action_channel_click();
|
type_signal_action_channel_click signal_action_channel_click();
|
||||||
type_signal_action_insert_mention signal_action_insert_mention();
|
type_signal_action_insert_mention signal_action_insert_mention();
|
||||||
type_signal_action_open_user_menu signal_action_open_user_menu();
|
type_signal_action_open_user_menu signal_action_open_user_menu();
|
||||||
|
type_signal_action_reaction_add signal_action_reaction_add();
|
||||||
|
type_signal_action_reaction_remove signal_action_reaction_remove();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
type_signal_action_message_delete m_signal_action_message_delete;
|
type_signal_action_message_delete m_signal_action_message_delete;
|
||||||
@@ -89,4 +94,6 @@ private:
|
|||||||
type_signal_action_channel_click m_signal_action_channel_click;
|
type_signal_action_channel_click m_signal_action_channel_click;
|
||||||
type_signal_action_insert_mention m_signal_action_insert_mention;
|
type_signal_action_insert_mention m_signal_action_insert_mention;
|
||||||
type_signal_action_open_user_menu m_signal_action_open_user_menu;
|
type_signal_action_open_user_menu m_signal_action_open_user_menu;
|
||||||
|
type_signal_action_reaction_add m_signal_action_reaction_add;
|
||||||
|
type_signal_action_reaction_remove m_signal_action_reaction_remove;
|
||||||
};
|
};
|
||||||
|
16
css/main.css
16
css/main.css
@@ -105,6 +105,22 @@
|
|||||||
margin: 5px;
|
margin: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.reaction-box {
|
||||||
|
padding: 2px 5px 2px 5px;
|
||||||
|
margin: 0px 0px 0px 0px;
|
||||||
|
background-color: rgba(0.4, 0.4, 0.4, 0.4);
|
||||||
|
border-radius: 5px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reaction-box.reacted {
|
||||||
|
border: 1px solid white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reaction-count {
|
||||||
|
color: #cfd8dc;
|
||||||
|
}
|
||||||
|
|
||||||
paned separator {
|
paned separator {
|
||||||
background:#37474f;
|
background:#37474f;
|
||||||
}
|
}
|
||||||
|
@@ -411,6 +411,34 @@ std::optional<Snowflake> DiscordClient::FindDM(Snowflake user_id) {
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DiscordClient::AddReaction(Snowflake id, Glib::ustring param) {
|
||||||
|
if (!param.is_ascii()) // means unicode param
|
||||||
|
param = Glib::uri_escape_string(param, "", false);
|
||||||
|
else {
|
||||||
|
const auto &tmp = m_store.GetEmoji(param);
|
||||||
|
if (tmp.has_value())
|
||||||
|
param = tmp->Name + ":" + std::to_string(tmp->ID);
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Snowflake channel_id = m_store.GetMessage(id)->ChannelID;
|
||||||
|
m_http.MakePUT("/channels/" + std::to_string(channel_id) + "/messages/" + std::to_string(id) + "/reactions/" + param + "/@me", "", [](auto) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiscordClient::RemoveReaction(Snowflake id, Glib::ustring param) {
|
||||||
|
if (!param.is_ascii()) // means unicode param
|
||||||
|
param = Glib::uri_escape_string(param, "", false);
|
||||||
|
else {
|
||||||
|
const auto &tmp = m_store.GetEmoji(param);
|
||||||
|
if (tmp.has_value())
|
||||||
|
param = tmp->Name + ":" + std::to_string(tmp->ID);
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Snowflake channel_id = m_store.GetMessage(id)->ChannelID;
|
||||||
|
m_http.MakeDELETE("/channels/" + std::to_string(channel_id) + "/messages/" + std::to_string(id) + "/reactions/" + param + "/@me", [](auto) {});
|
||||||
|
}
|
||||||
|
|
||||||
void DiscordClient::UpdateToken(std::string token) {
|
void DiscordClient::UpdateToken(std::string token) {
|
||||||
if (!IsStarted()) {
|
if (!IsStarted()) {
|
||||||
m_token = token;
|
m_token = token;
|
||||||
@@ -552,6 +580,12 @@ void DiscordClient::HandleGatewayMessage(std::string str) {
|
|||||||
case GatewayEvent::GUILD_ROLE_DELETE: {
|
case GatewayEvent::GUILD_ROLE_DELETE: {
|
||||||
HandleGatewayGuildRoleDelete(m);
|
HandleGatewayGuildRoleDelete(m);
|
||||||
} break;
|
} break;
|
||||||
|
case GatewayEvent::MESSAGE_REACTION_ADD: {
|
||||||
|
HandleGatewayMessageReactionAdd(m);
|
||||||
|
} break;
|
||||||
|
case GatewayEvent::MESSAGE_REACTION_REMOVE: {
|
||||||
|
HandleGatewayMessageReactionRemove(m);
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
@@ -735,6 +769,80 @@ void DiscordClient::HandleGatewayGuildRoleDelete(const GatewayMessage &msg) {
|
|||||||
m_signal_role_delete.emit(data.RoleID);
|
m_signal_role_delete.emit(data.RoleID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DiscordClient::HandleGatewayMessageReactionAdd(const GatewayMessage &msg) {
|
||||||
|
MessageReactionAddObject data = msg.Data;
|
||||||
|
auto to = m_store.GetMessage(data.MessageID);
|
||||||
|
if (!to.has_value()) return;
|
||||||
|
if (!to->Reactions.has_value()) to->Reactions.emplace();
|
||||||
|
// add if present
|
||||||
|
bool stock;
|
||||||
|
auto it = std::find_if(to->Reactions->begin(), to->Reactions->end(), [&](const ReactionData &x) {
|
||||||
|
if (data.Emoji.ID.IsValid() && x.Emoji.ID.IsValid()) {
|
||||||
|
stock = false;
|
||||||
|
return data.Emoji.ID == x.Emoji.ID;
|
||||||
|
} else {
|
||||||
|
stock = true;
|
||||||
|
return data.Emoji.Name == x.Emoji.Name;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (it != to->Reactions->end()) {
|
||||||
|
it->Count++;
|
||||||
|
if (data.UserID == GetUserData().ID)
|
||||||
|
it->HasReactedWith = true;
|
||||||
|
m_store.SetMessage(data.MessageID, *to);
|
||||||
|
if (stock)
|
||||||
|
m_signal_reaction_add.emit(data.MessageID, data.Emoji.Name);
|
||||||
|
else
|
||||||
|
m_signal_reaction_add.emit(data.MessageID, std::to_string(data.Emoji.ID));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create new
|
||||||
|
auto &rdata = to->Reactions->emplace_back();
|
||||||
|
rdata.Count = 1;
|
||||||
|
rdata.Emoji = data.Emoji;
|
||||||
|
rdata.HasReactedWith = data.UserID == GetUserData().ID;
|
||||||
|
m_store.SetMessage(data.MessageID, *to);
|
||||||
|
if (stock)
|
||||||
|
m_signal_reaction_add.emit(data.MessageID, data.Emoji.Name);
|
||||||
|
else
|
||||||
|
m_signal_reaction_add.emit(data.MessageID, std::to_string(data.Emoji.ID));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiscordClient::HandleGatewayMessageReactionRemove(const GatewayMessage &msg) {
|
||||||
|
MessageReactionRemoveObject data = msg.Data;
|
||||||
|
auto to = m_store.GetMessage(data.MessageID);
|
||||||
|
if (!to.has_value()) return;
|
||||||
|
if (!to->Reactions.has_value()) return;
|
||||||
|
bool stock;
|
||||||
|
auto it = std::find_if(to->Reactions->begin(), to->Reactions->end(), [&](const ReactionData &x) {
|
||||||
|
if (data.Emoji.ID.IsValid() && x.Emoji.ID.IsValid()) {
|
||||||
|
stock = false;
|
||||||
|
return data.Emoji.ID == x.Emoji.ID;
|
||||||
|
} else {
|
||||||
|
stock = true;
|
||||||
|
return data.Emoji.Name == x.Emoji.Name;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (it == to->Reactions->end()) return;
|
||||||
|
|
||||||
|
if (it->Count == 1)
|
||||||
|
to->Reactions->erase(it);
|
||||||
|
else {
|
||||||
|
if (data.UserID == GetUserData().ID)
|
||||||
|
it->HasReactedWith = false;
|
||||||
|
it->Count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_store.SetMessage(data.MessageID, *to);
|
||||||
|
|
||||||
|
if (stock)
|
||||||
|
m_signal_reaction_remove.emit(data.MessageID, data.Emoji.Name);
|
||||||
|
else
|
||||||
|
m_signal_reaction_remove.emit(data.MessageID, std::to_string(data.Emoji.ID));
|
||||||
|
}
|
||||||
|
|
||||||
void DiscordClient::HandleGatewayReconnect(const GatewayMessage &msg) {
|
void DiscordClient::HandleGatewayReconnect(const GatewayMessage &msg) {
|
||||||
m_signal_disconnected.emit(true);
|
m_signal_disconnected.emit(true);
|
||||||
inflateEnd(&m_zstream);
|
inflateEnd(&m_zstream);
|
||||||
@@ -928,6 +1036,8 @@ void DiscordClient::LoadEventMap() {
|
|||||||
m_event_map["GUILD_ROLE_UPDATE"] = GatewayEvent::GUILD_ROLE_UPDATE;
|
m_event_map["GUILD_ROLE_UPDATE"] = GatewayEvent::GUILD_ROLE_UPDATE;
|
||||||
m_event_map["GUILD_ROLE_CREATE"] = GatewayEvent::GUILD_ROLE_CREATE;
|
m_event_map["GUILD_ROLE_CREATE"] = GatewayEvent::GUILD_ROLE_CREATE;
|
||||||
m_event_map["GUILD_ROLE_DELETE"] = GatewayEvent::GUILD_ROLE_DELETE;
|
m_event_map["GUILD_ROLE_DELETE"] = GatewayEvent::GUILD_ROLE_DELETE;
|
||||||
|
m_event_map["MESSAGE_REACTION_ADD"] = GatewayEvent::MESSAGE_REACTION_ADD;
|
||||||
|
m_event_map["MESSAGE_REACTION_REMOVE"] = GatewayEvent::MESSAGE_REACTION_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
DiscordClient::type_signal_gateway_ready DiscordClient::signal_gateway_ready() {
|
DiscordClient::type_signal_gateway_ready DiscordClient::signal_gateway_ready() {
|
||||||
@@ -993,3 +1103,11 @@ DiscordClient::type_signal_role_create DiscordClient::signal_role_create() {
|
|||||||
DiscordClient::type_signal_role_delete DiscordClient::signal_role_delete() {
|
DiscordClient::type_signal_role_delete DiscordClient::signal_role_delete() {
|
||||||
return m_signal_role_delete;
|
return m_signal_role_delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DiscordClient::type_signal_reaction_add DiscordClient::signal_reaction_add() {
|
||||||
|
return m_signal_reaction_add;
|
||||||
|
}
|
||||||
|
|
||||||
|
DiscordClient::type_signal_reaction_remove DiscordClient::signal_reaction_remove() {
|
||||||
|
return m_signal_reaction_remove;
|
||||||
|
}
|
||||||
|
@@ -108,6 +108,8 @@ public:
|
|||||||
void UpdateStatus(const std::string &status, bool is_afk, const Activity &obj);
|
void UpdateStatus(const std::string &status, bool is_afk, const Activity &obj);
|
||||||
void CreateDM(Snowflake user_id);
|
void CreateDM(Snowflake user_id);
|
||||||
std::optional<Snowflake> FindDM(Snowflake user_id); // wont find group dms
|
std::optional<Snowflake> FindDM(Snowflake user_id); // wont find group dms
|
||||||
|
void AddReaction(Snowflake id, Glib::ustring param);
|
||||||
|
void RemoveReaction(Snowflake id, Glib::ustring param);
|
||||||
|
|
||||||
void UpdateToken(std::string token);
|
void UpdateToken(std::string token);
|
||||||
void SetUserAgent(std::string agent);
|
void SetUserAgent(std::string agent);
|
||||||
@@ -140,6 +142,8 @@ private:
|
|||||||
void HandleGatewayGuildRoleUpdate(const GatewayMessage &msg);
|
void HandleGatewayGuildRoleUpdate(const GatewayMessage &msg);
|
||||||
void HandleGatewayGuildRoleCreate(const GatewayMessage &msg);
|
void HandleGatewayGuildRoleCreate(const GatewayMessage &msg);
|
||||||
void HandleGatewayGuildRoleDelete(const GatewayMessage &msg);
|
void HandleGatewayGuildRoleDelete(const GatewayMessage &msg);
|
||||||
|
void HandleGatewayMessageReactionAdd(const GatewayMessage &msg);
|
||||||
|
void HandleGatewayMessageReactionRemove(const GatewayMessage &msg);
|
||||||
void HandleGatewayReconnect(const GatewayMessage &msg);
|
void HandleGatewayReconnect(const GatewayMessage &msg);
|
||||||
void HeartbeatThread();
|
void HeartbeatThread();
|
||||||
void SendIdentify();
|
void SendIdentify();
|
||||||
@@ -202,6 +206,8 @@ public:
|
|||||||
typedef sigc::signal<void, Snowflake> type_signal_role_update;
|
typedef sigc::signal<void, Snowflake> type_signal_role_update;
|
||||||
typedef sigc::signal<void, Snowflake> type_signal_role_create;
|
typedef sigc::signal<void, Snowflake> type_signal_role_create;
|
||||||
typedef sigc::signal<void, Snowflake> type_signal_role_delete;
|
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, bool> type_signal_disconnected; // bool true if reconnecting
|
typedef sigc::signal<void, bool> type_signal_disconnected; // bool true if reconnecting
|
||||||
typedef sigc::signal<void> type_signal_connected;
|
typedef sigc::signal<void> type_signal_connected;
|
||||||
|
|
||||||
@@ -219,6 +225,8 @@ public:
|
|||||||
type_signal_role_update signal_role_update();
|
type_signal_role_update signal_role_update();
|
||||||
type_signal_role_create signal_role_create();
|
type_signal_role_create signal_role_create();
|
||||||
type_signal_role_delete signal_role_delete();
|
type_signal_role_delete signal_role_delete();
|
||||||
|
type_signal_reaction_add signal_reaction_add();
|
||||||
|
type_signal_reaction_remove signal_reaction_remove();
|
||||||
type_signal_disconnected signal_disconnected();
|
type_signal_disconnected signal_disconnected();
|
||||||
type_signal_connected signal_connected();
|
type_signal_connected signal_connected();
|
||||||
|
|
||||||
@@ -237,6 +245,8 @@ protected:
|
|||||||
type_signal_role_update m_signal_role_update;
|
type_signal_role_update m_signal_role_update;
|
||||||
type_signal_role_create m_signal_role_create;
|
type_signal_role_create m_signal_role_create;
|
||||||
type_signal_role_delete m_signal_role_delete;
|
type_signal_role_delete m_signal_role_delete;
|
||||||
|
type_signal_reaction_add m_signal_reaction_add;
|
||||||
|
type_signal_reaction_remove m_signal_reaction_remove;
|
||||||
type_signal_disconnected m_signal_disconnected;
|
type_signal_disconnected m_signal_disconnected;
|
||||||
type_signal_connected m_signal_connected;
|
type_signal_connected m_signal_connected;
|
||||||
};
|
};
|
||||||
|
@@ -11,6 +11,23 @@ void from_json(const nlohmann::json &j, Emoji &m) {
|
|||||||
JS_O("available", m.IsAvailable);
|
JS_O("available", m.IsAvailable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void to_json(nlohmann::json &j, const Emoji &m) {
|
||||||
|
if (m.ID.IsValid())
|
||||||
|
j["id"] = m.ID;
|
||||||
|
else
|
||||||
|
j["id"] = nullptr;
|
||||||
|
if (m.Name != "")
|
||||||
|
j["name"] = m.Name;
|
||||||
|
else
|
||||||
|
j["name"] = nullptr;
|
||||||
|
JS_IF("roles", m.Roles);
|
||||||
|
JS_IF("user", m.Creator);
|
||||||
|
JS_IF("require_colons", m.NeedsColons);
|
||||||
|
JS_IF("managed", m.IsManaged);
|
||||||
|
JS_IF("animated", m.IsAnimated);
|
||||||
|
JS_IF("available", m.IsAvailable);
|
||||||
|
}
|
||||||
|
|
||||||
std::string Emoji::GetURL() const {
|
std::string Emoji::GetURL() const {
|
||||||
return "https://cdn.discordapp.com/emojis/" + std::to_string(ID) + ".png";
|
return "https://cdn.discordapp.com/emojis/" + std::to_string(ID) + ".png";
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,7 @@ struct Emoji {
|
|||||||
std::optional<bool> IsAvailable;
|
std::optional<bool> IsAvailable;
|
||||||
|
|
||||||
friend void from_json(const nlohmann::json &j, Emoji &m);
|
friend void from_json(const nlohmann::json &j, Emoji &m);
|
||||||
|
friend void to_json(nlohmann::json &j, const Emoji &m);
|
||||||
|
|
||||||
std::string GetURL() const;
|
std::string GetURL() const;
|
||||||
static std::string URLFromID(std::string emoji_id);
|
static std::string URLFromID(std::string emoji_id);
|
||||||
|
@@ -152,6 +152,18 @@ void to_json(nlohmann::json &j, const MessageReferenceData &m) {
|
|||||||
JS_IF("guild_id", m.GuildID);
|
JS_IF("guild_id", m.GuildID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void from_json(const nlohmann::json &j, ReactionData &m) {
|
||||||
|
JS_D("count", m.Count);
|
||||||
|
JS_D("me", m.HasReactedWith);
|
||||||
|
JS_D("emoji", m.Emoji);
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_json(nlohmann::json &j, const ReactionData &m) {
|
||||||
|
j["count"] = m.Count;
|
||||||
|
j["me"] = m.HasReactedWith;
|
||||||
|
j["emoji"] = m.Emoji;
|
||||||
|
}
|
||||||
|
|
||||||
void from_json(const nlohmann::json &j, Message &m) {
|
void from_json(const nlohmann::json &j, Message &m) {
|
||||||
JS_D("id", m.ID);
|
JS_D("id", m.ID);
|
||||||
JS_D("channel_id", m.ChannelID);
|
JS_D("channel_id", m.ChannelID);
|
||||||
@@ -170,7 +182,7 @@ void from_json(const nlohmann::json &j, Message &m) {
|
|||||||
// JS_O("mention_channels", m.MentionChannels);
|
// JS_O("mention_channels", m.MentionChannels);
|
||||||
JS_D("attachments", m.Attachments);
|
JS_D("attachments", m.Attachments);
|
||||||
JS_D("embeds", m.Embeds);
|
JS_D("embeds", m.Embeds);
|
||||||
// JS_O("reactions", m.Reactions);
|
JS_O("reactions", m.Reactions);
|
||||||
JS_O("nonce", m.Nonce);
|
JS_O("nonce", m.Nonce);
|
||||||
JS_D("pinned", m.IsPinned);
|
JS_D("pinned", m.IsPinned);
|
||||||
JS_O("webhook_id", m.WebhookID);
|
JS_O("webhook_id", m.WebhookID);
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
#include "json.hpp"
|
#include "json.hpp"
|
||||||
#include "user.hpp"
|
#include "user.hpp"
|
||||||
#include "sticker.hpp"
|
#include "sticker.hpp"
|
||||||
|
#include "emoji.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -140,6 +141,15 @@ struct MessageReferenceData {
|
|||||||
friend void to_json(nlohmann::json &j, const MessageReferenceData &m);
|
friend void to_json(nlohmann::json &j, const MessageReferenceData &m);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ReactionData {
|
||||||
|
int Count;
|
||||||
|
bool HasReactedWith;
|
||||||
|
Emoji Emoji;
|
||||||
|
|
||||||
|
friend void from_json(const nlohmann::json &j, ReactionData &m);
|
||||||
|
friend void to_json(nlohmann::json &j, const ReactionData &m);
|
||||||
|
};
|
||||||
|
|
||||||
struct Message {
|
struct Message {
|
||||||
Snowflake ID;
|
Snowflake ID;
|
||||||
Snowflake ChannelID;
|
Snowflake ChannelID;
|
||||||
@@ -156,7 +166,7 @@ struct Message {
|
|||||||
// std::optional<std::vector<ChannelMentionData>> MentionChannels;
|
// std::optional<std::vector<ChannelMentionData>> MentionChannels;
|
||||||
std::vector<AttachmentData> Attachments;
|
std::vector<AttachmentData> Attachments;
|
||||||
std::vector<EmbedData> Embeds;
|
std::vector<EmbedData> Embeds;
|
||||||
// std::optional<std::vector<ReactionData>> Reactions;
|
std::optional<std::vector<ReactionData>> Reactions;
|
||||||
std::optional<std::string> Nonce;
|
std::optional<std::string> Nonce;
|
||||||
bool IsPinned;
|
bool IsPinned;
|
||||||
std::optional<Snowflake> WebhookID;
|
std::optional<Snowflake> WebhookID;
|
||||||
|
@@ -216,3 +216,20 @@ void from_json(const nlohmann::json &j, GuildRoleDeleteObject &m) {
|
|||||||
JS_D("guild_id", m.GuildID);
|
JS_D("guild_id", m.GuildID);
|
||||||
JS_D("role_id", m.RoleID);
|
JS_D("role_id", m.RoleID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void from_json(const nlohmann::json &j, MessageReactionAddObject &m) {
|
||||||
|
JS_D("user_id", m.UserID);
|
||||||
|
JS_D("channel_id", m.ChannelID);
|
||||||
|
JS_D("message_id", m.MessageID);
|
||||||
|
JS_O("guild_id", m.GuildID);
|
||||||
|
JS_O("member", m.Member);
|
||||||
|
JS_D("emoji", m.Emoji);
|
||||||
|
}
|
||||||
|
|
||||||
|
void from_json(const nlohmann::json &j, MessageReactionRemoveObject &m) {
|
||||||
|
JS_D("user_id", m.UserID);
|
||||||
|
JS_D("channel_id", m.ChannelID);
|
||||||
|
JS_D("message_id", m.MessageID);
|
||||||
|
JS_O("guild_id", m.GuildID);
|
||||||
|
JS_D("emoji", m.Emoji);
|
||||||
|
}
|
||||||
|
@@ -49,6 +49,8 @@ enum class GatewayEvent : int {
|
|||||||
GUILD_ROLE_UPDATE,
|
GUILD_ROLE_UPDATE,
|
||||||
GUILD_ROLE_CREATE,
|
GUILD_ROLE_CREATE,
|
||||||
GUILD_ROLE_DELETE,
|
GUILD_ROLE_DELETE,
|
||||||
|
MESSAGE_REACTION_ADD,
|
||||||
|
MESSAGE_REACTION_REMOVE,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GatewayMessage {
|
struct GatewayMessage {
|
||||||
@@ -298,3 +300,24 @@ struct GuildRoleDeleteObject {
|
|||||||
|
|
||||||
friend void from_json(const nlohmann::json &j, GuildRoleDeleteObject &m);
|
friend void from_json(const nlohmann::json &j, GuildRoleDeleteObject &m);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MessageReactionAddObject {
|
||||||
|
Snowflake UserID;
|
||||||
|
Snowflake ChannelID;
|
||||||
|
Snowflake MessageID;
|
||||||
|
std::optional<Snowflake> GuildID;
|
||||||
|
std::optional<GuildMember> Member;
|
||||||
|
Emoji Emoji;
|
||||||
|
|
||||||
|
friend void from_json(const nlohmann::json &j, MessageReactionAddObject &m);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MessageReactionRemoveObject {
|
||||||
|
Snowflake UserID;
|
||||||
|
Snowflake ChannelID;
|
||||||
|
Snowflake MessageID;
|
||||||
|
std::optional<Snowflake> GuildID;
|
||||||
|
Emoji Emoji;
|
||||||
|
|
||||||
|
friend void from_json(const nlohmann::json &j, MessageReactionRemoveObject &m);
|
||||||
|
};
|
||||||
|
@@ -219,9 +219,13 @@ void Store::SetMessage(Snowflake id, const Message &message) {
|
|||||||
Bind(m_set_msg_stmt, 18, tmp);
|
Bind(m_set_msg_stmt, 18, tmp);
|
||||||
} else
|
} else
|
||||||
Bind(m_set_msg_stmt, 18, nullptr);
|
Bind(m_set_msg_stmt, 18, nullptr);
|
||||||
|
if (message.Reactions.has_value()) {
|
||||||
Bind(m_set_msg_stmt, 19, message.IsDeleted());
|
std::string tmp = nlohmann::json(*message.Reactions).dump();
|
||||||
Bind(m_set_msg_stmt, 20, message.IsEdited());
|
Bind(m_set_msg_stmt, 19, tmp);
|
||||||
|
} else
|
||||||
|
Bind(m_set_msg_stmt, 19, nullptr);
|
||||||
|
Bind(m_set_msg_stmt, 20, message.IsDeleted());
|
||||||
|
Bind(m_set_msg_stmt, 21, message.IsEdited());
|
||||||
|
|
||||||
if (!RunInsert(m_set_msg_stmt))
|
if (!RunInsert(m_set_msg_stmt))
|
||||||
fprintf(stderr, "message insert failed: %s\n", sqlite3_errstr(m_db_err));
|
fprintf(stderr, "message insert failed: %s\n", sqlite3_errstr(m_db_err));
|
||||||
@@ -468,10 +472,13 @@ std::optional<Message> Store::GetMessage(Snowflake id) const {
|
|||||||
Get(m_get_msg_stmt, 17, tmps);
|
Get(m_get_msg_stmt, 17, tmps);
|
||||||
if (tmps != "")
|
if (tmps != "")
|
||||||
ret.Stickers = nlohmann::json::parse(tmps).get<std::vector<Sticker>>();
|
ret.Stickers = nlohmann::json::parse(tmps).get<std::vector<Sticker>>();
|
||||||
|
Get(m_get_msg_stmt, 18, tmps);
|
||||||
|
if (tmps != "")
|
||||||
|
ret.Reactions = nlohmann::json::parse(tmps).get<std::vector<ReactionData>>();
|
||||||
bool tmpb = false;
|
bool tmpb = false;
|
||||||
Get(m_get_msg_stmt, 18, tmpb);
|
|
||||||
if (tmpb) ret.SetDeleted();
|
|
||||||
Get(m_get_msg_stmt, 19, tmpb);
|
Get(m_get_msg_stmt, 19, tmpb);
|
||||||
|
if (tmpb) ret.SetDeleted();
|
||||||
|
Get(m_get_msg_stmt, 20, tmpb);
|
||||||
if (tmpb) ret.SetEdited();
|
if (tmpb) ret.SetEdited();
|
||||||
|
|
||||||
Reset(m_get_msg_stmt);
|
Reset(m_get_msg_stmt);
|
||||||
@@ -589,164 +596,165 @@ void Store::EndTransaction() {
|
|||||||
|
|
||||||
bool Store::CreateTables() {
|
bool Store::CreateTables() {
|
||||||
constexpr const char *create_users = R"(
|
constexpr const char *create_users = R"(
|
||||||
CREATE TABLE IF NOT EXISTS users (
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
username TEXT NOT NULL,
|
username TEXT NOT NULL,
|
||||||
discriminator TEXT NOT NULL,
|
discriminator TEXT NOT NULL,
|
||||||
avatar TEXT,
|
avatar TEXT,
|
||||||
bot BOOL,
|
bot BOOL,
|
||||||
system BOOL,
|
system BOOL,
|
||||||
mfa BOOL,
|
mfa BOOL,
|
||||||
locale TEXT,
|
locale TEXT,
|
||||||
verified BOOl,
|
verified BOOl,
|
||||||
email TEXT,
|
email TEXT,
|
||||||
flags INTEGER,
|
flags INTEGER,
|
||||||
premium INTEGER,
|
premium INTEGER,
|
||||||
pubflags INTEGER
|
pubflags INTEGER
|
||||||
)
|
)
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr const char *create_permissions = R"(
|
constexpr const char *create_permissions = R"(
|
||||||
CREATE TABLE IF NOT EXISTS permissions (
|
CREATE TABLE IF NOT EXISTS permissions (
|
||||||
id INTEGER NOT NULL,
|
id INTEGER NOT NULL,
|
||||||
channel_id INTEGER NOT NULL,
|
channel_id INTEGER NOT NULL,
|
||||||
type INTEGER NOT NULL,
|
type INTEGER NOT NULL,
|
||||||
allow INTEGER NOT NULL,
|
allow INTEGER NOT NULL,
|
||||||
deny INTEGER NOT NULL
|
deny INTEGER NOT NULL
|
||||||
)
|
)
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr const char *create_messages = R"(
|
constexpr const char *create_messages = R"(
|
||||||
CREATE TABLE IF NOT EXISTS messages (
|
CREATE TABLE IF NOT EXISTS messages (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
channel_id INTEGER NOT NULL,
|
channel_id INTEGER NOT NULL,
|
||||||
guild_id INTEGER,
|
guild_id INTEGER,
|
||||||
author_id INTEGER NOT NULL,
|
author_id INTEGER NOT NULL,
|
||||||
content TEXT NOT NULL,
|
content TEXT NOT NULL,
|
||||||
timestamp TEXT NOT NULL,
|
timestamp TEXT NOT NULL,
|
||||||
edited_timestamp TEXT,
|
edited_timestamp TEXT,
|
||||||
tts BOOL NOT NULL,
|
tts BOOL NOT NULL,
|
||||||
everyone BOOL NOT NULL,
|
everyone BOOL NOT NULL,
|
||||||
mentions TEXT NOT NULL, /* json */
|
mentions TEXT NOT NULL, /* json */
|
||||||
attachments TEXT NOT NULL, /* json */
|
attachments TEXT NOT NULL, /* json */
|
||||||
embeds TEXT NOT NULL, /* json */
|
embeds TEXT NOT NULL, /* json */
|
||||||
pinned BOOL,
|
pinned BOOL,
|
||||||
webhook_id INTEGER,
|
webhook_id INTEGER,
|
||||||
type INTEGER,
|
type INTEGER,
|
||||||
reference TEXT, /* json */
|
reference TEXT, /* json */
|
||||||
flags INTEGER,
|
flags INTEGER,
|
||||||
stickers TEXT, /* json */
|
stickers TEXT, /* json */
|
||||||
/* extra */
|
reactions TEXT, /* json */
|
||||||
deleted BOOL,
|
/* extra */
|
||||||
edited BOOL
|
deleted BOOL,
|
||||||
)
|
edited BOOL
|
||||||
)";
|
)
|
||||||
|
)";
|
||||||
|
|
||||||
constexpr const char *create_roles = R"(
|
constexpr const char *create_roles = R"(
|
||||||
CREATE TABLE IF NOT EXISTS roles (
|
CREATE TABLE IF NOT EXISTS roles (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
color INTEGER NOT NULL,
|
color INTEGER NOT NULL,
|
||||||
hoisted BOOL NOT NULL,
|
hoisted BOOL NOT NULL,
|
||||||
position INTEGER NOT NULL,
|
position INTEGER NOT NULL,
|
||||||
permissions INTEGER NOT NULL,
|
permissions INTEGER NOT NULL,
|
||||||
managed BOOL NOT NULL,
|
managed BOOL NOT NULL,
|
||||||
mentionable BOOL NOT NULL
|
mentionable BOOL NOT NULL
|
||||||
)
|
)
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr const char *create_emojis = R"(
|
constexpr const char *create_emojis = R"(
|
||||||
CREATE TABLE IF NOT EXISTS emojis (
|
CREATE TABLE IF NOT EXISTS emojis (
|
||||||
id INTEGER PRIMARY KEY, /*though nullable, only custom emojis (with non-null ids) are stored*/
|
id INTEGER PRIMARY KEY, /*though nullable, only custom emojis (with non-null ids) are stored*/
|
||||||
name TEXT NOT NULL, /*same as id*/
|
name TEXT NOT NULL, /*same as id*/
|
||||||
roles TEXT, /* json */
|
roles TEXT, /* json */
|
||||||
creator_id INTEGER,
|
creator_id INTEGER,
|
||||||
colons BOOL,
|
colons BOOL,
|
||||||
managed BOOL,
|
managed BOOL,
|
||||||
animated BOOL,
|
animated BOOL,
|
||||||
available BOOL
|
available BOOL
|
||||||
)
|
)
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr const char *create_members = R"(
|
constexpr const char *create_members = R"(
|
||||||
CREATE TABLE IF NOT EXISTS members (
|
CREATE TABLE IF NOT EXISTS members (
|
||||||
user_id INTEGER PRIMARY KEY,
|
user_id INTEGER PRIMARY KEY,
|
||||||
guild_id INTEGER NOT NULL,
|
guild_id INTEGER NOT NULL,
|
||||||
nickname TEXT,
|
nickname TEXT,
|
||||||
roles TEXT NOT NULL, /* json */
|
roles TEXT NOT NULL, /* json */
|
||||||
joined_at TEXT NOT NULL,
|
joined_at TEXT NOT NULL,
|
||||||
premium_since TEXT,
|
premium_since TEXT,
|
||||||
deaf BOOL NOT NULL,
|
deaf BOOL NOT NULL,
|
||||||
mute BOOL NOT NULL
|
mute BOOL NOT NULL
|
||||||
)
|
)
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr char *create_guilds = R"(
|
constexpr const char *create_guilds = R"(
|
||||||
CREATE TABLE IF NOT EXISTS guilds (
|
CREATE TABLE IF NOT EXISTS guilds (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
icon TEXT NOT NULL,
|
icon TEXT NOT NULL,
|
||||||
splash TEXT,
|
splash TEXT,
|
||||||
owner BOOL,
|
owner BOOL,
|
||||||
owner_id INTEGER NOT NULL,
|
owner_id INTEGER NOT NULL,
|
||||||
permissions INTEGER, /* new */
|
permissions INTEGER, /* new */
|
||||||
voice_region TEXT,
|
voice_region TEXT,
|
||||||
afk_id INTEGER,
|
afk_id INTEGER,
|
||||||
afk_timeout INTEGER NOT NULL,
|
afk_timeout INTEGER NOT NULL,
|
||||||
verification INTEGER NOT NULL,
|
verification INTEGER NOT NULL,
|
||||||
notifications INTEGER NOT NULL,
|
notifications INTEGER NOT NULL,
|
||||||
roles TEXT NOT NULL, /* json */
|
roles TEXT NOT NULL, /* json */
|
||||||
emojis TEXT NOT NULL, /* json */
|
emojis TEXT NOT NULL, /* json */
|
||||||
features TEXT NOT NULL, /* json */
|
features TEXT NOT NULL, /* json */
|
||||||
mfa INTEGER NOT NULL,
|
mfa INTEGER NOT NULL,
|
||||||
application INTEGER,
|
application INTEGER,
|
||||||
widget BOOL,
|
widget BOOL,
|
||||||
widget_channel INTEGER,
|
widget_channel INTEGER,
|
||||||
system_flags INTEGER NOT NULL,
|
system_flags INTEGER NOT NULL,
|
||||||
rules_channel INTEGER,
|
rules_channel INTEGER,
|
||||||
joined_at TEXT,
|
joined_at TEXT,
|
||||||
large BOOL,
|
large BOOL,
|
||||||
unavailable BOOL,
|
unavailable BOOL,
|
||||||
member_count INTEGER,
|
member_count INTEGER,
|
||||||
channels TEXT NOT NULL, /* json */
|
channels TEXT NOT NULL, /* json */
|
||||||
max_presences INTEGER,
|
max_presences INTEGER,
|
||||||
max_members INTEGER,
|
max_members INTEGER,
|
||||||
vanity TEXT,
|
vanity TEXT,
|
||||||
description TEXT,
|
description TEXT,
|
||||||
banner_hash TEXT,
|
banner_hash TEXT,
|
||||||
premium_tier INTEGER NOT NULL,
|
premium_tier INTEGER NOT NULL,
|
||||||
premium_count INTEGER,
|
premium_count INTEGER,
|
||||||
locale TEXT NOT NULL,
|
locale TEXT NOT NULL,
|
||||||
public_updates_id INTEGER,
|
public_updates_id INTEGER,
|
||||||
max_video_users INTEGER,
|
max_video_users INTEGER,
|
||||||
approx_members INTEGER,
|
approx_members INTEGER,
|
||||||
approx_presences INTEGER,
|
approx_presences INTEGER,
|
||||||
lazy BOOL
|
lazy BOOL
|
||||||
)
|
)
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr char *create_channels = R"(
|
constexpr const char *create_channels = R"(
|
||||||
CREATE TABLE IF NOT EXISTS channels (
|
CREATE TABLE IF NOT EXISTS channels (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
type INTEGER NOT NULL,
|
type INTEGER NOT NULL,
|
||||||
guild_id INTEGER,
|
guild_id INTEGER,
|
||||||
position INTEGER,
|
position INTEGER,
|
||||||
overwrites TEXT, /* json */
|
overwrites TEXT, /* json */
|
||||||
name TEXT,
|
name TEXT,
|
||||||
topic TEXT,
|
topic TEXT,
|
||||||
is_nsfw BOOL,
|
is_nsfw BOOL,
|
||||||
last_message_id INTEGER,
|
last_message_id INTEGER,
|
||||||
bitrate INTEGER,
|
bitrate INTEGER,
|
||||||
user_limit INTEGER,
|
user_limit INTEGER,
|
||||||
rate_limit INTEGER,
|
rate_limit INTEGER,
|
||||||
recipients TEXT, /* json */
|
recipients TEXT, /* json */
|
||||||
icon TEXT,
|
icon TEXT,
|
||||||
owner_id INTEGER,
|
owner_id INTEGER,
|
||||||
application_id INTEGER,
|
application_id INTEGER,
|
||||||
parent_id INTEGER,
|
parent_id INTEGER,
|
||||||
last_pin_timestamp TEXT
|
last_pin_timestamp TEXT
|
||||||
)
|
)
|
||||||
)";
|
)";
|
||||||
|
|
||||||
m_db_err = sqlite3_exec(m_db, create_users, nullptr, nullptr, nullptr);
|
m_db_err = sqlite3_exec(m_db, create_users, nullptr, nullptr, nullptr);
|
||||||
if (m_db_err != SQLITE_OK) {
|
if (m_db_err != SQLITE_OK) {
|
||||||
@@ -801,84 +809,84 @@ last_pin_timestamp TEXT
|
|||||||
|
|
||||||
bool Store::CreateStatements() {
|
bool Store::CreateStatements() {
|
||||||
constexpr const char *set_user = R"(
|
constexpr const char *set_user = R"(
|
||||||
REPLACE INTO users VALUES (
|
REPLACE INTO users VALUES (
|
||||||
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
|
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
|
||||||
)
|
)
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr const char *get_user = R"(
|
constexpr const char *get_user = R"(
|
||||||
SELECT * FROM users WHERE id = ?
|
SELECT * FROM users WHERE id = ?
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr const char *set_perm = R"(
|
constexpr const char *set_perm = R"(
|
||||||
REPLACE INTO permissions VALUES (
|
REPLACE INTO permissions VALUES (
|
||||||
?, ?, ?, ?, ?
|
?, ?, ?, ?, ?
|
||||||
)
|
)
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr const char *get_perm = R"(
|
constexpr const char *get_perm = R"(
|
||||||
SELECT * FROM permissions WHERE id = ? AND channel_id = ?
|
SELECT * FROM permissions WHERE id = ? AND channel_id = ?
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr const char *set_msg = R"(
|
constexpr const char *set_msg = R"(
|
||||||
REPLACE INTO messages VALUES (
|
REPLACE INTO messages VALUES (
|
||||||
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
|
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
|
||||||
)
|
)
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr const char *get_msg = R"(
|
constexpr const char *get_msg = R"(
|
||||||
SELECT * FROM messages WHERE id = ?
|
SELECT * FROM messages WHERE id = ?
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr const char *set_role = R"(
|
constexpr const char *set_role = R"(
|
||||||
REPLACE INTO roles VALUES (
|
REPLACE INTO roles VALUES (
|
||||||
?, ?, ?, ?, ?, ?, ?, ?
|
?, ?, ?, ?, ?, ?, ?, ?
|
||||||
)
|
)
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr const char *get_role = R"(
|
constexpr const char *get_role = R"(
|
||||||
SELECT * FROM roles WHERE id = ?
|
SELECT * FROM roles WHERE id = ?
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr const char *set_emoji = R"(
|
constexpr const char *set_emoji = R"(
|
||||||
REPLACE INTO emojis VALUES (
|
REPLACE INTO emojis VALUES (
|
||||||
?, ?, ?, ?, ?, ?, ?, ?
|
?, ?, ?, ?, ?, ?, ?, ?
|
||||||
)
|
)
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr const char *get_emoji = R"(
|
constexpr const char *get_emoji = R"(
|
||||||
SELECT * FROM emojis WHERE id = ?
|
SELECT * FROM emojis WHERE id = ?
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr const char *set_member = R"(
|
constexpr const char *set_member = R"(
|
||||||
REPLACE INTO members VALUES (
|
REPLACE INTO members VALUES (
|
||||||
?, ?, ?, ?, ?, ?, ?, ?
|
?, ?, ?, ?, ?, ?, ?, ?
|
||||||
)
|
)
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr const char *get_member = R"(
|
constexpr const char *get_member = R"(
|
||||||
SELECT * FROM members WHERE user_id = ? AND guild_id = ?
|
SELECT * FROM members WHERE user_id = ? AND guild_id = ?
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr const char *set_guild = R"(
|
constexpr const char *set_guild = R"(
|
||||||
REPLACE INTO guilds VALUES (
|
REPLACE INTO guilds VALUES (
|
||||||
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
|
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
|
||||||
)
|
)
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr const char *get_guild = R"(
|
constexpr const char *get_guild = R"(
|
||||||
SELECT * FROM guilds WHERE id = ?
|
SELECT * FROM guilds WHERE id = ?
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr const char *set_chan = R"(
|
constexpr const char *set_chan = R"(
|
||||||
REPLACE INTO channels VALUES (
|
REPLACE INTO channels VALUES (
|
||||||
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
|
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
|
||||||
)
|
)
|
||||||
)";
|
)";
|
||||||
|
|
||||||
constexpr const char *get_chan = R"(
|
constexpr const char *get_chan = R"(
|
||||||
SELECT * FROM channels WHERE id = ?
|
SELECT * FROM channels WHERE id = ?
|
||||||
)";
|
)";
|
||||||
|
|
||||||
m_db_err = sqlite3_prepare_v2(m_db, set_user, -1, &m_set_user_stmt, nullptr);
|
m_db_err = sqlite3_prepare_v2(m_db, set_user, -1, &m_set_user_stmt, nullptr);
|
||||||
if (m_db_err != SQLITE_OK) {
|
if (m_db_err != SQLITE_OK) {
|
||||||
|
@@ -33,6 +33,13 @@ void from_json(const nlohmann::json &j, User &m) {
|
|||||||
JS_ON("phone", m.Phone);
|
JS_ON("phone", m.Phone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void to_json(nlohmann::json &j, const User &m) {
|
||||||
|
j["id"] = m.ID;
|
||||||
|
j["username"] = m.Username;
|
||||||
|
j["avatar"] = m.Avatar;
|
||||||
|
// rest of stuff as needed im too lazy and its probably not necessary
|
||||||
|
}
|
||||||
|
|
||||||
void User::update_from_json(const nlohmann::json &j, User &m) {
|
void User::update_from_json(const nlohmann::json &j, User &m) {
|
||||||
JS_RD("username", m.Username);
|
JS_RD("username", m.Username);
|
||||||
JS_RD("discriminator", m.Discriminator);
|
JS_RD("discriminator", m.Discriminator);
|
||||||
|
@@ -25,6 +25,7 @@ struct User {
|
|||||||
std::string Phone; // null?
|
std::string Phone; // null?
|
||||||
|
|
||||||
friend void from_json(const nlohmann::json &j, User &m);
|
friend void from_json(const nlohmann::json &j, User &m);
|
||||||
|
friend void to_json(nlohmann::json &j, const User &m);
|
||||||
static void update_from_json(const nlohmann::json &j, User &m);
|
static void update_from_json(const nlohmann::json &j, User &m);
|
||||||
|
|
||||||
bool HasAvatar() const;
|
bool HasAvatar() const;
|
||||||
|
@@ -211,6 +211,14 @@ Snowflake MainWindow::GetChatOldestListedMessage() {
|
|||||||
return m_chat.GetOldestListedMessage();
|
return m_chat.GetOldestListedMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::UpdateChatReactionAdd(Snowflake id, const Glib::ustring ¶m) {
|
||||||
|
m_chat.UpdateReactions(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::UpdateChatReactionRemove(Snowflake id, const Glib::ustring ¶m) {
|
||||||
|
m_chat.UpdateReactions(id);
|
||||||
|
}
|
||||||
|
|
||||||
ChannelList *MainWindow::GetChannelList() {
|
ChannelList *MainWindow::GetChannelList() {
|
||||||
return &m_channel_list;
|
return &m_channel_list;
|
||||||
}
|
}
|
||||||
|
@@ -26,6 +26,8 @@ public:
|
|||||||
void UpdateChatPrependHistory(const std::vector<Snowflake> &msgs);
|
void UpdateChatPrependHistory(const std::vector<Snowflake> &msgs);
|
||||||
void InsertChatInput(std::string text);
|
void InsertChatInput(std::string text);
|
||||||
Snowflake GetChatOldestListedMessage();
|
Snowflake GetChatOldestListedMessage();
|
||||||
|
void UpdateChatReactionAdd(Snowflake id, const Glib::ustring ¶m);
|
||||||
|
void UpdateChatReactionRemove(Snowflake id, const Glib::ustring ¶m);
|
||||||
|
|
||||||
ChannelList *GetChannelList();
|
ChannelList *GetChannelList();
|
||||||
ChatWindow *GetChatWindow();
|
ChatWindow *GetChatWindow();
|
||||||
|
Reference in New Issue
Block a user