join/leave guild

This commit is contained in:
ouwou
2020-09-21 18:47:34 -04:00
parent 23b32f8de9
commit 3b4edbfa16
17 changed files with 347 additions and 17 deletions

View File

@@ -128,8 +128,8 @@ add_executable(abaddon
abaddon.cpp abaddon.cpp
filecache.hpp filecache.hpp
filecache.cpp filecache.cpp
"imgmanager.hpp" imgmanager.hpp
"imgmanager.cpp" imgmanager.cpp
components/channels.hpp components/channels.hpp
components/channels.cpp components/channels.cpp
components/chatmessage.hpp components/chatmessage.hpp
@@ -140,6 +140,8 @@ add_executable(abaddon
components/memberlist.cpp components/memberlist.cpp
dialogs/editmessage.hpp dialogs/editmessage.hpp
dialogs/editmessage.cpp dialogs/editmessage.cpp
dialogs/joinguild.hpp
dialogs/joinguild.cpp
dialogs/token.hpp dialogs/token.hpp
dialogs/token.cpp dialogs/token.cpp
discord/discord.hpp discord/discord.hpp
@@ -169,6 +171,8 @@ add_executable(abaddon
discord/usersettings.cpp discord/usersettings.cpp
discord/message.hpp discord/message.hpp
discord/message.cpp discord/message.cpp
discord/invite.hpp
discord/invite.cpp
windows/mainwindow.hpp windows/mainwindow.hpp
windows/mainwindow.cpp windows/mainwindow.cpp
) )

View File

@@ -5,6 +5,7 @@
#include "discord/discord.hpp" #include "discord/discord.hpp"
#include "dialogs/token.hpp" #include "dialogs/token.hpp"
#include "dialogs/editmessage.hpp" #include "dialogs/editmessage.hpp"
#include "dialogs/joinguild.hpp"
#include "abaddon.hpp" #include "abaddon.hpp"
#ifdef _WIN32 #ifdef _WIN32
@@ -21,6 +22,8 @@ Abaddon::Abaddon()
m_discord.signal_message_delete().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnMessageDelete)); m_discord.signal_message_delete().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnMessageDelete));
m_discord.signal_message_update().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnMessageUpdate)); m_discord.signal_message_update().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnMessageUpdate));
m_discord.signal_guild_member_list_update().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnGuildMemberListUpdate)); m_discord.signal_guild_member_list_update().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnGuildMemberListUpdate));
m_discord.signal_guild_create().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnGuildCreate));
m_discord.signal_guild_delete().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnGuildDelete));
} }
Abaddon::~Abaddon() { Abaddon::~Abaddon() {
@@ -52,11 +55,13 @@ int Abaddon::StartGTK() {
m_main_window->signal_action_disconnect().connect(sigc::mem_fun(*this, &Abaddon::ActionDisconnect)); m_main_window->signal_action_disconnect().connect(sigc::mem_fun(*this, &Abaddon::ActionDisconnect));
m_main_window->signal_action_set_token().connect(sigc::mem_fun(*this, &Abaddon::ActionSetToken)); m_main_window->signal_action_set_token().connect(sigc::mem_fun(*this, &Abaddon::ActionSetToken));
m_main_window->signal_action_reload_css().connect(sigc::mem_fun(*this, &Abaddon::ActionReloadCSS)); m_main_window->signal_action_reload_css().connect(sigc::mem_fun(*this, &Abaddon::ActionReloadCSS));
m_main_window->signal_action_join_guild().connect(sigc::mem_fun(*this, &Abaddon::ActionJoinGuildDialog));
m_main_window->GetChannelList()->signal_action_channel_item_select().connect(sigc::mem_fun(*this, &Abaddon::ActionListChannelItemClick)); m_main_window->GetChannelList()->signal_action_channel_item_select().connect(sigc::mem_fun(*this, &Abaddon::ActionListChannelItemClick));
m_main_window->GetChannelList()->signal_action_guild_move_up().connect(sigc::mem_fun(*this, &Abaddon::ActionMoveGuildUp)); m_main_window->GetChannelList()->signal_action_guild_move_up().connect(sigc::mem_fun(*this, &Abaddon::ActionMoveGuildUp));
m_main_window->GetChannelList()->signal_action_guild_move_down().connect(sigc::mem_fun(*this, &Abaddon::ActionMoveGuildDown)); m_main_window->GetChannelList()->signal_action_guild_move_down().connect(sigc::mem_fun(*this, &Abaddon::ActionMoveGuildDown));
m_main_window->GetChannelList()->signal_action_guild_copy_id().connect(sigc::mem_fun(*this, &Abaddon::ActionCopyGuildID)); m_main_window->GetChannelList()->signal_action_guild_copy_id().connect(sigc::mem_fun(*this, &Abaddon::ActionCopyGuildID));
m_main_window->GetChannelList()->signal_action_guild_leave().connect(sigc::mem_fun(*this, &Abaddon::ActionLeaveGuild));
m_main_window->GetChatWindow()->signal_action_message_delete().connect(sigc::mem_fun(*this, &Abaddon::ActionChatDeleteMessage)); m_main_window->GetChatWindow()->signal_action_message_delete().connect(sigc::mem_fun(*this, &Abaddon::ActionChatDeleteMessage));
m_main_window->GetChatWindow()->signal_action_message_edit().connect(sigc::mem_fun(*this, &Abaddon::ActionChatEditMessage)); m_main_window->GetChatWindow()->signal_action_message_edit().connect(sigc::mem_fun(*this, &Abaddon::ActionChatEditMessage));
@@ -103,6 +108,11 @@ std::string Abaddon::GetDiscordToken() const {
return m_discord_token; return m_discord_token;
} }
DiscordClient &Abaddon::GetDiscordClient() {
std::scoped_lock<std::mutex> guard(m_mutex);
return m_discord;
}
const DiscordClient &Abaddon::GetDiscordClient() const { const DiscordClient &Abaddon::GetDiscordClient() const {
std::scoped_lock<std::mutex> guard(m_mutex); std::scoped_lock<std::mutex> guard(m_mutex);
return m_discord; return m_discord;
@@ -132,6 +142,14 @@ void Abaddon::DiscordOnGuildMemberListUpdate(Snowflake guild_id) {
m_main_window->UpdateMembers(); m_main_window->UpdateMembers();
} }
void Abaddon::DiscordOnGuildCreate(Snowflake guild_id) {
m_main_window->UpdateChannelListing();
}
void Abaddon::DiscordOnGuildDelete(Snowflake guild_id) {
m_main_window->UpdateChannelListing();
}
void Abaddon::ActionConnect() { void Abaddon::ActionConnect() {
if (!m_discord.IsStarted()) if (!m_discord.IsStarted())
StartDiscord(); StartDiscord();
@@ -160,6 +178,15 @@ void Abaddon::ActionSetToken() {
} }
} }
void Abaddon::ActionJoinGuildDialog() {
JoinGuildDialog dlg(*m_main_window);
auto response = dlg.run();
if (response == Gtk::RESPONSE_OK) {
auto code = dlg.GetCode();
m_discord.JoinGuild(code);
}
}
void Abaddon::ActionMoveGuildUp(Snowflake id) { void Abaddon::ActionMoveGuildUp(Snowflake id) {
auto order = m_discord.GetUserSortedGuilds(); auto order = m_discord.GetUserSortedGuilds();
// get iter to target // get iter to target
@@ -286,6 +313,10 @@ void Abaddon::ActionInsertMention(Snowflake id) {
m_main_window->InsertChatInput("<@" + std::to_string(id) + ">"); m_main_window->InsertChatInput("<@" + std::to_string(id) + ">");
} }
void Abaddon::ActionLeaveGuild(Snowflake id) {
m_discord.LeaveGuild(id);
}
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);

View File

@@ -31,6 +31,7 @@ public:
void ActionConnect(); void ActionConnect();
void ActionDisconnect(); void ActionDisconnect();
void ActionSetToken(); void ActionSetToken();
void ActionJoinGuildDialog();
void ActionMoveGuildUp(Snowflake id); void ActionMoveGuildUp(Snowflake id);
void ActionMoveGuildDown(Snowflake id); void ActionMoveGuildDown(Snowflake id);
void ActionCopyGuildID(Snowflake id); void ActionCopyGuildID(Snowflake id);
@@ -40,6 +41,7 @@ public:
void ActionChatDeleteMessage(Snowflake channel_id, Snowflake id); void ActionChatDeleteMessage(Snowflake channel_id, Snowflake id);
void ActionChatEditMessage(Snowflake channel_id, Snowflake id); void ActionChatEditMessage(Snowflake channel_id, Snowflake id);
void ActionInsertMention(Snowflake id); void ActionInsertMention(Snowflake id);
void ActionLeaveGuild(Snowflake id);
void ActionReloadCSS(); void ActionReloadCSS();
@@ -48,6 +50,7 @@ public:
std::string GetDiscordToken() const; std::string GetDiscordToken() const;
bool IsDiscordActive() const; bool IsDiscordActive() const;
DiscordClient &GetDiscordClient();
const DiscordClient &GetDiscordClient() const; const DiscordClient &GetDiscordClient() const;
void DiscordOnReady(); void DiscordOnReady();
void DiscordOnChannelListRefresh(); void DiscordOnChannelListRefresh();
@@ -55,6 +58,8 @@ public:
void DiscordOnMessageDelete(Snowflake id, Snowflake channel_id); void DiscordOnMessageDelete(Snowflake id, Snowflake channel_id);
void DiscordOnMessageUpdate(Snowflake id, Snowflake channel_id); void DiscordOnMessageUpdate(Snowflake id, Snowflake channel_id);
void DiscordOnGuildMemberListUpdate(Snowflake guild_id); void DiscordOnGuildMemberListUpdate(Snowflake guild_id);
void DiscordOnGuildCreate(Snowflake guild_id);
void DiscordOnGuildDelete(Snowflake guild_id);
private: private:
DiscordClient m_discord; DiscordClient m_discord;

View File

@@ -149,6 +149,10 @@ ChannelList::ChannelList() {
m_guild_menu_copyid->signal_activate().connect(sigc::mem_fun(*this, &ChannelList::on_menu_copyid)); m_guild_menu_copyid->signal_activate().connect(sigc::mem_fun(*this, &ChannelList::on_menu_copyid));
m_guild_menu.append(*m_guild_menu_copyid); m_guild_menu.append(*m_guild_menu_copyid);
m_guild_menu_leave = Gtk::manage(new Gtk::MenuItem("_Leave Guild", true));
m_guild_menu_leave->signal_activate().connect(sigc::mem_fun(*this, &ChannelList::on_menu_leave));
m_guild_menu.append(*m_guild_menu_leave);
m_guild_menu.show_all(); m_guild_menu.show_all();
m_list->set_activate_on_single_click(true); m_list->set_activate_on_single_click(true);
@@ -339,6 +343,12 @@ void ChannelList::on_menu_copyid() {
m_signal_action_guild_copy_id.emit(row->ID); m_signal_action_guild_copy_id.emit(row->ID);
} }
void ChannelList::on_menu_leave() {
auto row = dynamic_cast<ChannelListRow *>(m_list->get_selected_row());
if (row != nullptr)
m_signal_action_guild_leave.emit(row->ID);
}
void ChannelList::AttachMenuHandler(Gtk::ListBoxRow *row) { void ChannelList::AttachMenuHandler(Gtk::ListBoxRow *row) {
row->signal_button_press_event().connect([&, row](GdkEventButton *e) -> bool { row->signal_button_press_event().connect([&, row](GdkEventButton *e) -> bool {
if (e->type == GDK_BUTTON_PRESS && e->button == GDK_BUTTON_SECONDARY) { if (e->type == GDK_BUTTON_PRESS && e->button == GDK_BUTTON_SECONDARY) {
@@ -371,3 +381,7 @@ ChannelList::type_signal_action_guild_move_down ChannelList::signal_action_guild
ChannelList::type_signal_action_guild_copy_id ChannelList::signal_action_guild_copy_id() { ChannelList::type_signal_action_guild_copy_id ChannelList::signal_action_guild_copy_id() {
return m_signal_action_guild_copy_id; return m_signal_action_guild_copy_id;
} }
ChannelList::type_signal_action_guild_leave ChannelList::signal_action_guild_leave() {
return m_signal_action_guild_leave;
}

View File

@@ -97,9 +97,11 @@ protected:
Gtk::MenuItem *m_guild_menu_up; Gtk::MenuItem *m_guild_menu_up;
Gtk::MenuItem *m_guild_menu_down; Gtk::MenuItem *m_guild_menu_down;
Gtk::MenuItem *m_guild_menu_copyid; Gtk::MenuItem *m_guild_menu_copyid;
Gtk::MenuItem *m_guild_menu_leave;
void on_menu_move_up(); void on_menu_move_up();
void on_menu_move_down(); void on_menu_move_down();
void on_menu_copyid(); void on_menu_copyid();
void on_menu_leave();
Glib::Dispatcher m_update_dispatcher; Glib::Dispatcher m_update_dispatcher;
//mutable std::mutex m_update_mutex; //mutable std::mutex m_update_mutex;
@@ -113,15 +115,18 @@ public:
typedef sigc::signal<void, Snowflake> type_signal_action_guild_move_up; typedef sigc::signal<void, Snowflake> type_signal_action_guild_move_up;
typedef sigc::signal<void, Snowflake> type_signal_action_guild_move_down; typedef sigc::signal<void, Snowflake> type_signal_action_guild_move_down;
typedef sigc::signal<void, Snowflake> type_signal_action_guild_copy_id; typedef sigc::signal<void, Snowflake> type_signal_action_guild_copy_id;
typedef sigc::signal<void, Snowflake> type_signal_action_guild_leave;
type_signal_action_channel_item_select signal_action_channel_item_select(); type_signal_action_channel_item_select signal_action_channel_item_select();
type_signal_action_guild_move_up signal_action_guild_move_up(); type_signal_action_guild_move_up signal_action_guild_move_up();
type_signal_action_guild_move_down signal_action_guild_move_down(); type_signal_action_guild_move_down signal_action_guild_move_down();
type_signal_action_guild_copy_id signal_action_guild_copy_id(); type_signal_action_guild_copy_id signal_action_guild_copy_id();
type_signal_action_guild_leave signal_action_guild_leave();
protected: protected:
type_signal_action_channel_item_select m_signal_action_channel_item_select; type_signal_action_channel_item_select m_signal_action_channel_item_select;
type_signal_action_guild_move_up m_signal_action_guild_move_up; type_signal_action_guild_move_up m_signal_action_guild_move_up;
type_signal_action_guild_move_down m_signal_action_guild_move_down; type_signal_action_guild_move_down m_signal_action_guild_move_down;
type_signal_action_guild_copy_id m_signal_action_guild_copy_id; type_signal_action_guild_copy_id m_signal_action_guild_copy_id;
type_signal_action_guild_leave m_signal_action_guild_leave;
}; };

98
dialogs/joinguild.cpp Normal file
View File

@@ -0,0 +1,98 @@
#include "joinguild.hpp"
#include "../abaddon.hpp"
#include <nlohmann/json.hpp>
#include <regex>
JoinGuildDialog::JoinGuildDialog(Gtk::Window &parent)
: Gtk::Dialog("Join Server", parent, true)
, m_layout(Gtk::ORIENTATION_VERTICAL)
, m_ok("OK")
, m_cancel("Cancel")
, m_info("Enter code") {
set_default_size(300, 50);
Glib::signal_idle().connect(sigc::mem_fun(*this, &JoinGuildDialog::on_idle_slot));
m_entry.signal_changed().connect(sigc::mem_fun(*this, &JoinGuildDialog::on_entry_changed));
m_ok.set_sensitive(false);
m_ok.signal_clicked().connect([&]() {
m_code = m_entry.get_text();
response(Gtk::RESPONSE_OK);
});
m_cancel.signal_clicked().connect([&]() {
response(Gtk::RESPONSE_CANCEL);
});
m_entry.set_hexpand(true);
m_layout.add(m_entry);
m_lower.set_hexpand(true);
m_lower.pack_start(m_info);
m_info.set_halign(Gtk::ALIGN_START);
m_lower.pack_start(m_ok, Gtk::PACK_SHRINK);
m_lower.pack_start(m_cancel, Gtk::PACK_SHRINK);
m_ok.set_halign(Gtk::ALIGN_END);
m_cancel.set_halign(Gtk::ALIGN_END);
m_layout.add(m_lower);
get_content_area()->add(m_layout);
show_all_children();
}
void JoinGuildDialog::on_entry_changed() {
std::string s = m_entry.get_text();
std::regex invite_regex(R"~(discord\.(gg|com)\/([a-zA-Z0-9]+)$)~", std::regex_constants::ECMAScript);
std::smatch match;
bool full_url = std::regex_search(s, match, invite_regex);
if (full_url || IsCode(s)) {
m_code = full_url ? match[2].str() : s;
m_needs_request = true;
m_ok.set_sensitive(false);
} else {
m_ok.set_sensitive(false);
}
}
void JoinGuildDialog::CheckCode() {
// clang-format off
Abaddon::Get().GetDiscordClient().FetchInviteData(
m_code,
[this](Invite invite) {
m_ok.set_sensitive(true);
if (invite.Members != -1)
m_info.set_text(invite.Guild.Name + " (" + std::to_string(invite.Members) + " members)");
else
m_info.set_text(invite.Guild.Name);
},
[this](bool not_found) {
m_ok.set_sensitive(false);
if (not_found)
m_info.set_text("Invalid invite");
else
m_info.set_text("HTTP error (try again)");
}
);
// clang-format on
}
bool JoinGuildDialog::IsCode(std::string str) {
return str.length() >= 2 && std::all_of(str.begin(), str.end(), [](char c) -> bool { return std::isalnum(c); });
}
std::string JoinGuildDialog::GetCode() {
return m_code;
}
static const constexpr int RateLimitMS = 1500;
bool JoinGuildDialog::on_idle_slot() {
const auto now = std::chrono::steady_clock::now();
if (m_needs_request && ((now - m_last_req_time) > std::chrono::milliseconds(RateLimitMS))) {
m_needs_request = false;
m_last_req_time = now;
CheckCode();
}
return true;
}

31
dialogs/joinguild.hpp Normal file
View File

@@ -0,0 +1,31 @@
#pragma once
#include <gtkmm.h>
#include <string>
#include <chrono>
class JoinGuildDialog : public Gtk::Dialog {
public:
JoinGuildDialog(Gtk::Window &parent);
std::string GetCode();
protected:
void on_entry_changed();
bool IsCode(std::string str);
Gtk::Box m_layout;
Gtk::Button m_ok;
Gtk::Button m_cancel;
Gtk::Box m_lower;
Gtk::Label m_info;
Gtk::Entry m_entry;
void CheckCode();
// needs a rate limit cuz if u hit it u get ip banned from /invites for a long time :(
bool m_needs_request = false;
std::chrono::time_point<std::chrono::steady_clock> m_last_req_time;
bool on_idle_slot();
private:
std::string m_code;
};

View File

@@ -108,6 +108,19 @@ std::set<Snowflake> DiscordClient::GetMessagesForChannel(Snowflake id) const {
return ret; return ret;
} }
void DiscordClient::FetchInviteData(std::string code, std::function<void(Invite)> cb, std::function<void(bool)> err) {
//printf("test: %s\n", code.c_str());
//err(true);
m_http.MakeGET("/invites/" + code + "?with_counts=true", [this, cb, err](cpr::Response r) {
if (!CheckCode(r)) {
err(r.status_code == 404);
return;
};
cb(nlohmann::json::parse(r.text));
});
}
void DiscordClient::UpdateSettingsGuildPositions(const std::vector<Snowflake> &pos) { void DiscordClient::UpdateSettingsGuildPositions(const std::vector<Snowflake> &pos) {
nlohmann::json body; nlohmann::json body;
body["guild_positions"] = pos; body["guild_positions"] = pos;
@@ -247,6 +260,14 @@ void DiscordClient::SendLazyLoad(Snowflake id) {
m_websocket.Send(j); m_websocket.Send(j);
} }
void DiscordClient::JoinGuild(std::string code) {
m_http.MakePOST("/invites/" + code, "", [](auto) {});
}
void DiscordClient::LeaveGuild(Snowflake id) {
m_http.MakeDELETE("/users/@me/guilds/" + std::to_string(id), [](auto) {});
}
void DiscordClient::UpdateToken(std::string token) { void DiscordClient::UpdateToken(std::string token) {
m_token = token; m_token = token;
m_http.SetAuth(token); m_http.SetAuth(token);
@@ -332,6 +353,12 @@ void DiscordClient::HandleGatewayMessage(std::string str) {
case GatewayEvent::GUILD_MEMBER_LIST_UPDATE: { case GatewayEvent::GUILD_MEMBER_LIST_UPDATE: {
HandleGatewayGuildMemberListUpdate(m); HandleGatewayGuildMemberListUpdate(m);
} break; } break;
case GatewayEvent::GUILD_CREATE: {
HandleGatewayGuildCreate(m);
} break;
case GatewayEvent::GUILD_DELETE: {
HandleGatewayGuildDelete(m);
} break;
} }
} break; } break;
default: default:
@@ -343,23 +370,27 @@ void DiscordClient::HandleGatewayMessage(std::string str) {
} }
} }
void DiscordClient::HandleGatewayReady(const GatewayMessage &msg) { void DiscordClient::ProcessNewGuild(Guild &guild) {
m_ready_received = true; if (guild.IsUnavailable) {
ReadyEventData data = msg.Data; printf("guild (%lld) unavailable\n", static_cast<uint64_t>(guild.ID));
for (auto &g : data.Guilds) { return;
if (g.IsUnavailable) }
printf("guild (%lld) unavailable\n", (uint64_t)g.ID);
else { m_store.SetGuild(guild.ID, guild);
m_store.SetGuild(g.ID, g); for (auto &c : guild.Channels) {
for (auto &c : g.Channels) { c.GuildID = guild.ID;
c.GuildID = g.ID;
m_store.SetChannel(c.ID, c); m_store.SetChannel(c.ID, c);
} }
for (auto &r : g.Roles) for (auto &r : guild.Roles)
m_store.SetRole(r.ID, r); m_store.SetRole(r.ID, r);
} }
}
void DiscordClient::HandleGatewayReady(const GatewayMessage &msg) {
m_ready_received = true;
ReadyEventData data = msg.Data;
for (auto &g : data.Guilds)
ProcessNewGuild(g);
for (const auto &dm : data.PrivateChannels) { for (const auto &dm : data.PrivateChannels) {
m_store.SetChannel(dm.ID, dm); m_store.SetChannel(dm.ID, dm);
@@ -419,6 +450,34 @@ void DiscordClient::HandleGatewayGuildMemberListUpdate(const GatewayMessage &msg
m_signal_guild_member_list_update.emit(data.GuildID); m_signal_guild_member_list_update.emit(data.GuildID);
} }
void DiscordClient::HandleGatewayGuildCreate(const GatewayMessage &msg) {
Guild data = msg.Data;
ProcessNewGuild(data);
m_signal_guild_create.emit(data.ID);
}
void DiscordClient::HandleGatewayGuildDelete(const GatewayMessage &msg) {
Snowflake id = msg.Data.at("id");
bool unavailable = msg.Data.contains("unavilable") && msg.Data.at("unavailable").get<bool>();
if (unavailable)
printf("guild %llu became unavailable\n", static_cast<uint64_t>(id));
auto *guild = m_store.GetGuild(id);
if (guild == nullptr) {
m_store.ClearGuild(id);
m_signal_guild_delete.emit(id);
return;
}
m_store.ClearGuild(id);
for (const auto &c : guild->Channels)
m_store.ClearChannel(c.ID);
m_signal_guild_delete.emit(id);
}
void DiscordClient::AddMessageToChannel(Snowflake msg_id, Snowflake channel_id) { void DiscordClient::AddMessageToChannel(Snowflake msg_id, Snowflake channel_id) {
m_chan_to_message_map[channel_id].insert(msg_id); m_chan_to_message_map[channel_id].insert(msg_id);
} }
@@ -480,6 +539,8 @@ void DiscordClient::LoadEventMap() {
m_event_map["MESSAGE_DELETE"] = GatewayEvent::MESSAGE_DELETE; m_event_map["MESSAGE_DELETE"] = GatewayEvent::MESSAGE_DELETE;
m_event_map["MESSAGE_UPDATE"] = GatewayEvent::MESSAGE_UPDATE; m_event_map["MESSAGE_UPDATE"] = GatewayEvent::MESSAGE_UPDATE;
m_event_map["GUILD_MEMBER_LIST_UPDATE"] = GatewayEvent::GUILD_MEMBER_LIST_UPDATE; m_event_map["GUILD_MEMBER_LIST_UPDATE"] = GatewayEvent::GUILD_MEMBER_LIST_UPDATE;
m_event_map["GUILD_CREATE"] = GatewayEvent::GUILD_CREATE;
m_event_map["GUILD_DELETE"] = GatewayEvent::GUILD_DELETE;
} }
DiscordClient::type_signal_gateway_ready DiscordClient::signal_gateway_ready() { DiscordClient::type_signal_gateway_ready DiscordClient::signal_gateway_ready() {
@@ -505,3 +566,11 @@ DiscordClient::type_signal_message_update DiscordClient::signal_message_update()
DiscordClient::type_signal_guild_member_list_update DiscordClient::signal_guild_member_list_update() { DiscordClient::type_signal_guild_member_list_update DiscordClient::signal_guild_member_list_update() {
return m_signal_guild_member_list_update; return m_signal_guild_member_list_update;
} }
DiscordClient::type_signal_guild_create DiscordClient::signal_guild_create() {
return m_signal_guild_create;
}
DiscordClient::type_signal_guild_delete DiscordClient::signal_guild_delete() {
return m_signal_guild_delete;
}

View File

@@ -68,6 +68,7 @@ public:
std::set<Snowflake> GetMessagesForChannel(Snowflake id) const; std::set<Snowflake> GetMessagesForChannel(Snowflake id) const;
std::set<Snowflake> GetPrivateChannels() const; std::set<Snowflake> GetPrivateChannels() const;
void FetchInviteData(std::string code, std::function<void(Invite)> cb, std::function<void(bool)> err);
void UpdateSettingsGuildPositions(const std::vector<Snowflake> &pos); void UpdateSettingsGuildPositions(const std::vector<Snowflake> &pos);
void FetchMessagesInChannel(Snowflake id, std::function<void(const std::vector<Snowflake> &)> cb); 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); void FetchMessagesInChannelBefore(Snowflake channel_id, Snowflake before_id, std::function<void(const std::vector<Snowflake> &)> cb);
@@ -83,6 +84,8 @@ public:
void DeleteMessage(Snowflake channel_id, Snowflake id); void DeleteMessage(Snowflake channel_id, Snowflake id);
void EditMessage(Snowflake channel_id, Snowflake id, std::string content); void EditMessage(Snowflake channel_id, Snowflake id, std::string content);
void SendLazyLoad(Snowflake id); void SendLazyLoad(Snowflake id);
void JoinGuild(std::string code);
void LeaveGuild(Snowflake id);
void UpdateToken(std::string token); void UpdateToken(std::string token);
@@ -91,6 +94,9 @@ private:
std::vector<uint8_t> m_compressed_buf; std::vector<uint8_t> m_compressed_buf;
std::vector<uint8_t> m_decompress_buf; std::vector<uint8_t> m_decompress_buf;
z_stream m_zstream; z_stream m_zstream;
void ProcessNewGuild(Guild &guild);
void HandleGatewayMessageRaw(std::string str); void HandleGatewayMessageRaw(std::string str);
void HandleGatewayMessage(std::string str); void HandleGatewayMessage(std::string str);
void HandleGatewayReady(const GatewayMessage &msg); void HandleGatewayReady(const GatewayMessage &msg);
@@ -98,6 +104,8 @@ private:
void HandleGatewayMessageDelete(const GatewayMessage &msg); void HandleGatewayMessageDelete(const GatewayMessage &msg);
void HandleGatewayMessageUpdate(const GatewayMessage &msg); void HandleGatewayMessageUpdate(const GatewayMessage &msg);
void HandleGatewayGuildMemberListUpdate(const GatewayMessage &msg); void HandleGatewayGuildMemberListUpdate(const GatewayMessage &msg);
void HandleGatewayGuildCreate(const GatewayMessage &msg);
void HandleGatewayGuildDelete(const GatewayMessage &msg);
void HeartbeatThread(); void HeartbeatThread();
void SendIdentify(); void SendIdentify();
@@ -137,6 +145,8 @@ public:
typedef sigc::signal<void, Snowflake, Snowflake> type_signal_message_delete; typedef sigc::signal<void, Snowflake, Snowflake> type_signal_message_delete;
typedef sigc::signal<void, Snowflake, Snowflake> type_signal_message_update; typedef sigc::signal<void, Snowflake, Snowflake> type_signal_message_update;
typedef sigc::signal<void, Snowflake> type_signal_guild_member_list_update; typedef sigc::signal<void, Snowflake> type_signal_guild_member_list_update;
typedef sigc::signal<void, Snowflake> type_signal_guild_create;
typedef sigc::signal<void, Snowflake> type_signal_guild_delete;
type_signal_gateway_ready signal_gateway_ready(); type_signal_gateway_ready signal_gateway_ready();
type_signal_channel_list_refresh signal_channel_list_refresh(); type_signal_channel_list_refresh signal_channel_list_refresh();
@@ -144,6 +154,8 @@ public:
type_signal_message_delete signal_message_delete(); type_signal_message_delete signal_message_delete();
type_signal_message_update signal_message_update(); type_signal_message_update signal_message_update();
type_signal_guild_member_list_update signal_guild_member_list_update(); type_signal_guild_member_list_update signal_guild_member_list_update();
type_signal_guild_create signal_guild_create();
type_signal_guild_delete signal_guild_delete();
protected: protected:
type_signal_gateway_ready m_signal_gateway_ready; type_signal_gateway_ready m_signal_gateway_ready;
@@ -152,4 +164,6 @@ protected:
type_signal_message_delete m_signal_message_delete; type_signal_message_delete m_signal_message_delete;
type_signal_message_update m_signal_message_update; type_signal_message_update m_signal_message_update;
type_signal_guild_member_list_update m_signal_guild_member_list_update; type_signal_guild_member_list_update m_signal_guild_member_list_update;
type_signal_guild_create m_signal_guild_create;
type_signal_guild_delete m_signal_guild_delete;
}; };

View File

@@ -1,5 +1,6 @@
#include "http.hpp" #include "http.hpp"
//#define USE_LOCAL_PROXY
HTTPClient::HTTPClient(std::string api_base) HTTPClient::HTTPClient(std::string api_base)
: m_api_base(api_base) {} : m_api_base(api_base) {}

14
discord/invite.cpp Normal file
View File

@@ -0,0 +1,14 @@
#include "invite.hpp"
void from_json(const nlohmann::json &j, Invite &m) {
JS_D("code", m.Code);
JS_O("channel", m.Channel);
JS_O("inviter", m.Inviter);
JS_O("approximate_member_count", m.Members);
if (j.contains("guild")) {
auto x = j.at("guild");
x.at("id").get_to(m.Guild.ID);
x.at("name").get_to(m.Guild.Name);
}
}

15
discord/invite.hpp Normal file
View File

@@ -0,0 +1,15 @@
#pragma once
#include "json.hpp"
#include "guild.hpp"
#include <string>
class Invite {
public:
std::string Code; //
Guild Guild; // opt
Channel Channel; // opt
User Inviter; // opt
int Members = -1; // opt
friend void from_json(const nlohmann::json &j, Invite &m);
};

View File

@@ -11,6 +11,7 @@
#include "guild.hpp" #include "guild.hpp"
#include "usersettings.hpp" #include "usersettings.hpp"
#include "message.hpp" #include "message.hpp"
#include "invite.hpp"
// most stuff below should just be objects that get processed and thrown away immediately // most stuff below should just be objects that get processed and thrown away immediately
@@ -29,6 +30,8 @@ enum class GatewayEvent : int {
MESSAGE_DELETE, MESSAGE_DELETE,
MESSAGE_UPDATE, MESSAGE_UPDATE,
GUILD_MEMBER_LIST_UPDATE, GUILD_MEMBER_LIST_UPDATE,
GUILD_CREATE,
GUILD_DELETE,
}; };
struct GatewayMessage { struct GatewayMessage {

View File

@@ -114,6 +114,14 @@ const GuildMember *Store::GetGuildMemberData(Snowflake guild_id, Snowflake user_
return &mit->second; return &mit->second;
} }
void Store::ClearGuild(Snowflake id) {
m_guilds.erase(id);
}
void Store::ClearChannel(Snowflake id) {
m_channels.erase(id);
}
const Store::channels_type &Store::GetChannels() const { const Store::channels_type &Store::GetChannels() const {
return m_channels; return m_channels;
} }

View File

@@ -29,6 +29,9 @@ public:
const Message *GetMessage(Snowflake id) const; const Message *GetMessage(Snowflake id) const;
const GuildMember *GetGuildMemberData(Snowflake guild_id, Snowflake user_id) const; const GuildMember *GetGuildMemberData(Snowflake guild_id, Snowflake user_id) const;
void ClearGuild(Snowflake id);
void ClearChannel(Snowflake id);
using users_type = std::unordered_map<Snowflake, User>; using users_type = std::unordered_map<Snowflake, User>;
using channels_type = std::unordered_map<Snowflake, Channel>; using channels_type = std::unordered_map<Snowflake, Channel>;
using guilds_type = std::unordered_map<Snowflake, Guild>; using guilds_type = std::unordered_map<Snowflake, Guild>;

View File

@@ -15,9 +15,12 @@ MainWindow::MainWindow()
m_menu_discord_disconnect.set_label("Disconnect"); m_menu_discord_disconnect.set_label("Disconnect");
m_menu_discord_disconnect.set_sensitive(false); m_menu_discord_disconnect.set_sensitive(false);
m_menu_discord_set_token.set_label("Set Token"); m_menu_discord_set_token.set_label("Set Token");
m_menu_discord_join_guild.set_label("Join Guild");
m_menu_discord_join_guild.set_sensitive(false);
m_menu_discord_sub.append(m_menu_discord_connect); m_menu_discord_sub.append(m_menu_discord_connect);
m_menu_discord_sub.append(m_menu_discord_disconnect); m_menu_discord_sub.append(m_menu_discord_disconnect);
m_menu_discord_sub.append(m_menu_discord_set_token); m_menu_discord_sub.append(m_menu_discord_set_token);
m_menu_discord_sub.append(m_menu_discord_join_guild);
m_menu_discord.set_submenu(m_menu_discord_sub); m_menu_discord.set_submenu(m_menu_discord_sub);
m_menu_file.set_label("File"); m_menu_file.set_label("File");
@@ -40,6 +43,10 @@ MainWindow::MainWindow()
m_signal_action_set_token.emit(); m_signal_action_set_token.emit();
}); });
m_menu_discord_join_guild.signal_activate().connect([&] {
m_signal_action_join_guild.emit();
});
m_menu_file_reload_css.signal_activate().connect([this] { m_menu_file_reload_css.signal_activate().connect([this] {
m_signal_action_reload_css.emit(); m_signal_action_reload_css.emit();
}); });
@@ -87,8 +94,8 @@ void MainWindow::UpdateComponents() {
std::string token = Abaddon::Get().GetDiscordToken(); std::string token = Abaddon::Get().GetDiscordToken();
m_menu_discord_connect.set_sensitive(token.size() > 0 && !discord_active); m_menu_discord_connect.set_sensitive(token.size() > 0 && !discord_active);
m_menu_discord_disconnect.set_sensitive(discord_active); m_menu_discord_disconnect.set_sensitive(discord_active);
m_menu_discord_join_guild.set_sensitive(discord_active);
if (!discord_active) { if (!discord_active) {
m_channel_list.Clear(); m_channel_list.Clear();
@@ -191,3 +198,7 @@ MainWindow::type_signal_action_set_token MainWindow::signal_action_set_token() {
MainWindow::type_signal_action_reload_css MainWindow::signal_action_reload_css() { MainWindow::type_signal_action_reload_css MainWindow::signal_action_reload_css() {
return m_signal_action_reload_css; return m_signal_action_reload_css;
} }
MainWindow::type_signal_action_join_guild MainWindow::signal_action_join_guild() {
return m_signal_action_join_guild;
}

View File

@@ -30,17 +30,20 @@ public:
typedef sigc::signal<void> type_signal_action_disconnect; typedef sigc::signal<void> type_signal_action_disconnect;
typedef sigc::signal<void> type_signal_action_set_token; typedef sigc::signal<void> type_signal_action_set_token;
typedef sigc::signal<void> type_signal_action_reload_css; typedef sigc::signal<void> type_signal_action_reload_css;
typedef sigc::signal<void> type_signal_action_join_guild;
type_signal_action_connect signal_action_connect(); type_signal_action_connect signal_action_connect();
type_signal_action_disconnect signal_action_disconnect(); type_signal_action_disconnect signal_action_disconnect();
type_signal_action_set_token signal_action_set_token(); type_signal_action_set_token signal_action_set_token();
type_signal_action_reload_css signal_action_reload_css(); type_signal_action_reload_css signal_action_reload_css();
type_signal_action_join_guild signal_action_join_guild();
protected: protected:
type_signal_action_connect m_signal_action_connect; type_signal_action_connect m_signal_action_connect;
type_signal_action_disconnect m_signal_action_disconnect; type_signal_action_disconnect m_signal_action_disconnect;
type_signal_action_set_token m_signal_action_set_token; type_signal_action_set_token m_signal_action_set_token;
type_signal_action_reload_css m_signal_action_reload_css; type_signal_action_reload_css m_signal_action_reload_css;
type_signal_action_join_guild m_signal_action_join_guild;
protected: protected:
Gtk::Box m_main_box; Gtk::Box m_main_box;
@@ -58,6 +61,7 @@ protected:
Gtk::MenuItem m_menu_discord_connect; Gtk::MenuItem m_menu_discord_connect;
Gtk::MenuItem m_menu_discord_disconnect; Gtk::MenuItem m_menu_discord_disconnect;
Gtk::MenuItem m_menu_discord_set_token; Gtk::MenuItem m_menu_discord_set_token;
Gtk::MenuItem m_menu_discord_join_guild;
Gtk::MenuItem m_menu_file; Gtk::MenuItem m_menu_file;
Gtk::Menu m_menu_file_sub; Gtk::Menu m_menu_file_sub;