Clang-format; Correctly add command discordrpc-reconnect; Check for doLanguageIcons config option

This commit is contained in:
Bytequill
2025-02-11 22:20:43 +01:00
parent fadb3b9879
commit 08e92db506
6 changed files with 551 additions and 527 deletions

View File

@@ -160,6 +160,8 @@ File path is: </string>
<string name="cut">Cut</string> <string name="cut">Cut</string>
<string name="dark">Dark</string> <string name="dark">Dark</string>
<string name="date">Date</string> <string name="date">Date</string>
<string name="dc_editing">Editing %s, a %s file</string>
<string name="dc_workspace">Working on %s</string>
<string name="debug_draw_boxes">Draw Boxes</string> <string name="debug_draw_boxes">Draw Boxes</string>
<string name="debug_draw_boxes_toggle">Debug Draw Boxes Toggle</string> <string name="debug_draw_boxes_toggle">Debug Draw Boxes Toggle</string>
<string name="debug_draw_debug_data">Debug Draw Debug Data</string> <string name="debug_draw_debug_data">Debug Draw Debug Data</string>

View File

@@ -1,112 +1,110 @@
{ {
"config" : { "config": {
"appID": "1335730393948749898", "appID": "1335730393948749898",
"doLanguageIcons": true, "doLanguageIcons": true,
"iconBindings": { "iconBindings": {
".htaccess": "https://github.com/vyfor/icons/raw/master/icons/onyx/gear.png", ".htaccess": "https://github.com/vyfor/icons/raw/master/icons/onyx/gear.png",
".ignore file": "https://github.com/vyfor/icons/raw/master/icons/onyx/git.png", ".ignore file": "https://github.com/vyfor/icons/raw/master/icons/onyx/git.png",
"[x]it!": "https://github.com/vyfor/icons/raw/master/icons/onyx/notes.png", "[x]it!": "https://github.com/vyfor/icons/raw/master/icons/onyx/notes.png",
"ada": "https://github.com/vyfor/icons/raw/master/icons/pastel/ada.png", "ada": "https://github.com/vyfor/icons/raw/master/icons/pastel/ada.png",
"adept": "https://raw.github.com/AdeptLanguage/Adept/master/.github/README_logo.png", "adept": "https://raw.github.com/AdeptLanguage/Adept/master/.github/README_logo.png",
"angelscript": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png", "angelscript": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png",
"awk script": "https://github.com/vyfor/icons/raw/master/icons/pastel/awk.png", "awk script": "https://github.com/vyfor/icons/raw/master/icons/pastel/awk.png",
"bat": "https://github.com/vyfor/icons/raw/master/icons/onyx/shell.png", "bat": "https://github.com/vyfor/icons/raw/master/icons/onyx/shell.png",
"bazel": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7d/Bazel_logo.svg/1024px-Bazel_logo.svg.png", "bazel": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7d/Bazel_logo.svg/1024px-Bazel_logo.svg.png",
"bend": "https://avatars.githubusercontent.com/u/92327702", "bend": "https://avatars.githubusercontent.com/u/92327702",
"blueprint": "https://github.com/vyfor/icons/raw/master/icons/onyx/controller.png", "blueprint": "https://github.com/vyfor/icons/raw/master/icons/onyx/controller.png",
"brainfuck": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png", "brainfuck": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png",
"buzz": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png", "buzz": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png",
"c": "https://github.com/vyfor/icons/raw/master/icons/onyx/c.png", "c": "https://github.com/vyfor/icons/raw/master/icons/onyx/c.png",
"carbon": "https://upload.wikimedia.org/wikipedia/commons/e/e1/Carbon_logo.png", "carbon": "https://upload.wikimedia.org/wikipedia/commons/e/e1/Carbon_logo.png",
"clojure": "https://github.com/vyfor/icons/raw/master/icons/onyx/clojure.png", "clojure": "https://github.com/vyfor/icons/raw/master/icons/onyx/clojure.png",
"cmake": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ef/CMake_logo.svg/1024px-CMake_logo.svg.png", "cmake": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ef/CMake_logo.svg/1024px-CMake_logo.svg.png",
"cpp": "https://github.com/vyfor/icons/raw/master/icons/onyx/cpp.png", "cpp": "https://github.com/vyfor/icons/raw/master/icons/onyx/cpp.png",
"crystal": "https://github.com/vyfor/icons/raw/master/icons/onyx/crystal.png", "crystal": "https://github.com/vyfor/icons/raw/master/icons/onyx/crystal.png",
"csharp": "https://github.com/vyfor/icons/raw/master/icons/onyx/csharp.png", "csharp": "https://github.com/vyfor/icons/raw/master/icons/onyx/csharp.png",
"css": "https://github.com/vyfor/icons/raw/master/icons/onyx/css.png", "css": "https://github.com/vyfor/icons/raw/master/icons/onyx/css.png",
"d": "https://github.com/vyfor/icons/raw/master/icons/onyx/d.png", "d": "https://github.com/vyfor/icons/raw/master/icons/onyx/d.png",
"dart": "https://github.com/vyfor/icons/raw/master/icons/onyx/dart.png", "dart": "https://github.com/vyfor/icons/raw/master/icons/onyx/dart.png",
"diff": "https://github.com/vyfor/icons/raw/master/icons/onyx/diagnostics.png", "diff": "https://github.com/vyfor/icons/raw/master/icons/onyx/diagnostics.png",
"dockerfile": "https://github.com/vyfor/icons/raw/master/icons/onyx/docker.png", "dockerfile": "https://github.com/vyfor/icons/raw/master/icons/onyx/docker.png",
"elixir": "https://github.com/vyfor/icons/raw/master/icons/onyx/elixir.png", "elixir": "https://github.com/vyfor/icons/raw/master/icons/onyx/elixir.png",
"elm": "https://github.com/vyfor/icons/raw/master/icons/onyx/elm.png", "elm": "https://github.com/vyfor/icons/raw/master/icons/onyx/elm.png",
"environment file": "https://github.com/vyfor/icons/raw/master/icons/onyx/gear.png", "environment file": "https://github.com/vyfor/icons/raw/master/icons/onyx/gear.png",
"fantom": "https://avatars.githubusercontent.com/u/54911692", "fantom": "https://avatars.githubusercontent.com/u/54911692",
"fortran": "https://github.com/vyfor/icons/raw/master/icons/onyx/fortran.png", "fortran": "https://github.com/vyfor/icons/raw/master/icons/onyx/fortran.png",
"fstab": "https://github.com/vyfor/icons/raw/master/icons/onyx/gear.png", "fstab": "https://github.com/vyfor/icons/raw/master/icons/onyx/gear.png",
"gdscript": "https://github.com/vyfor/icons/raw/master/icons/onyx/godot.png", "gdscript": "https://github.com/vyfor/icons/raw/master/icons/onyx/godot.png",
"glsl": "https://github.com/vyfor/icons/raw/master/icons/onyx/opengl.png", "glsl": "https://github.com/vyfor/icons/raw/master/icons/onyx/opengl.png",
"go": "https://github.com/vyfor/icons/raw/master/icons/onyx/go.png", "go": "https://github.com/vyfor/icons/raw/master/icons/onyx/go.png",
"graphql": "https://github.com/vyfor/icons/raw/master/icons/onyx/graphql.png", "graphql": "https://github.com/vyfor/icons/raw/master/icons/onyx/graphql.png",
"groovy": "https://github.com/vyfor/icons/raw/master/icons/onyx/groovy.png", "groovy": "https://github.com/vyfor/icons/raw/master/icons/onyx/groovy.png",
"hare": "https://harelang.org/mascot.png", "hare": "https://harelang.org/mascot.png",
"haskell": "https://github.com/vyfor/icons/raw/master/icons/onyx/haskell.png", "haskell": "https://github.com/vyfor/icons/raw/master/icons/onyx/haskell.png",
"haxe": "https://github.com/vyfor/icons/raw/master/icons/pastel/haxe.png", "haxe": "https://github.com/vyfor/icons/raw/master/icons/pastel/haxe.png",
"haxe compiler arguments": "https://github.com/vyfor/icons/raw/master/icons/onyx/haxe.png", "haxe compiler arguments": "https://github.com/vyfor/icons/raw/master/icons/onyx/haxe.png",
"hlsl": "https://github.com/vyfor/icons/raw/master/icons/onyx/diagnostics.png", "hlsl": "https://github.com/vyfor/icons/raw/master/icons/onyx/diagnostics.png",
"html": "https://github.com/vyfor/icons/raw/master/icons/onyx/html.png", "html": "https://github.com/vyfor/icons/raw/master/icons/onyx/html.png",
"ini": "https://github.com/vyfor/icons/raw/master/icons/onyx/gear.png", "ini": "https://github.com/vyfor/icons/raw/master/icons/onyx/gear.png",
"jai": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png", "jai": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png",
"java": "https://github.com/vyfor/icons/raw/master/icons/onyx/java.png", "java": "https://github.com/vyfor/icons/raw/master/icons/onyx/java.png",
"javascript": "https://github.com/vyfor/icons/raw/master/icons/onyx/javascript.png", "javascript": "https://github.com/vyfor/icons/raw/master/icons/onyx/javascript.png",
"javascriptreact": "https://github.com/vyfor/icons/raw/master/icons/onyx/react.png", "javascriptreact": "https://github.com/vyfor/icons/raw/master/icons/onyx/react.png",
"json": "https://github.com/vyfor/icons/raw/master/icons/onyx/json.png", "json": "https://github.com/vyfor/icons/raw/master/icons/onyx/json.png",
"julia": "https://github.com/vyfor/icons/raw/master/icons/onyx/julia.png", "julia": "https://github.com/vyfor/icons/raw/master/icons/onyx/julia.png",
"kotlin": "https://github.com/vyfor/icons/raw/master/icons/onyx/kotlin.png", "kotlin": "https://github.com/vyfor/icons/raw/master/icons/onyx/kotlin.png",
"latex": "https://github.com/vyfor/icons/raw/master/icons/onyx/latex.png", "latex": "https://github.com/vyfor/icons/raw/master/icons/onyx/latex.png",
"lobster": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png", "lobster": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png",
"lua": "https://github.com/vyfor/icons/raw/master/icons/onyx/latex.png", "lua": "https://github.com/vyfor/icons/raw/master/icons/onyx/latex.png",
"makefile": "https://github.com/vyfor/icons/raw/master/icons/onyx/diagnostics.png", "makefile": "https://github.com/vyfor/icons/raw/master/icons/onyx/diagnostics.png",
"markdown": "https://github.com/vyfor/icons/raw/master/icons/onyx/markdown.png", "markdown": "https://github.com/vyfor/icons/raw/master/icons/onyx/markdown.png",
"meson": "https://github.com/vyfor/icons/raw/master/icons/onyx/diagnostics.png", "meson": "https://github.com/vyfor/icons/raw/master/icons/onyx/diagnostics.png",
"moonscript": "https://github.com/vyfor/icons/raw/master/icons/onyx/lua.png", "moonscript": "https://github.com/vyfor/icons/raw/master/icons/onyx/lua.png",
"nelua": "https://nelua.io/assets/img/nelua-logo-64px.png", "nelua": "https://nelua.io/assets/img/nelua-logo-64px.png",
"nim": "https://github.com/vyfor/icons/raw/master/icons/onyx/nim.png", "nim": "https://github.com/vyfor/icons/raw/master/icons/onyx/nim.png",
"objeck": "https://github.com/vyfor/icons/raw/master/icons/onyx/gear.png", "objeck": "https://github.com/vyfor/icons/raw/master/icons/onyx/gear.png",
"objective-c": "https://github.com/vyfor/icons/raw/master/icons/onyx/c.png", "objective-c": "https://github.com/vyfor/icons/raw/master/icons/onyx/c.png",
"ocaml": "https://github.com/vyfor/icons/raw/master/icons/onyx/ocaml.png", "ocaml": "https://github.com/vyfor/icons/raw/master/icons/onyx/ocaml.png",
"odin": "https://github.com/vyfor/icons/raw/master/icons/onyx/odin.png", "odin": "https://github.com/vyfor/icons/raw/master/icons/onyx/odin.png",
"openscad": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/eb/Openscad.svg/1024px-Openscad.svg.png", "openscad": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/eb/Openscad.svg/1024px-Openscad.svg.png",
"pascal": "https://github.com/vyfor/icons/raw/master/icons/onyx/pascal.png", "pascal": "https://github.com/vyfor/icons/raw/master/icons/onyx/pascal.png",
"perl": "https://github.com/vyfor/icons/raw/master/icons/onyx/perl.png", "perl": "https://github.com/vyfor/icons/raw/master/icons/onyx/perl.png",
"php": "https://github.com/vyfor/icons/raw/master/icons/onyx/php.png", "php": "https://github.com/vyfor/icons/raw/master/icons/onyx/php.png",
"pico-8": "https://www.lexaloffle.com/gfx/p8b_pico8.png", "pico-8": "https://www.lexaloffle.com/gfx/p8b_pico8.png",
"plaintext": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png", "plaintext": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png",
"po": "https://github.com/vyfor/icons/raw/master/icons/onyx/gnu.png", "po": "https://github.com/vyfor/icons/raw/master/icons/onyx/gnu.png",
"pony": "https://avatars.githubusercontent.com/u/12997238", "pony": "https://avatars.githubusercontent.com/u/12997238",
"postgresql": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/29/Postgresql_elephant.svg/1024px-Postgresql_elephant.svg.png", "postgresql": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/29/Postgresql_elephant.svg/1024px-Postgresql_elephant.svg.png",
"powershell": "https://github.com/vyfor/icons/raw/master/icons/onyx/powershell.png", "powershell": "https://github.com/vyfor/icons/raw/master/icons/onyx/powershell.png",
"python": "https://github.com/vyfor/icons/raw/master/icons/onyx/python.png", "python": "https://github.com/vyfor/icons/raw/master/icons/onyx/python.png",
"r": "https://github.com/vyfor/icons/raw/master/icons/onyx/r.png", "r": "https://github.com/vyfor/icons/raw/master/icons/onyx/r.png",
"ring": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png", "ring": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png",
"ruby": "https://github.com/vyfor/icons/raw/master/icons/onyx/ruby.png", "ruby": "https://github.com/vyfor/icons/raw/master/icons/onyx/ruby.png",
"rust": "https://github.com/vyfor/icons/raw/master/icons/onyx/rust.png", "rust": "https://github.com/vyfor/icons/raw/master/icons/onyx/rust.png",
"sass": "https://github.com/vyfor/icons/raw/master/icons/onyx/scss.png", "sass": "https://github.com/vyfor/icons/raw/master/icons/onyx/scss.png",
"scala": "https://github.com/vyfor/icons/raw/master/icons/onyx/scala.png", "scala": "https://github.com/vyfor/icons/raw/master/icons/onyx/scala.png",
"shellscript": "https://github.com/vyfor/icons/raw/master/icons/onyx/shell.png", "shellscript": "https://github.com/vyfor/icons/raw/master/icons/onyx/shell.png",
"smallbasic": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png", "smallbasic": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png",
"solidity": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png", "solidity": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png",
"sql": "https://github.com/vyfor/icons/raw/master/icons/onyx/sql.png", "sql": "https://github.com/vyfor/icons/raw/master/icons/onyx/sql.png",
"swift": "https://github.com/vyfor/icons/raw/master/icons/onyx/swift.png", "swift": "https://github.com/vyfor/icons/raw/master/icons/onyx/swift.png",
"tcl": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png", "tcl": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png",
"teal": "https://avatars.githubusercontent.com/u/62526430", "teal": "https://avatars.githubusercontent.com/u/62526430",
"toml": "https://github.com/vyfor/icons/raw/master/icons/onyx/toml.png", "toml": "https://github.com/vyfor/icons/raw/master/icons/onyx/toml.png",
"typescript": "https://github.com/vyfor/icons/raw/master/icons/onyx/typescript.png", "typescript": "https://github.com/vyfor/icons/raw/master/icons/onyx/typescript.png",
"typescriptreact": "https://github.com/vyfor/icons/raw/master/icons/onyx/react.png", "typescriptreact": "https://github.com/vyfor/icons/raw/master/icons/onyx/react.png",
"v": "https://github.com/vyfor/icons/raw/master/icons/onyx/v.png", "v": "https://github.com/vyfor/icons/raw/master/icons/onyx/v.png",
"vala": "https://github.com/vyfor/icons/raw/master/icons/onyx/vala.png", "vala": "https://github.com/vyfor/icons/raw/master/icons/onyx/vala.png",
"verilog": "https://github.com/vyfor/icons/raw/master/icons/onyx/assembly.png", "verilog": "https://github.com/vyfor/icons/raw/master/icons/onyx/assembly.png",
"visual basic": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/40/VB.NET_Logo.svg/1024px-VB.NET_Logo.svg.png", "visual basic": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/40/VB.NET_Logo.svg/1024px-VB.NET_Logo.svg.png",
"vue": "https://github.com/vyfor/icons/raw/master/icons/onyx/vue.png", "vue": "https://github.com/vyfor/icons/raw/master/icons/onyx/vue.png",
"wren": "https://avatars.githubusercontent.com/u/45213573", "wren": "https://avatars.githubusercontent.com/u/45213573",
"x86 assembly": "https://github.com/vyfor/icons/raw/master/icons/onyx/assembly.png", "x86 assembly": "https://github.com/vyfor/icons/raw/master/icons/onyx/assembly.png",
"xml": "https://github.com/vyfor/icons/raw/master/icons/onyx/xml.png", "xml": "https://github.com/vyfor/icons/raw/master/icons/onyx/xml.png",
"xtend": "https://github.com/vyfor/icons/raw/master/icons/onyx/java.png", "xtend": "https://github.com/vyfor/icons/raw/master/icons/onyx/java.png",
"yaml": "https://github.com/vyfor/icons/raw/master/icons/onyx/yaml.png", "yaml": "https://github.com/vyfor/icons/raw/master/icons/onyx/yaml.png",
"zig": "https://github.com/vyfor/icons/raw/master/icons/onyx/zig.png" "zig": "https://github.com/vyfor/icons/raw/master/icons/onyx/zig.png"
} }
}, },
"keybindings" : { "keybindings": {}
}
} }

