mirror of
https://github.com/uowuo/abaddon.git
synced 2024-11-10 06:00:10 +00:00
rudimentary chat
This commit is contained in:
parent
4b903bbd3e
commit
a201d5905a
@ -143,6 +143,7 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="abaddon.cpp" />
|
||||
<ClCompile Include="components\channels.cpp" />
|
||||
<ClCompile Include="components\chatwindow.cpp" />
|
||||
<ClCompile Include="dialogs\token.cpp" />
|
||||
<ClCompile Include="discord\discord.cpp" />
|
||||
<ClCompile Include="discord\http.cpp" />
|
||||
@ -153,6 +154,7 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="components\channels.hpp" />
|
||||
<ClInclude Include="abaddon.hpp" />
|
||||
<ClInclude Include="components\chatwindow.hpp" />
|
||||
<ClInclude Include="dialogs\token.hpp" />
|
||||
<ClInclude Include="discord\discord.hpp" />
|
||||
<ClInclude Include="discord\http.hpp" />
|
||||
|
@ -39,6 +39,9 @@
|
||||
<ClCompile Include="discord\http.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="components\chatwindow.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="windows\mainwindow.hpp">
|
||||
@ -65,5 +68,8 @@
|
||||
<ClInclude Include="discord\http.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="components\chatwindow.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
15
abaddon.cpp
15
abaddon.cpp
@ -107,7 +107,7 @@ void Abaddon::ActionMoveGuildUp(Snowflake id) {
|
||||
std::vector<Snowflake> &pos = d.GuildPositions;
|
||||
if (pos.size() == 0) {
|
||||
auto x = m_discord.GetUserSortedGuilds();
|
||||
for (const auto& pair : x)
|
||||
for (const auto &pair : x)
|
||||
pos.push_back(pair.first);
|
||||
}
|
||||
|
||||
@ -136,7 +136,20 @@ void Abaddon::ActionMoveGuildDown(Snowflake id) {
|
||||
m_discord.UpdateSettingsGuildPositions(pos);
|
||||
}
|
||||
|
||||
void Abaddon::ActionListChannelItemClick(Snowflake id) {
|
||||
m_main_window->UpdateChatActiveChannel(id);
|
||||
if (m_channels_requested.find(id) == m_channels_requested.end()) {
|
||||
m_discord.FetchMessagesInChannel(id, [this, id](const std::vector<MessageData> &msgs) {
|
||||
m_channels_requested.insert(id);
|
||||
m_main_window->UpdateChatWindowContents();
|
||||
});
|
||||
} else {
|
||||
m_main_window->UpdateChatWindowContents();
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
Gtk::Main::init_gtkmm_internals(); // why???
|
||||
Abaddon abaddon;
|
||||
return abaddon.StartGTK();
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include "discord/discord.hpp"
|
||||
#include "windows/mainwindow.hpp"
|
||||
#include "settings.hpp"
|
||||
@ -22,6 +23,7 @@ public:
|
||||
void ActionSetToken();
|
||||
void ActionMoveGuildUp(Snowflake id);
|
||||
void ActionMoveGuildDown(Snowflake id);
|
||||
void ActionListChannelItemClick(Snowflake id);
|
||||
|
||||
std::string GetDiscordToken() const;
|
||||
bool IsDiscordActive() const;
|
||||
@ -31,10 +33,12 @@ public:
|
||||
void DiscordNotifyChannelListFullRefresh();
|
||||
|
||||
private:
|
||||
DiscordClient m_discord;
|
||||
std::string m_discord_token;
|
||||
std::unordered_set<Snowflake> m_channels_requested;
|
||||
|
||||
mutable std::mutex m_mutex;
|
||||
Glib::RefPtr<Gtk::Application> m_gtk_app;
|
||||
DiscordClient m_discord;
|
||||
SettingsManager m_settings;
|
||||
std::unique_ptr<MainWindow> m_main_window; // wah wah cant create a gtkstylecontext fuck you
|
||||
};
|
||||
|
@ -52,6 +52,10 @@ void ChannelList::on_row_activated(Gtk::ListBoxRow *row) {
|
||||
bool new_collapsed = !info.IsUserCollapsed;
|
||||
info.IsUserCollapsed = new_collapsed;
|
||||
|
||||
if (info.Type == ListItemInfo::ListItemType::Channel) {
|
||||
m_abaddon->ActionListChannelItemClick(info.ID);
|
||||
}
|
||||
|
||||
if (info.CatArrow != nullptr)
|
||||
info.CatArrow->set(new_collapsed ? Gtk::ARROW_RIGHT : Gtk::ARROW_DOWN, Gtk::SHADOW_NONE);
|
||||
|
||||
@ -143,6 +147,7 @@ void ChannelList::SetListingFromGuildsInternal() {
|
||||
info.ID = id;
|
||||
info.IsUserCollapsed = false;
|
||||
info.IsHidden = false;
|
||||
info.Type = ListItemInfo::ListItemType::Channel;
|
||||
|
||||
m_infos[channel_row] = std::move(info);
|
||||
return channel_row;
|
||||
@ -168,6 +173,7 @@ void ChannelList::SetListingFromGuildsInternal() {
|
||||
info.IsUserCollapsed = false;
|
||||
info.IsHidden = true;
|
||||
info.CatArrow = category_arrow;
|
||||
info.Type = ListItemInfo::ListItemType::Category;
|
||||
|
||||
if (cat_to_channels.find(id) != cat_to_channels.end()) {
|
||||
std::map<int, const ChannelData *> sorted_channels;
|
||||
@ -206,6 +212,7 @@ void ChannelList::SetListingFromGuildsInternal() {
|
||||
info.IsUserCollapsed = true;
|
||||
info.IsHidden = false;
|
||||
info.GuildIndex = m_guild_count++;
|
||||
info.Type = ListItemInfo::ListItemType::Guild;
|
||||
|
||||
if (orphan_channels.find(id) != orphan_channels.end()) {
|
||||
std::map<int, const ChannelData *> sorted_orphans;
|
||||
|
@ -21,11 +21,17 @@ protected:
|
||||
Gtk::ScrolledWindow *m_main;
|
||||
|
||||
struct ListItemInfo {
|
||||
enum ListItemType {
|
||||
Guild,
|
||||
Category,
|
||||
Channel,
|
||||
};
|
||||
int GuildIndex;
|
||||
Snowflake ID;
|
||||
std::unordered_set<Gtk::ListBoxRow *> Children;
|
||||
bool IsUserCollapsed;
|
||||
bool IsHidden;
|
||||
ListItemType Type;
|
||||
// for categories
|
||||
Gtk::Arrow *CatArrow = nullptr;
|
||||
};
|
||||
|
164
components/chatwindow.cpp
Normal file
164
components/chatwindow.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
#include "chatwindow.hpp"
|
||||
#include <map>
|
||||
|
||||
ChatWindow::ChatWindow() {
|
||||
m_update_dispatcher.connect(sigc::mem_fun(*this, &ChatWindow::SetMessagesInternal));
|
||||
|
||||
m_main = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
|
||||
m_listbox = Gtk::manage(new Gtk::ListBox);
|
||||
m_viewport = Gtk::manage(new Gtk::Viewport(Gtk::Adjustment::create(0, 0, 0, 0, 0, 0), Gtk::Adjustment::create(0, 0, 0, 0, 0, 0)));
|
||||
m_scroll = Gtk::manage(new Gtk::ScrolledWindow);
|
||||
m_input = Gtk::manage(new Gtk::TextView);
|
||||
m_entry_scroll = Gtk::manage(new Gtk::ScrolledWindow);
|
||||
|
||||
m_main->set_hexpand(true);
|
||||
m_main->set_vexpand(true);
|
||||
m_main->show();
|
||||
|
||||
m_scroll->set_can_focus(false);
|
||||
m_scroll->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_ALWAYS);
|
||||
m_scroll->show();
|
||||
|
||||
m_listbox->signal_size_allocate().connect([this](Gtk::Allocation &) {
|
||||
ScrollToBottom();
|
||||
});
|
||||
|
||||
m_listbox->set_selection_mode(Gtk::SELECTION_NONE);
|
||||
m_listbox->set_hexpand(true);
|
||||
m_listbox->set_vexpand(true);
|
||||
m_listbox->set_focus_hadjustment(m_scroll->get_hadjustment());
|
||||
m_listbox->set_focus_vadjustment(m_scroll->get_vadjustment());
|
||||
m_listbox->show();
|
||||
|
||||
m_viewport->set_can_focus(false);
|
||||
m_viewport->set_valign(Gtk::ALIGN_END);
|
||||
m_viewport->set_vscroll_policy(Gtk::SCROLL_NATURAL);
|
||||
m_viewport->set_shadow_type(Gtk::SHADOW_NONE);
|
||||
m_viewport->show();
|
||||
|
||||
m_input->set_hexpand(true);
|
||||
m_input->set_wrap_mode(Gtk::WRAP_WORD_CHAR);
|
||||
m_input->show();
|
||||
|
||||
m_entry_scroll->set_max_content_height(150);
|
||||
m_entry_scroll->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
|
||||
m_entry_scroll->add(*m_input);
|
||||
m_entry_scroll->show();
|
||||
|
||||
m_viewport->add(*m_listbox);
|
||||
m_scroll->add(*m_viewport);
|
||||
m_main->add(*m_scroll);
|
||||
m_main->add(*m_entry_scroll);
|
||||
}
|
||||
|
||||
Gtk::Widget *ChatWindow::GetRoot() const {
|
||||
return m_main;
|
||||
}
|
||||
|
||||
void ChatWindow::SetActiveChannel(Snowflake id) {
|
||||
m_active_channel = id;
|
||||
}
|
||||
|
||||
Snowflake ChatWindow::GetActiveChannel() const {
|
||||
return m_active_channel;
|
||||
}
|
||||
|
||||
Gtk::ListBoxRow *ChatWindow::CreateChatEntryComponentText(const MessageData *data) {
|
||||
auto *row = Gtk::manage(new Gtk::ListBoxRow);
|
||||
auto *main_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
|
||||
auto *sub_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
|
||||
auto *meta_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
|
||||
auto *author = Gtk::manage(new Gtk::Label);
|
||||
auto *timestamp = Gtk::manage(new Gtk::Label);
|
||||
auto *text = Gtk::manage(new Gtk::TextView);
|
||||
|
||||
text->set_can_focus(false);
|
||||
text->set_editable(false);
|
||||
text->set_wrap_mode(Gtk::WRAP_WORD_CHAR);
|
||||
text->set_halign(Gtk::ALIGN_FILL);
|
||||
text->set_hexpand(true);
|
||||
text->get_buffer()->set_text(data->Content);
|
||||
text->show();
|
||||
|
||||
author->set_markup("<span weight=\"bold\">" + Glib::Markup::escape_text(data->Author.Username) + "</span>");
|
||||
author->set_single_line_mode(true);
|
||||
author->set_line_wrap(false);
|
||||
author->set_ellipsize(Pango::ELLIPSIZE_END);
|
||||
author->set_xalign(0.f);
|
||||
author->show();
|
||||
|
||||
timestamp->set_text(data->Timestamp);
|
||||
timestamp->set_opacity(0.5);
|
||||
timestamp->set_single_line_mode(true);
|
||||
timestamp->set_margin_start(12);
|
||||
timestamp->show();
|
||||
|
||||
main_box->set_hexpand(true);
|
||||
main_box->set_vexpand(true);
|
||||
main_box->show();
|
||||
|
||||
meta_box->show();
|
||||
sub_box->show();
|
||||
|
||||
meta_box->add(*author);
|
||||
meta_box->add(*timestamp);
|
||||
sub_box->add(*meta_box);
|
||||
sub_box->add(*text);
|
||||
main_box->add(*sub_box);
|
||||
row->add(*main_box);
|
||||
row->set_margin_bottom(8);
|
||||
|
||||
row->show();
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
Gtk::ListBoxRow *ChatWindow::CreateChatEntryComponent(const MessageData *data) {
|
||||
if (data->Type == MessageType::DEFAULT && data->Content.size() > 0)
|
||||
return CreateChatEntryComponentText(data);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ChatWindow::SetMessages(std::unordered_set<const MessageData *> msgs) {
|
||||
std::scoped_lock<std::mutex> guard(m_update_mutex);
|
||||
m_update_queue.push(msgs);
|
||||
m_update_dispatcher.emit();
|
||||
}
|
||||
|
||||
void ChatWindow::ScrollToBottom() {
|
||||
auto x = m_scroll->get_vadjustment();
|
||||
x->set_value(x->get_upper());
|
||||
}
|
||||
|
||||
void ChatWindow::SetMessagesInternal() {
|
||||
auto children = m_listbox->get_children();
|
||||
auto it = children.begin();
|
||||
|
||||
while (it != children.end()) {
|
||||
delete *it;
|
||||
it++;
|
||||
}
|
||||
|
||||
std::unordered_set<const MessageData *> *msgs;
|
||||
{
|
||||
std::scoped_lock<std::mutex> guard(m_update_mutex);
|
||||
msgs = &m_update_queue.front();
|
||||
}
|
||||
|
||||
// sort
|
||||
std::map<Snowflake, const MessageData *> sorted_messages;
|
||||
for (const auto msg : *msgs)
|
||||
sorted_messages[msg->ID] = msg;
|
||||
|
||||
for (const auto &[id, msg] : sorted_messages) {
|
||||
auto *row = CreateChatEntryComponent(msg);
|
||||
if (row != nullptr)
|
||||
m_listbox->add(*row);
|
||||
}
|
||||
|
||||
{
|
||||
std::scoped_lock<std::mutex> guard(m_update_mutex);
|
||||
m_update_queue.pop();
|
||||
}
|
||||
}
|
33
components/chatwindow.hpp
Normal file
33
components/chatwindow.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
#include <gtkmm.h>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include "../discord/discord.hpp"
|
||||
|
||||
class ChatWindow {
|
||||
public:
|
||||
ChatWindow();
|
||||
Gtk::Widget *GetRoot() const;
|
||||
void SetActiveChannel(Snowflake id);
|
||||
Snowflake GetActiveChannel() const;
|
||||
void SetMessages(std::unordered_set<const MessageData *> msgs);
|
||||
|
||||
protected:
|
||||
void ScrollToBottom();
|
||||
void SetMessagesInternal();
|
||||
Gtk::ListBoxRow *CreateChatEntryComponentText(const MessageData *data);
|
||||
Gtk::ListBoxRow *CreateChatEntryComponent(const MessageData *data);
|
||||
|
||||
Glib::Dispatcher m_update_dispatcher;
|
||||
std::queue<std::unordered_set<const MessageData *>> m_update_queue;
|
||||
std::mutex m_update_mutex;
|
||||
|
||||
Snowflake m_active_channel;
|
||||
|
||||
Gtk::Box *m_main;
|
||||
Gtk::ListBox *m_listbox;
|
||||
Gtk::Viewport *m_viewport;
|
||||
Gtk::ScrolledWindow *m_scroll;
|
||||
Gtk::ScrolledWindow *m_entry_scroll;
|
||||
Gtk::TextView *m_input;
|
||||
};
|
@ -84,6 +84,13 @@ std::vector<std::pair<Snowflake, GuildData>> DiscordClient::GetUserSortedGuilds(
|
||||
return sorted_guilds;
|
||||
}
|
||||
|
||||
std::unordered_set<const MessageData *> DiscordClient::GetMessagesForChannel(Snowflake id) const {
|
||||
auto it = m_chan_to_message_map.find(id);
|
||||
if (it == m_chan_to_message_map.end())
|
||||
return std::unordered_set<const MessageData *>();
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void DiscordClient::UpdateSettingsGuildPositions(const std::vector<Snowflake> &pos) {
|
||||
assert(pos.size() == m_guilds.size());
|
||||
nlohmann::json body;
|
||||
@ -94,6 +101,18 @@ void DiscordClient::UpdateSettingsGuildPositions(const std::vector<Snowflake> &p
|
||||
});
|
||||
}
|
||||
|
||||
void DiscordClient::FetchMessagesInChannel(Snowflake id, std::function<void(const std::vector<MessageData> &)> cb) {
|
||||
std::string path = "/channels/" + std::to_string(id) + "/messages?limit=50";
|
||||
m_http.MakeGET(path, [this, id, cb](cpr::Response r) {
|
||||
std::vector<MessageData> msgs;
|
||||
nlohmann::json::parse(r.text).get_to(msgs);
|
||||
for (const auto &msg : msgs)
|
||||
StoreMessage(msg.ID, msg);
|
||||
|
||||
cb(msgs);
|
||||
});
|
||||
}
|
||||
|
||||
void DiscordClient::UpdateToken(std::string token) {
|
||||
m_token = token;
|
||||
m_http.SetAuth(token);
|
||||
@ -153,6 +172,15 @@ void DiscordClient::StoreGuild(Snowflake id, const GuildData &g) {
|
||||
m_guilds[id] = g;
|
||||
}
|
||||
|
||||
void DiscordClient::StoreMessage(Snowflake id, const MessageData &m) {
|
||||
assert(id.IsValid());
|
||||
m_messages[id] = m;
|
||||
auto it = m_chan_to_message_map.find(m.ChannelID);
|
||||
if (it == m_chan_to_message_map.end())
|
||||
m_chan_to_message_map[m.ChannelID] = decltype(m_chan_to_message_map)::mapped_type();
|
||||
m_chan_to_message_map[m.ChannelID].insert(&m_messages[id]);
|
||||
}
|
||||
|
||||
void DiscordClient::HeartbeatThread() {
|
||||
while (m_client_connected) {
|
||||
if (!m_heartbeat_acked) {
|
||||
@ -308,6 +336,33 @@ void from_json(const nlohmann::json &j, ChannelData &m) {
|
||||
JS_ON("last_pin_timestamp", m.LastPinTimestamp);
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json &j, MessageData &m) {
|
||||
JS_D("id", m.ID);
|
||||
JS_D("channel_id", m.ChannelID);
|
||||
JS_O("guild_id", m.GuildID);
|
||||
JS_D("author", m.Author);
|
||||
// JS_O("member", m.Member);
|
||||
JS_D("content", m.Content);
|
||||
JS_D("timestamp", m.Timestamp);
|
||||
JS_N("edited_timestamp", m.EditedTimestamp);
|
||||
JS_D("tts", m.IsTTS);
|
||||
JS_D("mention_everyone", m.DoesMentionEveryone);
|
||||
JS_D("mentions", m.Mentions);
|
||||
// JS_D("mention_roles", m.MentionRoles);
|
||||
// JS_O("mention_channels", m.MentionChannels);
|
||||
// JS_D("attachments", m.Attachments);
|
||||
// JS_D("embeds", m.Embeds);
|
||||
// JS_O("reactions", m.Reactions);
|
||||
JS_O("nonce", m.Nonce);
|
||||
JS_D("pinned", m.IsPinned);
|
||||
JS_O("webhook_id", m.WebhookID);
|
||||
JS_D("type", m.Type);
|
||||
// JS_O("activity", m.Activity);
|
||||
// JS_O("application", m.Application);
|
||||
// JS_O("message_reference", m.MessageReference);
|
||||
JS_O("flags", m.Flags);
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json &j, ReadyEventData &m) {
|
||||
JS_D("v", m.GatewayVersion);
|
||||
JS_D("user", m.User);
|
||||
@ -400,7 +455,7 @@ void from_json(const nlohmann::json &j, Snowflake &s) {
|
||||
s.m_num = std::stoull(tmp);
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json& j, const Snowflake& s) {
|
||||
void to_json(nlohmann::json &j, const Snowflake &s) {
|
||||
j = std::to_string(s);
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <mutex>
|
||||
|
||||
struct Snowflake {
|
||||
@ -33,6 +34,7 @@ struct Snowflake {
|
||||
|
||||
private:
|
||||
friend struct std::hash<Snowflake>;
|
||||
friend struct std::less<Snowflake>;
|
||||
unsigned long long m_num;
|
||||
};
|
||||
|
||||
@ -43,6 +45,13 @@ struct hash<Snowflake> {
|
||||
return k.m_num;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct less<Snowflake> {
|
||||
bool operator()(const Snowflake &l, const Snowflake &r) const {
|
||||
return l.m_num < r.m_num;
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
enum class GatewayOp : int {
|
||||
@ -222,6 +231,62 @@ struct UserSettingsData {
|
||||
friend void from_json(const nlohmann::json &j, UserSettingsData &m);
|
||||
};
|
||||
|
||||
enum class MessageType {
|
||||
DEFAULT = 0,
|
||||
RECIPIENT_ADD = 1,
|
||||
RECIPIENT_REMOVE = 2,
|
||||
CALL = 3,
|
||||
CHANNEL_NaME_CHANGE = 4,
|
||||
CHANNEL_ICON_CHANGE = 5,
|
||||
CHANNEL_PINNED_MESSAGE = 6,
|
||||
GUILD_MEMBER_JOIN = 6,
|
||||
USER_PREMIUM_GUILD_SUBSCRIPTION = 7,
|
||||
USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1 = 8,
|
||||
USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2 = 9,
|
||||
USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3 = 10,
|
||||
CHANNEL_FOLLOW_ADD = 12,
|
||||
GUILD_DISCOVERY_DISQUALIFIED = 13,
|
||||
GUILD_DISCOVERY_REQUALIFIED = 14,
|
||||
};
|
||||
|
||||
enum class MessageFlags {
|
||||
NONE = 0,
|
||||
CROSSPOSTED = 1 << 0,
|
||||
IS_CROSSPOST = 1 << 1,
|
||||
SUPPRESS_EMBEDS = 1 << 2,
|
||||
SOURCE_MESSAGE_DELETE = 1 << 3,
|
||||
URGENT = 1 << 4,
|
||||
};
|
||||
|
||||
struct MessageData {
|
||||
Snowflake ID; //
|
||||
Snowflake ChannelID; //
|
||||
Snowflake GuildID; // opt
|
||||
UserData Author; //
|
||||
// GuildMemberData Member; // opt
|
||||
std::string Content; //
|
||||
std::string Timestamp; //
|
||||
std::string EditedTimestamp; // null
|
||||
bool IsTTS; //
|
||||
bool DoesMentionEveryone; //
|
||||
std::vector<UserData> Mentions; //
|
||||
// std::vector<RoleData> MentionRoles; //
|
||||
// std::vector<ChannelMentionData> MentionChannels; // opt
|
||||
// std::vector<AttachmentData> Attachments; //
|
||||
// std::vector<EmbedData> Embeds; //
|
||||
// std::vector<ReactionData> Reactions; // opt
|
||||
std::string Nonce; // opt
|
||||
bool IsPinned; //
|
||||
Snowflake WebhookID; // opt
|
||||
MessageType Type; //
|
||||
// MessageActivityData Activity; // opt
|
||||
// MessageApplicationData Application; // opt
|
||||
// MessageReferenceData MessageReference; // opt
|
||||
MessageFlags Flags = MessageFlags::NONE; // opt
|
||||
|
||||
friend void from_json(const nlohmann::json &j, MessageData &m);
|
||||
};
|
||||
|
||||
struct ReadyEventData {
|
||||
int GatewayVersion; //
|
||||
UserData User; //
|
||||
@ -307,10 +372,15 @@ public:
|
||||
bool IsStarted() const;
|
||||
|
||||
using Guilds_t = std::unordered_map<Snowflake, GuildData>;
|
||||
using Messages_t = std::unordered_map<Snowflake, MessageData>;
|
||||
|
||||
const Guilds_t &GetGuilds() const;
|
||||
const UserSettingsData &GetUserSettings() const;
|
||||
std::vector<std::pair<Snowflake, GuildData>> GetUserSortedGuilds() const;
|
||||
std::unordered_set<const MessageData *> GetMessagesForChannel(Snowflake id) const;
|
||||
|
||||
void UpdateSettingsGuildPositions(const std::vector<Snowflake> &pos);
|
||||
void FetchMessagesInChannel(Snowflake id, std::function<void(const std::vector<MessageData> &)> cb);
|
||||
|
||||
void UpdateToken(std::string token);
|
||||
|
||||
@ -330,6 +400,10 @@ private:
|
||||
void StoreGuild(Snowflake id, const GuildData &g);
|
||||
Guilds_t m_guilds;
|
||||
|
||||
void StoreMessage(Snowflake id, const MessageData &m);
|
||||
Messages_t m_messages;
|
||||
std::unordered_map<Snowflake, std::unordered_set<const MessageData *>> m_chan_to_message_map;
|
||||
|
||||
UserSettingsData m_user_settings;
|
||||
|
||||
Websocket m_websocket;
|
||||
|
@ -36,6 +36,37 @@ void HTTPClient::MakePOST(std::string path, std::string payload, std::function<v
|
||||
{ "Content-Type", "application/json" },
|
||||
};
|
||||
auto body = cpr::Body { payload };
|
||||
#ifdef USE_LOCAL_PROXY
|
||||
m_futures.push_back(cpr::GetCallback(
|
||||
std::bind(&HTTPClient::OnResponse, this, std::placeholders::_1, cb),
|
||||
url, headers, body,
|
||||
cpr::Proxies { { "http", "127.0.0.1:8888" }, { "https", "127.0.0.1:8888" } },
|
||||
cpr::VerifySsl { false }));
|
||||
#else
|
||||
m_futures.push_back(cpr::PatchCallback(
|
||||
std::bind(&HTTPClient::OnResponse, this, std::placeholders::_1, cb),
|
||||
url, headers, body));
|
||||
#endif
|
||||
}
|
||||
|
||||
void HTTPClient::MakeGET(std::string path, std::function<void(cpr::Response r)> cb) {
|
||||
printf("POST %s\n", path.c_str());
|
||||
auto url = cpr::Url { m_api_base + path };
|
||||
auto headers = cpr::Header {
|
||||
{ "Authorization", m_authorization },
|
||||
{ "Content-Type", "application/json" },
|
||||
};
|
||||
#ifdef USE_LOCAL_PROXY
|
||||
m_futures.push_back(cpr::GetCallback(
|
||||
std::bind(&HTTPClient::OnResponse, this, std::placeholders::_1, cb),
|
||||
url, headers,
|
||||
cpr::Proxies { { "http", "127.0.0.1:8888" }, { "https", "127.0.0.1:8888" } },
|
||||
cpr::VerifySsl { false }));
|
||||
#else
|
||||
m_futures.push_back(cpr::GetCallback(
|
||||
std::bind(&HTTPClient::OnResponse, this, std::placeholders::_1, cb),
|
||||
url, headers));
|
||||
#endif
|
||||
}
|
||||
|
||||
void HTTPClient::CleanupFutures() {
|
||||
|
@ -19,6 +19,7 @@ public:
|
||||
HTTPClient(std::string api_base);
|
||||
|
||||
void SetAuth(std::string auth);
|
||||
void MakeGET(std::string path, std::function<void(cpr::Response r)> cb);
|
||||
void MakePATCH(std::string path, std::string payload, std::function<void(cpr::Response r)> cb);
|
||||
void MakePOST(std::string path, std::string payload, std::function<void(cpr::Response r)> cb);
|
||||
|
||||
|
@ -3,7 +3,8 @@
|
||||
|
||||
MainWindow::MainWindow()
|
||||
: m_main_box(Gtk::ORIENTATION_VERTICAL)
|
||||
, m_content_box(Gtk::ORIENTATION_HORIZONTAL) {
|
||||
, m_content_box(Gtk::ORIENTATION_HORIZONTAL)
|
||||
, m_chan_chat_paned(Gtk::ORIENTATION_HORIZONTAL) {
|
||||
set_default_size(800, 600);
|
||||
|
||||
m_menu_discord.set_label("Discord");
|
||||
@ -20,7 +21,7 @@ MainWindow::MainWindow()
|
||||
m_menu_bar.append(m_menu_discord);
|
||||
|
||||
m_menu_discord_connect.signal_activate().connect([&] {
|
||||
m_abaddon->ActionConnect(); // this feels maybe not too smart
|
||||
m_abaddon->ActionConnect();
|
||||
});
|
||||
|
||||
m_menu_discord_disconnect.signal_activate().connect([&] {
|
||||
@ -38,9 +39,17 @@ MainWindow::MainWindow()
|
||||
m_main_box.add(m_content_box);
|
||||
|
||||
auto *channel_list = m_channel_list.GetRoot();
|
||||
channel_list->set_hexpand(true);
|
||||
channel_list->set_vexpand(true);
|
||||
m_content_box.add(*channel_list);
|
||||
channel_list->set_size_request(-1, -1);
|
||||
m_chan_chat_paned.pack1(*channel_list);
|
||||
auto *chat = m_chat.GetRoot();
|
||||
chat->set_vexpand(true);
|
||||
chat->set_hexpand(true);
|
||||
m_chan_chat_paned.pack2(*chat);
|
||||
m_chan_chat_paned.set_position(200);
|
||||
m_chan_chat_paned.child_property_shrink(*channel_list) = true;
|
||||
m_chan_chat_paned.child_property_resize(*channel_list) = true;
|
||||
m_content_box.add(m_chan_chat_paned);
|
||||
|
||||
add(m_main_box);
|
||||
|
||||
@ -70,6 +79,15 @@ void MainWindow::UpdateChannelListing() {
|
||||
m_channel_list.SetListingFromGuilds(discord.GetGuilds());
|
||||
}
|
||||
|
||||
void MainWindow::UpdateChatWindowContents() {
|
||||
auto &discord = m_abaddon->GetDiscordClient();
|
||||
m_chat.SetMessages(discord.GetMessagesForChannel(m_chat.GetActiveChannel()));
|
||||
}
|
||||
|
||||
void MainWindow::UpdateChatActiveChannel(Snowflake id) {
|
||||
m_chat.SetActiveChannel(id);
|
||||
}
|
||||
|
||||
void MainWindow::SetAbaddon(Abaddon *ptr) {
|
||||
m_abaddon = ptr;
|
||||
m_channel_list.SetAbaddon(ptr);
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "../components/channels.hpp"
|
||||
#include "../components/chatwindow.hpp"
|
||||
#include <gtkmm.h>
|
||||
|
||||
class Abaddon;
|
||||
@ -10,12 +11,16 @@ public:
|
||||
|
||||
void UpdateComponents();
|
||||
void UpdateChannelListing();
|
||||
void UpdateChatWindowContents();
|
||||
void UpdateChatActiveChannel(Snowflake id);
|
||||
|
||||
protected:
|
||||
Gtk::Box m_main_box;
|
||||
Gtk::Box m_content_box;
|
||||
Gtk::Paned m_chan_chat_paned;
|
||||
|
||||
ChannelList m_channel_list;
|
||||
ChatWindow m_chat;
|
||||
|
||||
Gtk::MenuBar m_menu_bar;
|
||||
Gtk::MenuItem m_menu_discord;
|
||||
|
Loading…
Reference in New Issue
Block a user