mirror of
https://github.com/uowuo/abaddon.git
synced 2024-11-10 06:00:10 +00:00
connect and heartbeat
This commit is contained in:
parent
212511e29d
commit
18af78e6af
64
.clang-format
Normal file
64
.clang-format
Normal file
@ -0,0 +1,64 @@
|
||||
---
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveDeclarations: 'false'
|
||||
AlignOperands: 'true'
|
||||
AlignTrailingComments: 'true'
|
||||
AllowAllArgumentsOnNextLine: 'false'
|
||||
AllowAllConstructorInitializersOnNextLine: 'false'
|
||||
AllowAllParametersOfDeclarationOnNextLine: 'false'
|
||||
AllowShortBlocksOnASingleLine: 'true'
|
||||
AllowShortCaseLabelsOnASingleLine: 'true'
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortIfStatementsOnASingleLine: Always
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: 'true'
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: 'false'
|
||||
AlwaysBreakTemplateDeclarations: 'Yes'
|
||||
BinPackArguments: 'true'
|
||||
BinPackParameters: 'true'
|
||||
BreakAfterJavaFieldAnnotations: 'true'
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeTernaryOperators: 'true'
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakInheritanceList: BeforeComma
|
||||
BreakStringLiterals: 'true'
|
||||
ColumnLimit: '0'
|
||||
CompactNamespaces: 'false'
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: 'false'
|
||||
ContinuationIndentWidth: '4'
|
||||
Cpp11BracedListStyle: 'false'
|
||||
DerivePointerAlignment: 'false'
|
||||
FixNamespaceComments: 'true'
|
||||
IncludeBlocks: Merge
|
||||
IndentCaseLabels: 'true'
|
||||
IndentPPDirectives: BeforeHash
|
||||
IndentWidth: '4'
|
||||
IndentWrappedFunctionNames: 'false'
|
||||
JavaScriptQuotes: Double
|
||||
KeepEmptyLinesAtTheStartOfBlocks: 'false'
|
||||
Language: Cpp
|
||||
NamespaceIndentation: Inner
|
||||
PointerAlignment: Right
|
||||
SortIncludes: 'false'
|
||||
SpaceAfterCStyleCast: 'false'
|
||||
SpaceAfterLogicalNot: 'false'
|
||||
SpaceAfterTemplateKeyword: 'false'
|
||||
SpaceBeforeAssignmentOperators: 'true'
|
||||
SpaceBeforeCpp11BracedList: 'true'
|
||||
SpaceBeforeCtorInitializerColon: 'true'
|
||||
SpaceBeforeInheritanceColon: 'true'
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: 'true'
|
||||
SpaceInEmptyParentheses: 'false'
|
||||
SpacesInAngles: 'false'
|
||||
SpacesInCStyleCastParentheses: 'false'
|
||||
SpacesInParentheses: 'false'
|
||||
SpacesInSquareBrackets: 'false'
|
||||
Standard: Auto
|
||||
TabWidth: '4'
|
||||
|
||||
...
|
31
Abaddon.sln
Normal file
31
Abaddon.sln
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30204.135
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Abaddon", "Abaddon.vcxproj", "{A2A67504-F7F1-4DD3-B86B-68033416FFF5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A2A67504-F7F1-4DD3-B86B-68033416FFF5}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A2A67504-F7F1-4DD3-B86B-68033416FFF5}.Debug|x64.Build.0 = Debug|x64
|
||||
{A2A67504-F7F1-4DD3-B86B-68033416FFF5}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{A2A67504-F7F1-4DD3-B86B-68033416FFF5}.Debug|x86.Build.0 = Debug|Win32
|
||||
{A2A67504-F7F1-4DD3-B86B-68033416FFF5}.Release|x64.ActiveCfg = Release|x64
|
||||
{A2A67504-F7F1-4DD3-B86B-68033416FFF5}.Release|x64.Build.0 = Release|x64
|
||||
{A2A67504-F7F1-4DD3-B86B-68033416FFF5}.Release|x86.ActiveCfg = Release|Win32
|
||||
{A2A67504-F7F1-4DD3-B86B-68033416FFF5}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {CA30A7C6-E05A-4D4C-BC71-1D4C80E5647E}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
160
Abaddon.vcxproj
Normal file
160
Abaddon.vcxproj
Normal file
@ -0,0 +1,160 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{a2a67504-f7f1-4dd3-b86b-68033416fff5}</ProjectGuid>
|
||||
<RootNamespace>Abaddon</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="abaddon.cpp" />
|
||||
<ClCompile Include="components\channels.cpp" />
|
||||
<ClCompile Include="discord\discord.cpp" />
|
||||
<ClCompile Include="discord\websocket.cpp" />
|
||||
<ClCompile Include="windows\mainwindow.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="components\channels.hpp" />
|
||||
<ClInclude Include="abaddon.hpp" />
|
||||
<ClInclude Include="discord\discord.hpp" />
|
||||
<ClInclude Include="discord\websocket.hpp" />
|
||||
<ClInclude Include="windows\mainwindow.hpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
51
Abaddon.vcxproj.filters
Normal file
51
Abaddon.vcxproj.filters
Normal file
@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="abaddon.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="windows\mainwindow.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="components\channels.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="discord\websocket.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="discord\discord.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="windows\mainwindow.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="components\channels.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="discord\discord.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="discord\websocket.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="abaddon.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
44
abaddon.cpp
Normal file
44
abaddon.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include <gtkmm.h>
|
||||
#include "discord/discord.hpp"
|
||||
#include "windows/mainwindow.hpp"
|
||||
#include <memory>
|
||||
#include "abaddon.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma comment(lib, "crypt32.lib")
|
||||
#endif
|
||||
|
||||
int Abaddon::DoMainLoop() {
|
||||
m_gtk_app = Gtk::Application::create("com.github.lorpus.abaddon");
|
||||
|
||||
MainWindow main;
|
||||
main.SetAbaddon(this);
|
||||
main.set_title("Abaddon");
|
||||
main.show();
|
||||
|
||||
m_gtk_app->signal_shutdown().connect([&]() {
|
||||
m_discord.Stop();
|
||||
});
|
||||
|
||||
/*sigc::connection draw_signal_handler = main.signal_draw().connect([&](const Cairo::RefPtr<Cairo::Context> &ctx) -> bool {
|
||||
draw_signal_handler.disconnect();
|
||||
|
||||
return false;
|
||||
});*/
|
||||
|
||||
return m_gtk_app->run(main);
|
||||
}
|
||||
|
||||
void Abaddon::StartDiscordThread() {
|
||||
m_discord.Start();
|
||||
}
|
||||
|
||||
void Abaddon::ActionConnect() {
|
||||
if (!m_discord.IsStarted())
|
||||
StartDiscordThread();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
Abaddon abaddon;
|
||||
return abaddon.DoMainLoop();
|
||||
}
|
14
abaddon.hpp
Normal file
14
abaddon.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include <gtkmm.h>
|
||||
#include "discord/discord.hpp"
|
||||
|
||||
class Abaddon {
|
||||
public:
|
||||
int DoMainLoop();
|
||||
void StartDiscordThread();
|
||||
|
||||
void ActionConnect();
|
||||
|
||||
private:
|
||||
Glib::RefPtr<Gtk::Application> m_gtk_app;
|
||||
DiscordClient m_discord;
|
||||
};
|
12
components/channels.cpp
Normal file
12
components/channels.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
#include "channels.hpp"
|
||||
|
||||
ChannelList::ChannelList() {
|
||||
m_main = Gtk::manage(new Gtk::ScrolledWindow);
|
||||
m_list = Gtk::manage(new Gtk::ListBox);
|
||||
|
||||
m_main->add(*m_list);
|
||||
}
|
||||
|
||||
Gtk::Widget* ChannelList::GetRoot() const {
|
||||
return m_main;
|
||||
}
|
12
components/channels.hpp
Normal file
12
components/channels.hpp
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include <gtkmm.h>
|
||||
|
||||
class ChannelList {
|
||||
public:
|
||||
ChannelList();
|
||||
Gtk::Widget *GetRoot() const;
|
||||
|
||||
protected:
|
||||
Gtk::ListBox *m_list;
|
||||
Gtk::ScrolledWindow *m_main;
|
||||
};
|
85
discord/discord.cpp
Normal file
85
discord/discord.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
#include "discord.hpp"
|
||||
|
||||
DiscordClient::DiscordClient() {}
|
||||
|
||||
void DiscordClient::Start() {
|
||||
if (m_client_connected)
|
||||
throw std::runtime_error("attempt to start client twice consecutively");
|
||||
|
||||
m_client_connected = true;
|
||||
m_websocket.StartConnection(DiscordGateway);
|
||||
m_websocket.SetJSONCallback(std::bind(&DiscordClient::HandleGatewayMessage, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
void DiscordClient::Stop() {
|
||||
if (!m_client_connected) return;
|
||||
m_heartbeat_waiter.kill();
|
||||
m_heartbeat_thread.join();
|
||||
m_client_connected = false;
|
||||
}
|
||||
|
||||
bool DiscordClient::IsStarted() const {
|
||||
return m_client_connected;
|
||||
}
|
||||
|
||||
void DiscordClient::HandleGatewayMessage(nlohmann::json j) {
|
||||
GatewayMessage m;
|
||||
try {
|
||||
m = j;
|
||||
} catch (std::exception &e) {
|
||||
printf("Error decoding JSON. Discarding message: %s\n", e.what());
|
||||
return;
|
||||
}
|
||||
|
||||
switch (m.Opcode) {
|
||||
case GatewayOp::Hello: {
|
||||
HelloMessageData d = m.Data;
|
||||
m_heartbeat_msec = d.HeartbeatInterval;
|
||||
m_heartbeat_thread = std::thread(std::bind(&DiscordClient::HeartbeatThread, this));
|
||||
} break;
|
||||
case GatewayOp::HeartbeatAck: {
|
||||
m_heartbeat_acked = true;
|
||||
} break;
|
||||
default:
|
||||
printf("Unknown opcode %d\n", m.Opcode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DiscordClient::HeartbeatThread() {
|
||||
while (m_client_connected) {
|
||||
if (!m_heartbeat_acked) {
|
||||
printf("wow! a heartbeat wasn't acked! how could this happen?");
|
||||
}
|
||||
|
||||
m_heartbeat_acked = false;
|
||||
|
||||
HeartbeatMessage msg;
|
||||
msg.Sequence = m_last_sequence;
|
||||
nlohmann::json j = msg;
|
||||
m_websocket.Send(j.dump());
|
||||
|
||||
if (!m_heartbeat_waiter.wait_for(std::chrono::milliseconds(m_heartbeat_msec)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json &j, GatewayMessage &m) {
|
||||
j.at("op").get_to(m.Opcode);
|
||||
m.Data = j.at("d");
|
||||
|
||||
if (j.contains("t") && !j.at("t").is_null())
|
||||
j.at("t").get_to(m.Type);
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json &j, HelloMessageData &m) {
|
||||
j.at("heartbeat_interval").get_to(m.HeartbeatInterval);
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const HeartbeatMessage &m) {
|
||||
j["op"] = GatewayOp::Heartbeat;
|
||||
if (m.Sequence == -1)
|
||||
j["d"] = nullptr;
|
||||
else
|
||||
j["d"] = m.Sequence;
|
||||
}
|
75
discord/discord.hpp
Normal file
75
discord/discord.hpp
Normal file
@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
#include "websocket.hpp"
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <thread>
|
||||
|
||||
enum class GatewayOp : int {
|
||||
Heartbeat = 1,
|
||||
Hello = 10,
|
||||
HeartbeatAck = 11,
|
||||
};
|
||||
|
||||
struct GatewayMessage {
|
||||
GatewayOp Opcode;
|
||||
nlohmann::json Data;
|
||||
std::string Type;
|
||||
|
||||
friend void from_json(const nlohmann::json &j, GatewayMessage &m);
|
||||
};
|
||||
|
||||
struct HelloMessageData {
|
||||
int HeartbeatInterval;
|
||||
|
||||
friend void from_json(const nlohmann::json &j, HelloMessageData &m);
|
||||
};
|
||||
|
||||
struct HeartbeatMessage : GatewayMessage {
|
||||
int Sequence;
|
||||
|
||||
friend void to_json(nlohmann::json &j, const HeartbeatMessage &m);
|
||||
};
|
||||
|
||||
// https://stackoverflow.com/questions/29775153/stopping-long-sleep-threads/29775639#29775639
|
||||
class HeartbeatWaiter {
|
||||
public:
|
||||
template<class R, class P>
|
||||
bool wait_for(std::chrono::duration<R, P> const &time) const {
|
||||
std::unique_lock<std::mutex> lock(m);
|
||||
return !cv.wait_for(lock, time, [&] { return terminate; });
|
||||
}
|
||||
void kill() {
|
||||
std::unique_lock<std::mutex> lock(m);
|
||||
terminate = true;
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::condition_variable cv;
|
||||
mutable std::mutex m;
|
||||
bool terminate = false;
|
||||
};
|
||||
|
||||
class DiscordClient {
|
||||
public:
|
||||
static const constexpr char *DiscordGateway = "wss://gateway.discord.gg/?v=6&encoding=json";
|
||||
static const constexpr char *DiscordAPI = "https://discord.com/api";
|
||||
|
||||
public:
|
||||
DiscordClient();
|
||||
void Start();
|
||||
void Stop();
|
||||
bool IsStarted() const;
|
||||
|
||||
private:
|
||||
void HandleGatewayMessage(nlohmann::json msg);
|
||||
void HeartbeatThread();
|
||||
|
||||
Websocket m_websocket;
|
||||
bool m_client_connected = false;
|
||||
|
||||
std::thread m_heartbeat_thread;
|
||||
int m_last_sequence = -1;
|
||||
int m_heartbeat_msec = 0;
|
||||
HeartbeatWaiter m_heartbeat_waiter;
|
||||
bool m_heartbeat_acked = true;
|
||||
};
|
30
discord/websocket.cpp
Normal file
30
discord/websocket.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include "websocket.hpp"
|
||||
#include <functional>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
Websocket::Websocket() {}
|
||||
|
||||
void Websocket::StartConnection(std::string url) {
|
||||
m_websocket.setUrl(url);
|
||||
m_websocket.setOnMessageCallback(std::bind(&Websocket::OnMessage, this, std::placeholders::_1));
|
||||
m_websocket.start();
|
||||
}
|
||||
|
||||
void Websocket::SetJSONCallback(JSONCallback_t func) {
|
||||
m_json_callback = func;
|
||||
}
|
||||
|
||||
void Websocket::Send(const std::string &str) {
|
||||
m_websocket.sendText(str);
|
||||
}
|
||||
|
||||
void Websocket::OnMessage(const ix::WebSocketMessagePtr &msg) {
|
||||
switch (msg->type) {
|
||||
case ix::WebSocketMessageType::Message:
|
||||
printf("%s\n", msg->str.c_str());
|
||||
auto obj = nlohmann::json::parse(msg->str);
|
||||
if (m_json_callback)
|
||||
m_json_callback(obj);
|
||||
break;
|
||||
}
|
||||
}
|
22
discord/websocket.hpp
Normal file
22
discord/websocket.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include <ixwebsocket/IXNetSystem.h>
|
||||
#include <ixwebsocket/IXWebSocket.h>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
class Websocket {
|
||||
public:
|
||||
Websocket();
|
||||
void StartConnection(std::string url);
|
||||
|
||||
using JSONCallback_t = std::function<void(nlohmann::json)>;
|
||||
void SetJSONCallback(JSONCallback_t func);
|
||||
void Send(const std::string &str);
|
||||
|
||||
private:
|
||||
void OnMessage(const ix::WebSocketMessagePtr &msg);
|
||||
|
||||
JSONCallback_t m_json_callback;
|
||||
ix::WebSocket m_websocket;
|
||||
};
|
31
windows/mainwindow.cpp
Normal file
31
windows/mainwindow.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
#include "mainwindow.hpp"
|
||||
#include "../abaddon.hpp"
|
||||
|
||||
MainWindow::MainWindow()
|
||||
: m_main_box(Gtk::ORIENTATION_VERTICAL) {
|
||||
set_default_size(800, 600);
|
||||
|
||||
m_menu_discord.set_label("Discord");
|
||||
m_menu_discord.set_submenu(m_menu_discord_sub);
|
||||
m_menu_discord_connect.set_label("Connect");
|
||||
m_menu_discord_sub.append(m_menu_discord_connect);
|
||||
m_menu_discord.set_submenu(m_menu_discord_sub);
|
||||
m_menu_bar.append(m_menu_discord);
|
||||
|
||||
m_menu_discord_connect.signal_activate().connect([&] {
|
||||
m_abaddon->ActionConnect(); // this feels maybe not too smart
|
||||
});
|
||||
|
||||
m_main_box.add(m_menu_bar);
|
||||
|
||||
auto *channel_list = m_channel_list.GetRoot();
|
||||
m_main_box.add(*channel_list);
|
||||
|
||||
add(m_main_box);
|
||||
|
||||
show_all_children();
|
||||
}
|
||||
|
||||
void MainWindow::SetAbaddon(Abaddon* ptr) {
|
||||
m_abaddon = ptr;
|
||||
}
|
22
windows/mainwindow.hpp
Normal file
22
windows/mainwindow.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "../components/channels.hpp"
|
||||
#include <gtkmm.h>
|
||||
|
||||
class Abaddon;
|
||||
class MainWindow : public Gtk::Window {
|
||||
public:
|
||||
MainWindow();
|
||||
void SetAbaddon(Abaddon *ptr);
|
||||
|
||||
protected:
|
||||
Gtk::Box m_main_box;
|
||||
|
||||
ChannelList m_channel_list;
|
||||
|
||||
Gtk::MenuBar m_menu_bar;
|
||||
Gtk::MenuItem m_menu_discord;
|
||||
Gtk::Menu m_menu_discord_sub;
|
||||
Gtk::MenuItem m_menu_discord_connect;
|
||||
|
||||
Abaddon *m_abaddon = nullptr;
|
||||
};
|
Loading…
Reference in New Issue
Block a user