View File

@@ -1,7 +1,7 @@
#include "discordRPCplugin.hpp" #include "discordRPCplugin.hpp"
using json = nlohmann::json; using json = nlohmann::json;
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined ( __EMSCRIPTEN_PTHREADS__ ) #if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
#define dcRPC_THREADED 1 #define dcRPC_THREADED 1
#else #else
#define dcRPC_THREADED 0 #define dcRPC_THREADED 0
@@ -9,11 +9,11 @@ using json = nlohmann::json;
namespace ecode { namespace ecode {
Plugin* DiscordRPCplugin::New( PluginManager* pluginManager) { Plugin* DiscordRPCplugin::New( PluginManager* pluginManager ) {
return eeNew( DiscordRPCplugin, ( pluginManager, false ) ); return eeNew( DiscordRPCplugin, ( pluginManager, false ) );
} }
Plugin* DiscordRPCplugin::NewSync( PluginManager* pluginManager) { Plugin* DiscordRPCplugin::NewSync( PluginManager* pluginManager ) {
return eeNew( DiscordRPCplugin, ( pluginManager, true ) ); return eeNew( DiscordRPCplugin, ( pluginManager, true ) );
} }
@@ -33,7 +33,6 @@ DiscordRPCplugin::DiscordRPCplugin( PluginManager* pluginManager, bool sync ) :
DiscordRPCplugin::~DiscordRPCplugin() { DiscordRPCplugin::~DiscordRPCplugin() {
waitUntilLoaded(); waitUntilLoaded();
mShuttingDown = true; mShuttingDown = true;
} }
void DiscordRPCplugin::load( PluginManager* pluginManager ) { void DiscordRPCplugin::load( PluginManager* pluginManager ) {
Clock clock; Clock clock;
@@ -50,11 +49,11 @@ void DiscordRPCplugin::load( PluginManager* pluginManager ) {
paths.emplace_back( path ); paths.emplace_back( path );
path = pluginManager->getPluginsPath() + "discordRPC.json"; path = pluginManager->getPluginsPath() + "discordRPC.json";
if ( FileSystem::fileExists( path ) || if ( FileSystem::fileExists( path ) ||
FileSystem::fileWrite(path, "{\n \"config\":{},\n \"keybindings\":{}\n}\n") ) { FileSystem::fileWrite( path, "{\n \"config\":{},\n \"keybindings\":{}\n}\n" ) ) {
mConfigPath = path; mConfigPath = path;
paths.emplace_back( path ); paths.emplace_back( path );
} }
std::string data; std::string data;
if ( !FileSystem::fileGet( path, data ) ) if ( !FileSystem::fileGet( path, data ) )
return; return;
mConfigHash = String::hash( data ); mConfigHash = String::hash( data );
@@ -81,7 +80,12 @@ void DiscordRPCplugin::load( PluginManager* pluginManager ) {
mIPC.mcClientID = "1335730393948749898"; mIPC.mcClientID = "1335730393948749898";
updateConfigFile = true; updateConfigFile = true;
} }
if ( config.contains( "doLanguageIcons" ) ) {
mcDoLangIcon = config.value( "doLanguageIcons", true );
} else {
mIPC.mcClientID = true;
updateConfigFile = true;
}
} }
if ( updateConfigFile ) { if ( updateConfigFile ) {
@@ -96,7 +100,7 @@ void DiscordRPCplugin::load( PluginManager* pluginManager ) {
DiscordIPCActivity* a = mIPC.getActivity(); DiscordIPCActivity* a = mIPC.getActivity();
a->largeImage = DISCORDRPC_DEFAULT_ICON; a->largeImage = DISCORDRPC_DEFAULT_ICON;
mIPC.setActivity(*a); mIPC.setActivity( *a );
mReady = true; mReady = true;
fireReadyCbs(); fireReadyCbs();
@@ -109,13 +113,13 @@ PluginRequestHandle DiscordRPCplugin::processMessage( const PluginMessage& msg )
std::string rpath = FileSystem::getRealPath( msg.asJSON()["folder"] ); std::string rpath = FileSystem::getRealPath( msg.asJSON()["folder"] );
FileSystem::dirAddSlashAtEnd( rpath ); FileSystem::dirAddSlashAtEnd( rpath );
mProjectName = FileSystem::fileNameFromPath( rpath ); mProjectName = FileSystem::fileNameFromPath( rpath );
Log::debug("Loaded new workspace: %s ; %s", rpath, mProjectName); Log::debug( "Loaded new workspace: %s ; %s", rpath, mProjectName );
} }
case PluginMessageType::UIReady: { case PluginMessageType::UIReady: {
mIPC.mUIReady = true; mIPC.mUIReady = true;
// Log::debug("dcPlugin: UI is ready!"); // Log::debug("dcPlugin: UI is ready!");
if (mIPC.mIsReconnectScheduled) { if ( mIPC.mIsReconnectScheduled ) {
Log::debug("Running scheduled reconnect"); Log::debug( "Running scheduled reconnect" );
mIPC.tryConnect(); mIPC.tryConnect();
} }
} }
@@ -126,10 +130,15 @@ PluginRequestHandle DiscordRPCplugin::processMessage( const PluginMessage& msg )
return PluginRequestHandle::empty(); return PluginRequestHandle::empty();
} }
void DiscordRPCplugin::onRegisterDocument( TextDocument* doc ){ void DiscordRPCplugin::onRegisterEditor( UICodeEditor* editor ) {
doc->setCommand( "discordrpc-reconnect", [this] { editor->addUnlockedCommands( { "discordrpc-reconnect" } );
mIPC.reconnect(); editor->getDocument().setCommand( "discordrpc-reconnect", [this] { mIPC.reconnect(); } );
} );
PluginBase::onRegisterEditor( editor );
}
void DiscordRPCplugin::onUnregisterEditor( UICodeEditor* editor ) {
editor->removeUnlockedCommands( { "discordrpc-reconnect" } );
} }
void DiscordRPCplugin::onRegisterListeners( UICodeEditor* editor, std::vector<Uint32>& listeners ) { void DiscordRPCplugin::onRegisterListeners( UICodeEditor* editor, std::vector<Uint32>& listeners ) {
@@ -137,7 +146,9 @@ void DiscordRPCplugin::onRegisterListeners( UICodeEditor* editor, std::vector<Ui
// `this` in the scope of the lambda is the parent `DiscordRPCplugin` // `this` in the scope of the lambda is the parent `DiscordRPCplugin`
auto& doc = editor->getDocument(); auto& doc = editor->getDocument();
if (!doc.hasFilepath()) { return; } if ( !doc.hasFilepath() ) {
return;
}
auto filename = doc.getFilename(); auto filename = doc.getFilename();
@@ -149,27 +160,25 @@ void DiscordRPCplugin::onRegisterListeners( UICodeEditor* editor, std::vector<Ui
DiscordIPCActivity* a = this->mIPC.getActivity(); DiscordIPCActivity* a = this->mIPC.getActivity();
if (!mProjectName.empty()) if ( !mProjectName.empty() )
a->details = String::format(i18n( "dc_workspace", "Working on %s" ).toUtf8(), a->details = String::format( i18n( "dc_workspace", "Working on %s" ).toUtf8(),
mProjectName); mProjectName );
a->state = String::format(i18n( "dc_editing", "Editing %s, a %s file" ).toUtf8(), a->state = String::format( i18n( "dc_editing", "Editing %s, a %s file" ).toUtf8(),
filename, doc.getSyntaxDefinition().getLanguageName() ); filename, doc.getSyntaxDefinition().getLanguageName() );
a->start = time( nullptr ); // Time spent in this specific file a->start = time( nullptr ); // Time spent in this specific file
// TODO: Implement github/gitlab remote button (integrate with git plugin)
// a->buttons[0].label = "Repository";
// a->buttons[0].url = "https://github.com/name/repo";
std::string name = doc.getSyntaxDefinition().getLSPName(); std::string name = doc.getSyntaxDefinition().getLSPName();
if (!name.empty()) { if ( !name.empty() && mcDoLangIcon ) {
a->largeImage = mcLangBindings.value(name, DISCORDRPC_DEFAULT_ICON); a->largeImage = mcLangBindings.value( name, DISCORDRPC_DEFAULT_ICON );
} }
this->mIPC.setActivity( *a ); this->mIPC.setActivity( *a );
} }
} ) ); } ) );
} }
} // namespace ecode } // namespace ecode

View File

@@ -4,10 +4,10 @@
#include "../plugin.hpp" #include "../plugin.hpp"
#include "../pluginmanager.hpp" #include "../pluginmanager.hpp"
#include <eepp/system/threadpool.hpp>
#include <eepp/system/mutex.hpp>
#include <eepp/system/filesystem.hpp> #include <eepp/system/filesystem.hpp>
#include <eepp/system/mutex.hpp>
#include <eepp/system/scopedop.hpp> #include <eepp/system/scopedop.hpp>
#include <eepp/system/threadpool.hpp>
#include "sdk/ipc.hpp" #include "sdk/ipc.hpp"
@@ -18,52 +18,53 @@ using namespace EE::System;
using namespace EE::UI; using namespace EE::UI;
using namespace EE::UI::Doc; using namespace EE::UI::Doc;
#define DISCORDRPC_DEFAULT_ICON "https://github.com/SpartanJ/eepp/blob/develop/bin/assets/icon/ecode.png?raw=true" #define DISCORDRPC_DEFAULT_ICON \
"https://github.com/SpartanJ/eepp/blob/develop/bin/assets/icon/ecode.png?raw=true"
namespace ecode { namespace ecode {
class DiscordRPCplugin : public PluginBase { class DiscordRPCplugin : public PluginBase {
public: public:
static PluginDefinition Definition() { static PluginDefinition Definition() {
return { return { "discrdrpc",
"discrdrpc", "Discord Rich Presence",
"Discord Rich Presence", "Show your friends what you are up to through the discord Rich Presence system",
"Show your friends what you are up to through the discord Rich Presence system", DiscordRPCplugin::New,
DiscordRPCplugin::New, { 0, 0, 0 },
{ 0, 0, 0 }, DiscordRPCplugin::NewSync };
DiscordRPCplugin::NewSync }; }
}
static Plugin* New( PluginManager* pluginManager ); static Plugin* New( PluginManager* pluginManager );
static Plugin* NewSync( PluginManager* pluginManager ); static Plugin* NewSync( PluginManager* pluginManager );
virtual ~DiscordRPCplugin() override; virtual ~DiscordRPCplugin() override;
std::string getId() override { return Definition().id; } std::string getId() override { return Definition().id; }
std::string getTitle() override { return Definition().name; } std::string getTitle() override { return Definition().name; }
std::string getDescription() override { return Definition().description; } std::string getDescription() override { return Definition().description; }
protected: protected:
DiscordIPC mIPC; DiscordIPC mIPC;
std::string mLastFile; std::string mLastFile;
std::string mProjectName; std::string mProjectName;
nlohmann::json mcLangBindings; nlohmann::json mcLangBindings;
bool mcDoLangIcon;
void load ( PluginManager* pluginManager ); void load( PluginManager* pluginManager );
PluginRequestHandle processMessage( const PluginMessage& msg ); PluginRequestHandle processMessage( const PluginMessage& msg );
virtual void onRegisterListeners(UICodeEditor* editor, std::vector<Uint32>& listeners ) override; virtual void onRegisterListeners( UICodeEditor* editor,
virtual void onRegisterDocument( TextDocument* doc ) override; std::vector<Uint32>& listeners ) override;
virtual void onRegisterEditor( UICodeEditor* editor ) override;
virtual void onUnregisterEditor( UICodeEditor* editor ) override;
DiscordRPCplugin( PluginManager* pluginManager, bool sync );
DiscordRPCplugin( PluginManager* pluginManager, bool sync );
}; };
} // namespace ecode } // namespace ecode
#endif // ECODE_DISCORDRPCPLUGIN_HPP #endif // ECODE_DISCORDRPCPLUGIN_HPP

View File

@@ -3,19 +3,19 @@
#include <filesystem> #include <filesystem>
#include <vector> #include <vector>
#include <eepp/system/log.hpp>
#include <eepp/scene/scenemanager.hpp> #include <eepp/scene/scenemanager.hpp>
#include <eepp/system/log.hpp>
#include <eepp/ui/uiscenenode.hpp> #include <eepp/ui/uiscenenode.hpp>
#if defined( EE_PLATFORM_POSIX ) #if defined( EE_PLATFORM_POSIX )
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
#include <unistd.h> #include <unistd.h>
#elif EE_PLATFORM == EE_PLATFORM_WIN #elif EE_PLATFORM == EE_PLATFORM_WIN
#ifndef WIN32LEAN_AND_MEAN #ifndef WIN32LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#endif #endif
#include <windows.h> #include <windows.h>
#endif #endif
using namespace EE::System; using namespace EE::System;
@@ -27,303 +27,320 @@ DiscordIPC::DiscordIPC() {
} }
bool DiscordIPC::tryConnect() { bool DiscordIPC::tryConnect() {
#if EE_PLATFORM == EE_PLATFORM_WIN #if EE_PLATFORM == EE_PLATFORM_WIN
std::string basePath = "\\\\.\\pipe\\"; std::string basePath = "\\\\.\\pipe\\";
for (int i = 0; i < 10; ++i) { for ( int i = 0; i < 10; ++i ) {
std::string ipcPath = basePath + "discord-ipc-" + std::to_string(i); std::string ipcPath = basePath + "discord-ipc-" + std::to_string( i );
// Check if exists // Check if exists
DWORD attributes = GetFileAttributes(ipcPath.c_str()); DWORD attributes = GetFileAttributes( ipcPath.c_str() );
if (attributes != INVALID_FILE_ATTRIBUTES) { if ( attributes != INVALID_FILE_ATTRIBUTES ) {
Log::debug("dcIPC: IPC path found! - %s", ipcPath); Log::debug( "dcIPC: IPC path found! - %s", ipcPath );
mIpcPath = ipcPath; mIpcPath = ipcPath;
mSocket = CreateFile(mIpcPath.c_str(), GENERIC_READ | GENERIC_WRITE, mSocket = CreateFile( mIpcPath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr,
0, nullptr, OPEN_EXISTING, 0, nullptr); OPEN_EXISTING, 0, nullptr );
doHandshake(); doHandshake();
return true; return true;
}
} }
}
reconnect();
return false;
#elif defined( EE_PLATFORM_POSIX )
// Socket path can be in any of the following directories:
// * `XDG_RUNTIME_DIR`
// * `TMPDIR`
// * `TMP`
// * `TEMP`
// * `/tmp`
//
// Possibly Followed by:
// * `/app/com.discordapp.Discord` - for flatpak
// * `/.flatpak/dev.vencord.Vesktop/xdg-run` - Vesktop flatpak
// * `/snap.discord` - for snap
//
// Followed by:
// * `/discord-ipc-{i}` - where `i` is a number from 0 to 9
const std::string env[] = { "XDG_RUNTIME_DIR", "TMPDIR", "TMP", "TEMP" };
const std::vector<std::string> additionalPaths = {
"/app/com.discordapp.Discord",
"/.flatpak/dev.vencord.Vesktop/xdg-run",
"/snap.discord",
};
std::vector<std::string> validPaths;
for ( const auto& eVar : env ) {
const char* value = std::getenv( eVar.c_str() );
if ( !value ) {
continue;
}
if ( !std::filesystem::exists( value ) ) {
continue;
}
validPaths.push_back( value );
}
validPaths.push_back( "/tmp" ); // Hard coded fallback
std::vector<std::string> checkPaths;
for ( const auto& basePath : validPaths ) {
for ( const auto& additionalPath : additionalPaths ) {
std::string fullPath = basePath + additionalPath;
if ( std::filesystem::exists( fullPath ) ) {
checkPaths.push_back( fullPath );
}
}
}
checkPaths.insert( checkPaths.end(), validPaths.begin(), validPaths.end() );
for ( const auto& basePath : checkPaths ) {
if ( !std::filesystem::exists( basePath ) ) {
continue;
}
for ( int i = 0; i < 10; ++i ) {
std::string ipcPath = basePath + "/discord-ipc-" + std::to_string( i );
if ( std::filesystem::exists( ipcPath ) ) {
Log::debug( "dcIPC: IPC path found! - %s", ipcPath );
mIpcPath = ipcPath;
mSocket = socket( AF_UNIX, SOCK_STREAM, 0 );
if ( mSocket == -1 ) {
Log::error( "dcIPC: Discord IPC socket cold not be opened: %s", mIpcPath );
mIpcPath = "";
continue;
}
sockaddr_un serverAddr;
memset( &serverAddr, 0, sizeof( serverAddr ) );
serverAddr.sun_family = AF_UNIX;
mIpcPath.copy( serverAddr.sun_path, sizeof( serverAddr.sun_path ) - 1 );
serverAddr.sun_path[sizeof( serverAddr.sun_path ) - 1] =
'\0'; // Ensure null termination
if ( connect( mSocket, reinterpret_cast<struct sockaddr*>( &serverAddr ),
sizeof( serverAddr ) ) == -1 ) {
close( mSocket );
return false;
}
doHandshake();
return true;
}
}
reconnect(); reconnect();
return false; return false;
}
#elif defined(EE_PLATFORM_POSIX) #endif
// Socket path can be in any of the following directories:
// * `XDG_RUNTIME_DIR`
// * `TMPDIR`
// * `TMP`
// * `TEMP`
// * `/tmp`
//
// Possibly Followed by:
// * `/app/com.discordapp.Discord` - for flatpak
// * `/.flatpak/dev.vencord.Vesktop/xdg-run` - Vesktop flatpak
// * `/snap.discord` - for snap
//
// Followed by:
// * `/discord-ipc-{i}` - where `i` is a number from 0 to 9
const std::string env[] = {"XDG_RUNTIME_DIR", "TMPDIR", "TMP", "TEMP"};
const std::vector<std::string> additionalPaths = {
"/app/com.discordapp.Discord",
"/.flatpak/dev.vencord.Vesktop/xdg-run",
"/snap.discord",
};
std::vector<std::string> validPaths;
for ( const auto& eVar : env ){
const char* value = std::getenv(eVar.c_str());
if (!value) { continue; }
if (!std::filesystem::exists(value)) { continue; }
validPaths.push_back(value);
}
validPaths.push_back("/tmp"); // Hard coded fallback
std::vector<std::string> checkPaths;
for ( const auto& basePath : validPaths ) {
for (const auto& additionalPath : additionalPaths) {
std::string fullPath = basePath + additionalPath;
if (std::filesystem::exists(fullPath)) {
checkPaths.push_back(fullPath);
}
}
}
checkPaths.insert(checkPaths.end(), validPaths.begin(), validPaths.end());
for (const auto& basePath : checkPaths) {
if (!std::filesystem::exists(basePath)) { continue; }
for (int i = 0; i < 10; ++i) {
std::string ipcPath = basePath + "/discord-ipc-" + std::to_string(i);
if (std::filesystem::exists(ipcPath)) {
Log::debug("dcIPC: IPC path found! - %s", ipcPath);
mIpcPath = ipcPath;
mSocket = socket(AF_UNIX, SOCK_STREAM, 0);
if (mSocket == -1) {
Log::error("dcIPC: Discord IPC socket cold not be opened: %s", mIpcPath);
mIpcPath = "";
continue;
}
sockaddr_un serverAddr;
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sun_family = AF_UNIX;
mIpcPath.copy(serverAddr.sun_path, sizeof(serverAddr.sun_path) - 1);
serverAddr.sun_path[sizeof(serverAddr.sun_path) - 1] = '\0'; // Ensure null termination
if (connect(mSocket, reinterpret_cast<struct sockaddr*>(&serverAddr), sizeof(serverAddr)) == -1) {
close(mSocket);
return false;
}
doHandshake();
return true;
}
}
reconnect();
return false;
}
#endif
return false; // Discord not supported by other OS (if it is, TBA) return false; // Discord not supported by other OS (if it is, TBA)
} }
void DiscordIPC::doHandshake() { void DiscordIPC::doHandshake() {
json j = { json j = { { "v", 1 }, { "client_id", mcClientID } };
{"v", 1},
{"client_id", mcClientID}
};
sendPacket(DiscordIPCOpcodes::Handshake, j); sendPacket( DiscordIPCOpcodes::Handshake, j );
} }
void DiscordIPC::clearActivity() { void DiscordIPC::clearActivity() {
json j = { json j = {
{"cmd", "SET_ACTIVITY"}, { "cmd", "SET_ACTIVITY" },
{"args", { { "args", { { "pid", 0 }, { "activity", nullptr } } },
{"pid", 0}, { "nonce", "-" } // TODO: Null nonce for dev purposes, change to UUIDV4 in finished product
{"activity", nullptr} };
}}, sendPacket( DiscordIPCOpcodes::Frame, j );
{"nonce", "-"} // TODO: Null nonce for dev purposes, change to UUIDV4 in finished product
};
sendPacket(DiscordIPCOpcodes::Frame, j);
} }
void DiscordIPC::setActivity( DiscordIPCActivity a ) { void DiscordIPC::setActivity( DiscordIPCActivity a ) {
json aj = { json aj = {
{"type", static_cast<int>(a.type)}, { "type", static_cast<int>( a.type ) },
{"instance", true}, { "instance", true },
};
if (!a.state.empty())
aj["state"] = a.state;
if (!a.details.empty())
aj["details"] = a.details;
json as;
if (!a.largeImage.empty()) {
as["large_image"] = a.largeImage;
}
if (!a.largeText.empty()) {
as["large_text"] = a.largeText;
}
if (!a.smallImage.empty()) {
as["small_image"] = a.smallImage;
}
if (!a.smallText.empty()) {
as["small_text"] = a.smallText;
}
if (!as.empty()) {
aj["assets"] = as;
}
json t;
if (a.start != 0) {
t["start"] = a.start;
}
if (a.end != 0) {
t["end"] = a.end;
}
if (!t.empty()) {
aj["timestamps"] = t;
}
json b;
if (!a.buttons[0].url.empty()){
b[0]["label"] = a.buttons[0].label;
b[0]["url"] = a.buttons[0].url;
}
if (!a.buttons[1].url.empty()){
b[1]["label"] = a.buttons[1].label;
b[1]["url"] = a.buttons[1].url;
}
if (!b.empty()) {
aj["buttons"] = b;
}
json j{
{"cmd", "SET_ACTIVITY"},
{"args", {
{"pid", mPID},
{"activity", aj},
}},
{"nonce", "-"}
}; };
if ( !a.state.empty() )
aj["state"] = a.state;
if ( !a.details.empty() )
aj["details"] = a.details;
json as;
if ( !a.largeImage.empty() ) {
as["large_image"] = a.largeImage;
}
if ( !a.largeText.empty() ) {
as["large_text"] = a.largeText;
}
if ( !a.smallImage.empty() ) {
as["small_image"] = a.smallImage;
}
if ( !a.smallText.empty() ) {
as["small_text"] = a.smallText;
}
if ( !as.empty() ) {
aj["assets"] = as;
}
json t;
if ( a.start != 0 ) {
t["start"] = a.start;
}
if ( a.end != 0 ) {
t["end"] = a.end;
}
if ( !t.empty() ) {
aj["timestamps"] = t;
}
json b;
if ( !a.buttons[0].url.empty() ) {
b[0]["label"] = a.buttons[0].label;
b[0]["url"] = a.buttons[0].url;
}
if ( !a.buttons[1].url.empty() ) {
b[1]["label"] = a.buttons[1].label;
b[1]["url"] = a.buttons[1].url;
}
if ( !b.empty() ) {
aj["buttons"] = b;
}
json j{ { "cmd", "SET_ACTIVITY" },
{ "args",
{
{ "pid", mPID },
{ "activity", aj },
} },
{ "nonce", "-" } };
mActivity = a; mActivity = a;
sendPacket(DiscordIPCOpcodes::Frame, j); sendPacket( DiscordIPCOpcodes::Frame, j );
} }
void DiscordIPC::sendPacket(DiscordIPCOpcodes opcode, json j) { void DiscordIPC::sendPacket( DiscordIPCOpcodes opcode, json j ) {
if (!std::filesystem::exists(mIpcPath)) { reconnect(); return; } if ( !std::filesystem::exists( mIpcPath ) ) {
reconnect();
return;
}
const std::string packet = j.dump(); const std::string packet = j.dump();
std::vector<uint8_t> data; std::vector<uint8_t> data;
// Add correct ammount of padding for the protocol // Add correct ammount of padding for the protocol
union { union {
uint32_t value; uint32_t value;
uint8_t bytes[4]; uint8_t bytes[4];
} bytes; } bytes;
bytes.value = opcode; bytes.value = opcode;
for (int i = 0; i <= 3; ++i) { for ( int i = 0; i <= 3; ++i ) {
data.push_back(bytes.bytes[i]); data.push_back( bytes.bytes[i] );
} }
bytes.value = packet.length(); bytes.value = packet.length();
for (int i = 0; i <= 3; ++i) { for ( int i = 0; i <= 3; ++i ) {
data.push_back(bytes.bytes[i]); data.push_back( bytes.bytes[i] );
} }
for (char c : packet) { for ( char c : packet ) {
data.push_back(static_cast<uint8_t>(c)); data.push_back( static_cast<uint8_t>( c ) );
} }
// Log::debug("Packet is: %s (%u)", j.dump(4), data.size()); // Log::debug("Packet is: %s (%u)", j.dump(4), data.size());
// std::stringstream ss; // std::stringstream ss;
// for (uint8_t byte : data) { // for (uint8_t byte : data) {
// ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte) << " "; // ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte) << " ";
// } // }
// Log::debug(ss.str()); // Log::debug(ss.str());
#if defined( EE_PLATFORM_POSIX ) #if defined( EE_PLATFORM_POSIX )
ssize_t bytesSent = send(mSocket, data.data(), data.size(), 0); ssize_t bytesSent = send( mSocket, data.data(), data.size(), 0 );
if (bytesSent != data.size()) { if ( bytesSent != data.size() ) {
Log::error("dcIPC: Failed to send all data to Unix socket: %zu bytes sent, %zu bytes expected", bytesSent, data.size()); Log::error(
reconnect(); "dcIPC: Failed to send all data to Unix socket: %zu bytes sent, %zu bytes expected",
return; bytesSent, data.size() );
} reconnect();
return;
}
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 500000; // 0.5 seconds in microseconds
setsockopt( mSocket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof( tv ) );
struct timeval tv; char buffer[1024];
tv.tv_sec = 0; ssize_t bytesRead = recv( mSocket, buffer, sizeof( buffer ), 0 );
tv.tv_usec = 500000; // 0.5 seconds in microseconds
setsockopt(mSocket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
char buffer[1024]; // Log::debug("dcIPC: RECV: %s", buffer);
ssize_t bytesRead = recv(mSocket, buffer, sizeof(buffer), 0);
// Log::debug("dcIPC: RECV: %s", buffer); // TODO: Implement nonce checking? (does it even really matter?)
// TODO: Implement nonce checking? (does it even really matter?) // return bytesRead;
#elif EE_PLATFORM == EE_PLATFORM_WIN
DWORD bytesSent;
if ( !WriteFile( mSocket, data.data(), data.size(), &bytesSent, nullptr ) ) {
Log::error( "dcIPC: Error writing to pipe!!" );
reconnect();
return;
} else if ( bytesSent != data.size() ) {
Log::error( "dcIPC: Incorrect ammount of data written: %zu bytes sent, %zu bytes expected",
bytesSent, data.size() );
reconnect();
return;
}
//return bytesRead; DWORD bytesRead;
#elif EE_PLATFORM == EE_PLATFORM_WIN char buffer[1024];
DWORD bytesSent; if ( !ReadFile( mSocket, buffer, 1024, &bytesRead, nullptr ) ) {
if ( !WriteFile(mSocket, data.data(), data.size(), &bytesSent, nullptr) ) { Log::error( "dcIPC: Error reading pipe!!" );
Log::error("dcIPC: Error writing to pipe!!"); reconnect();
reconnect(); return;
return; }
} else if (bytesSent != data.size()) {
Log::error("dcIPC: Incorrect ammount of data written: %zu bytes sent, %zu bytes expected",
bytesSent, data.size());
reconnect();
return;
}
DWORD bytesRead; // Log::debug("dcIPC: RECV: %s", buffer);
char buffer[1024];
if ( !ReadFile(mSocket, buffer, 1024, &bytesRead, nullptr ) ) {
Log::error("dcIPC: Error reading pipe!!");
reconnect();
return;
}
// Log::debug("dcIPC: RECV: %s", buffer); #endif
#endif
} }
void DiscordIPC::reconnect() { void DiscordIPC::reconnect() {
if (mReconnectLock) {Log::warning("dcIPC: Tried to call reconnect while locked"); return;} if ( mReconnectLock ) {
if (!mUIReady) { Log::debug("dcIPC: Scheduled a reconnect"); mIsReconnectScheduled = true; return; } Log::warning( "dcIPC: Tried to call reconnect while locked" );
if (mBackoffIndex < DISCORDIPC_BACKOFF_MAX) { mBackoffIndex++; } return;
int delay = 5 + pow(2, mBackoffIndex); }
if ( !mUIReady ) {
Log::debug( "dcIPC: Scheduled a reconnect" );
mIsReconnectScheduled = true;
return;
}
if ( mBackoffIndex < DISCORDIPC_BACKOFF_MAX ) {
mBackoffIndex++;
}
int delay = 5 + pow( 2, mBackoffIndex );
mReconnectLock = true; mReconnectLock = true;
Log::warning("dcIPC: Waiting for reconnect delay of %us (%u/%u)", delay, mBackoffIndex, DISCORDIPC_BACKOFF_MAX); Log::warning( "dcIPC: Waiting for reconnect delay of %us (%u/%u)", delay, mBackoffIndex,
EE::Scene::SceneManager::instance()->getUISceneNode() DISCORDIPC_BACKOFF_MAX );
->setTimeout( [this] { EE::Scene::SceneManager::instance()->getUISceneNode()->setTimeout(
EE::Scene::SceneManager::instance()->getUISceneNode() [this] {
->getThreadPool()->run( [this]{ EE::Scene::SceneManager::instance()->getUISceneNode()->getThreadPool()->run( [this] {
Log::info("dcIPC: Reconnecting..."); Log::info( "dcIPC: Reconnecting..." );
mReconnectLock = false; mReconnectLock = false;
if(tryConnect()){ mBackoffIndex = 0; } if ( tryConnect() ) {
}); mBackoffIndex = 0;
}, Seconds(delay)); }
} );
},
Seconds( delay ) );
} }
DiscordIPC::~DiscordIPC() { DiscordIPC::~DiscordIPC() {
#if defined( EE_PLATFORM_POSIX ) #if defined( EE_PLATFORM_POSIX )
close(mSocket); close( mSocket );
#elif EE_PLATFORM == EE_PLATFORM_WIN #elif EE_PLATFORM == EE_PLATFORM_WIN
CloseHandle(mSocket); CloseHandle( mSocket );
#endif #endif
} }

View File

@@ -6,78 +6,75 @@
#define DISCORDIPC_BACKOFF_MAX 8 #define DISCORDIPC_BACKOFF_MAX 8
enum DiscordIPCActivityTypes { enum DiscordIPCActivityTypes {
Playing = 0, Playing = 0,
Listening = 2, Listening = 2,
Watching = 3, Watching = 3,
Competing = 5, Competing = 5,
}; };
struct DiscordIPCActivityButton { struct DiscordIPCActivityButton {
std::string label; std::string label;
std::string url; std::string url;
}; };
struct DiscordIPCActivity { struct DiscordIPCActivity {
DiscordIPCActivityTypes type = DiscordIPCActivityTypes::Playing; DiscordIPCActivityTypes type = DiscordIPCActivityTypes::Playing;
std::string state; std::string state;
std::string details; std::string details;
time_t start = 0; time_t start = 0;
time_t end = 0; time_t end = 0;
std::string largeImage; std::string largeImage;
std::string largeText; std::string largeText;
std::string smallImage; std::string smallImage;
std::string smallText; std::string smallText;
DiscordIPCActivityButton buttons[2]; // IMPORTANT: For some reason, you do not see the buttons of your own account on the discord
// client (intended discord behavior)
DiscordIPCActivityButton buttons[2];
}; };
enum DiscordIPCOpcodes { enum DiscordIPCOpcodes { Handshake = 0, Frame, Close, Ping, Pong };
Handshake = 0,
Frame,
Close,
Ping,
Pong
};
class DiscordIPC { class DiscordIPC {
public: public:
virtual ~DiscordIPC();
DiscordIPC();
virtual ~DiscordIPC(); // false - FileNotFound/OSNotSupported
DiscordIPC(); // true - Success
bool tryConnect();
void reconnect();
// false - FileNotFound/OSNotSupported void setActivity( DiscordIPCActivity a );
// true - Success DiscordIPCActivity* getActivity() { return &mActivity; }
bool tryConnect(); void clearActivity();
void reconnect();
void setActivity( DiscordIPCActivity a ); bool mUIReady;
DiscordIPCActivity *getActivity() { return &mActivity; } bool mIsReconnectScheduled =
void clearActivity(); false; // If we fail to load bofore UI initialises we call reconnect after init
bool mUIReady; // Configurables
bool mIsReconnectScheduled = false; // If we fail to load bofore UI initialises we call reconnect after init std::string mcClientID;
//Configurables protected:
std::string mcClientID; std::string mIpcPath;
protected: int mPID;
std::string mIpcPath;
int mPID;
int mBackoffIndex; int mBackoffIndex;
int mReconnectLock = false; // Not quite a mutex because I want to lock any attempts if one is already waiting int mReconnectLock =
false; // Not quite a mutex because I want to lock any attempts if one is already waiting
DiscordIPCActivity mActivity; DiscordIPCActivity mActivity;
#if defined( EE_PLATFORM_POSIX )
int mSocket;
#elif EE_PLATFORM == EE_PLATFORM_WIN
void* mSocket;
#endif
#if defined( EE_PLATFORM_POSIX ) void doHandshake();
int mSocket;
#elif EE_PLATFORM == EE_PLATFORM_WIN
void* mSocket;
#endif
void doHandshake(); void sendPacket( DiscordIPCOpcodes opcode, nlohmann::json j );
void sendPacket( DiscordIPCOpcodes opcode, nlohmann::json j );
}; };