mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-05-28 17:16:29 +03:00
Clang-format; Correctly add command discordrpc-reconnect; Check for doLanguageIcons config option
This commit is contained in:
@@ -160,6 +160,8 @@ File path is: </string>
|
||||
<string name="cut">Cut</string>
|
||||
<string name="dark">Dark</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_toggle">Debug Draw Boxes Toggle</string>
|
||||
<string name="debug_draw_debug_data">Debug Draw Debug Data</string>
|
||||
|
||||
@@ -1,112 +1,110 @@
|
||||
{
|
||||
"config" : {
|
||||
"appID": "1335730393948749898",
|
||||
"doLanguageIcons": true,
|
||||
"iconBindings": {
|
||||
".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",
|
||||
"[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",
|
||||
"adept": "https://raw.github.com/AdeptLanguage/Adept/master/.github/README_logo.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",
|
||||
"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",
|
||||
"bend": "https://avatars.githubusercontent.com/u/92327702",
|
||||
"blueprint": "https://github.com/vyfor/icons/raw/master/icons/onyx/controller.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",
|
||||
"c": "https://github.com/vyfor/icons/raw/master/icons/onyx/c.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",
|
||||
"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",
|
||||
"crystal": "https://github.com/vyfor/icons/raw/master/icons/onyx/crystal.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",
|
||||
"d": "https://github.com/vyfor/icons/raw/master/icons/onyx/d.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",
|
||||
"dockerfile": "https://github.com/vyfor/icons/raw/master/icons/onyx/docker.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",
|
||||
"environment file": "https://github.com/vyfor/icons/raw/master/icons/onyx/gear.png",
|
||||
"fantom": "https://avatars.githubusercontent.com/u/54911692",
|
||||
"fortran": "https://github.com/vyfor/icons/raw/master/icons/onyx/fortran.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",
|
||||
"glsl": "https://github.com/vyfor/icons/raw/master/icons/onyx/opengl.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",
|
||||
"groovy": "https://github.com/vyfor/icons/raw/master/icons/onyx/groovy.png",
|
||||
"hare": "https://harelang.org/mascot.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 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",
|
||||
"html": "https://github.com/vyfor/icons/raw/master/icons/onyx/html.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",
|
||||
"java": "https://github.com/vyfor/icons/raw/master/icons/onyx/java.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",
|
||||
"json": "https://github.com/vyfor/icons/raw/master/icons/onyx/json.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",
|
||||
"latex": "https://github.com/vyfor/icons/raw/master/icons/onyx/latex.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",
|
||||
"makefile": "https://github.com/vyfor/icons/raw/master/icons/onyx/diagnostics.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",
|
||||
"moonscript": "https://github.com/vyfor/icons/raw/master/icons/onyx/lua.png",
|
||||
"nelua": "https://nelua.io/assets/img/nelua-logo-64px.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",
|
||||
"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",
|
||||
"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",
|
||||
"pascal": "https://github.com/vyfor/icons/raw/master/icons/onyx/pascal.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",
|
||||
"pico-8": "https://www.lexaloffle.com/gfx/p8b_pico8.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",
|
||||
"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",
|
||||
"powershell": "https://github.com/vyfor/icons/raw/master/icons/onyx/powershell.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",
|
||||
"ring": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.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",
|
||||
"sass": "https://github.com/vyfor/icons/raw/master/icons/onyx/scss.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",
|
||||
"smallbasic": "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",
|
||||
"swift": "https://github.com/vyfor/icons/raw/master/icons/onyx/swift.png",
|
||||
"tcl": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png",
|
||||
"teal": "https://avatars.githubusercontent.com/u/62526430",
|
||||
"toml": "https://github.com/vyfor/icons/raw/master/icons/onyx/toml.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",
|
||||
"v": "https://github.com/vyfor/icons/raw/master/icons/onyx/v.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",
|
||||
"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",
|
||||
"wren": "https://avatars.githubusercontent.com/u/45213573",
|
||||
"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",
|
||||
"xtend": "https://github.com/vyfor/icons/raw/master/icons/onyx/java.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"
|
||||
}
|
||||
},
|
||||
"keybindings" : {
|
||||
|
||||
}
|
||||
"config": {
|
||||
"appID": "1335730393948749898",
|
||||
"doLanguageIcons": true,
|
||||
"iconBindings": {
|
||||
".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",
|
||||
"[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",
|
||||
"adept": "https://raw.github.com/AdeptLanguage/Adept/master/.github/README_logo.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",
|
||||
"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",
|
||||
"bend": "https://avatars.githubusercontent.com/u/92327702",
|
||||
"blueprint": "https://github.com/vyfor/icons/raw/master/icons/onyx/controller.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",
|
||||
"c": "https://github.com/vyfor/icons/raw/master/icons/onyx/c.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",
|
||||
"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",
|
||||
"crystal": "https://github.com/vyfor/icons/raw/master/icons/onyx/crystal.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",
|
||||
"d": "https://github.com/vyfor/icons/raw/master/icons/onyx/d.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",
|
||||
"dockerfile": "https://github.com/vyfor/icons/raw/master/icons/onyx/docker.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",
|
||||
"environment file": "https://github.com/vyfor/icons/raw/master/icons/onyx/gear.png",
|
||||
"fantom": "https://avatars.githubusercontent.com/u/54911692",
|
||||
"fortran": "https://github.com/vyfor/icons/raw/master/icons/onyx/fortran.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",
|
||||
"glsl": "https://github.com/vyfor/icons/raw/master/icons/onyx/opengl.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",
|
||||
"groovy": "https://github.com/vyfor/icons/raw/master/icons/onyx/groovy.png",
|
||||
"hare": "https://harelang.org/mascot.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 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",
|
||||
"html": "https://github.com/vyfor/icons/raw/master/icons/onyx/html.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",
|
||||
"java": "https://github.com/vyfor/icons/raw/master/icons/onyx/java.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",
|
||||
"json": "https://github.com/vyfor/icons/raw/master/icons/onyx/json.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",
|
||||
"latex": "https://github.com/vyfor/icons/raw/master/icons/onyx/latex.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",
|
||||
"makefile": "https://github.com/vyfor/icons/raw/master/icons/onyx/diagnostics.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",
|
||||
"moonscript": "https://github.com/vyfor/icons/raw/master/icons/onyx/lua.png",
|
||||
"nelua": "https://nelua.io/assets/img/nelua-logo-64px.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",
|
||||
"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",
|
||||
"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",
|
||||
"pascal": "https://github.com/vyfor/icons/raw/master/icons/onyx/pascal.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",
|
||||
"pico-8": "https://www.lexaloffle.com/gfx/p8b_pico8.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",
|
||||
"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",
|
||||
"powershell": "https://github.com/vyfor/icons/raw/master/icons/onyx/powershell.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",
|
||||
"ring": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.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",
|
||||
"sass": "https://github.com/vyfor/icons/raw/master/icons/onyx/scss.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",
|
||||
"smallbasic": "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",
|
||||
"swift": "https://github.com/vyfor/icons/raw/master/icons/onyx/swift.png",
|
||||
"tcl": "https://github.com/vyfor/icons/raw/master/icons/onyx/text.png",
|
||||
"teal": "https://avatars.githubusercontent.com/u/62526430",
|
||||
"toml": "https://github.com/vyfor/icons/raw/master/icons/onyx/toml.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",
|
||||
"v": "https://github.com/vyfor/icons/raw/master/icons/onyx/v.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",
|
||||
"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",
|
||||
"wren": "https://avatars.githubusercontent.com/u/45213573",
|
||||
"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",
|
||||
"xtend": "https://github.com/vyfor/icons/raw/master/icons/onyx/java.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"
|
||||
}
|
||||
},
|
||||
"keybindings": {}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "discordRPCplugin.hpp"
|
||||
|
||||
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
|
||||
#else
|
||||
#define dcRPC_THREADED 0
|
||||
@@ -9,11 +9,11 @@ using json = nlohmann::json;
|
||||
|
||||
namespace ecode {
|
||||
|
||||
Plugin* DiscordRPCplugin::New( PluginManager* pluginManager) {
|
||||
Plugin* DiscordRPCplugin::New( PluginManager* pluginManager ) {
|
||||
return eeNew( DiscordRPCplugin, ( pluginManager, false ) );
|
||||
}
|
||||
|
||||
Plugin* DiscordRPCplugin::NewSync( PluginManager* pluginManager) {
|
||||
Plugin* DiscordRPCplugin::NewSync( PluginManager* pluginManager ) {
|
||||
return eeNew( DiscordRPCplugin, ( pluginManager, true ) );
|
||||
}
|
||||
|
||||
@@ -33,28 +33,27 @@ DiscordRPCplugin::DiscordRPCplugin( PluginManager* pluginManager, bool sync ) :
|
||||
DiscordRPCplugin::~DiscordRPCplugin() {
|
||||
waitUntilLoaded();
|
||||
mShuttingDown = true;
|
||||
|
||||
}
|
||||
void DiscordRPCplugin::load( PluginManager* pluginManager ) {
|
||||
Clock clock;
|
||||
AtomicBoolScopedOp loading( mLoading, true );
|
||||
|
||||
|
||||
pluginManager->subscribeMessages( this,
|
||||
[this]( const auto& notification ) -> PluginRequestHandle {
|
||||
return processMessage( notification );
|
||||
} );
|
||||
|
||||
|
||||
std::vector<std::string> paths;
|
||||
std::string path( pluginManager->getResourcesPath() + "plugins/discordRPC.json" );
|
||||
if ( FileSystem::fileExists( path ) )
|
||||
paths.emplace_back( path );
|
||||
path = pluginManager->getPluginsPath() + "discordRPC.json";
|
||||
if ( FileSystem::fileExists( path ) ||
|
||||
FileSystem::fileWrite(path, "{\n \"config\":{},\n \"keybindings\":{}\n}\n") ) {
|
||||
mConfigPath = path;
|
||||
paths.emplace_back( path );
|
||||
}
|
||||
std::string data;
|
||||
FileSystem::fileWrite( path, "{\n \"config\":{},\n \"keybindings\":{}\n}\n" ) ) {
|
||||
mConfigPath = path;
|
||||
paths.emplace_back( path );
|
||||
}
|
||||
std::string data;
|
||||
if ( !FileSystem::fileGet( path, data ) )
|
||||
return;
|
||||
mConfigHash = String::hash( data );
|
||||
@@ -81,7 +80,12 @@ void DiscordRPCplugin::load( PluginManager* pluginManager ) {
|
||||
mIPC.mcClientID = "1335730393948749898";
|
||||
updateConfigFile = true;
|
||||
}
|
||||
|
||||
if ( config.contains( "doLanguageIcons" ) ) {
|
||||
mcDoLangIcon = config.value( "doLanguageIcons", true );
|
||||
} else {
|
||||
mIPC.mcClientID = true;
|
||||
updateConfigFile = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( updateConfigFile ) {
|
||||
@@ -91,13 +95,13 @@ void DiscordRPCplugin::load( PluginManager* pluginManager ) {
|
||||
mConfigHash = String::hash( newData );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mIPC.tryConnect();
|
||||
DiscordIPCActivity* a = mIPC.getActivity();
|
||||
a->largeImage = DISCORDRPC_DEFAULT_ICON;
|
||||
|
||||
mIPC.setActivity(*a);
|
||||
|
||||
|
||||
mIPC.setActivity( *a );
|
||||
|
||||
mReady = true;
|
||||
fireReadyCbs();
|
||||
setReady( clock.getElapsedTime() );
|
||||
@@ -109,38 +113,45 @@ PluginRequestHandle DiscordRPCplugin::processMessage( const PluginMessage& msg )
|
||||
std::string rpath = FileSystem::getRealPath( msg.asJSON()["folder"] );
|
||||
FileSystem::dirAddSlashAtEnd( 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: {
|
||||
mIPC.mUIReady = true;
|
||||
// Log::debug("dcPlugin: UI is ready!");
|
||||
if (mIPC.mIsReconnectScheduled) {
|
||||
Log::debug("Running scheduled reconnect");
|
||||
// Log::debug("dcPlugin: UI is ready!");
|
||||
if ( mIPC.mIsReconnectScheduled ) {
|
||||
Log::debug( "Running scheduled reconnect" );
|
||||
mIPC.tryConnect();
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return PluginRequestHandle::empty();
|
||||
}
|
||||
|
||||
void DiscordRPCplugin::onRegisterDocument( TextDocument* doc ){
|
||||
doc->setCommand( "discordrpc-reconnect", [this] {
|
||||
mIPC.reconnect();
|
||||
} );
|
||||
void DiscordRPCplugin::onRegisterEditor( UICodeEditor* editor ) {
|
||||
editor->addUnlockedCommands( { "discordrpc-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 ) {
|
||||
listeners.push_back( editor->on( Event::OnFocus, [this, editor]( const Event* ) {
|
||||
// `this` in the scope of the lambda is the parent `DiscordRPCplugin`
|
||||
|
||||
|
||||
auto& doc = editor->getDocument();
|
||||
if (!doc.hasFilepath()) { return; }
|
||||
|
||||
if ( !doc.hasFilepath() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto filename = doc.getFilename();
|
||||
|
||||
|
||||
if ( filename != mLastFile ) {
|
||||
this->mLastFile = filename;
|
||||
|
||||
@@ -149,27 +160,25 @@ void DiscordRPCplugin::onRegisterListeners( UICodeEditor* editor, std::vector<Ui
|
||||
|
||||
DiscordIPCActivity* a = this->mIPC.getActivity();
|
||||
|
||||
if (!mProjectName.empty())
|
||||
a->details = String::format(i18n( "dc_workspace", "Working on %s" ).toUtf8(),
|
||||
mProjectName);
|
||||
a->state = String::format(i18n( "dc_editing", "Editing %s, a %s file" ).toUtf8(),
|
||||
filename, doc.getSyntaxDefinition().getLanguageName() );
|
||||
if ( !mProjectName.empty() )
|
||||
a->details = String::format( i18n( "dc_workspace", "Working on %s" ).toUtf8(),
|
||||
mProjectName );
|
||||
a->state = String::format( i18n( "dc_editing", "Editing %s, a %s file" ).toUtf8(),
|
||||
filename, doc.getSyntaxDefinition().getLanguageName() );
|
||||
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();
|
||||
if (!name.empty()) {
|
||||
a->largeImage = mcLangBindings.value(name, DISCORDRPC_DEFAULT_ICON);
|
||||
if ( !name.empty() && mcDoLangIcon ) {
|
||||
a->largeImage = mcLangBindings.value( name, DISCORDRPC_DEFAULT_ICON );
|
||||
}
|
||||
|
||||
this->mIPC.setActivity( *a );
|
||||
}
|
||||
|
||||
} ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace ecode
|
||||
@@ -4,10 +4,10 @@
|
||||
#include "../plugin.hpp"
|
||||
#include "../pluginmanager.hpp"
|
||||
|
||||
#include <eepp/system/threadpool.hpp>
|
||||
#include <eepp/system/mutex.hpp>
|
||||
#include <eepp/system/filesystem.hpp>
|
||||
#include <eepp/system/mutex.hpp>
|
||||
#include <eepp/system/scopedop.hpp>
|
||||
#include <eepp/system/threadpool.hpp>
|
||||
|
||||
#include "sdk/ipc.hpp"
|
||||
|
||||
@@ -18,52 +18,53 @@ using namespace EE::System;
|
||||
using namespace EE::UI;
|
||||
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 {
|
||||
|
||||
class DiscordRPCplugin : public PluginBase {
|
||||
public:
|
||||
static PluginDefinition Definition() {
|
||||
return {
|
||||
"discrdrpc",
|
||||
"Discord Rich Presence",
|
||||
"Show your friends what you are up to through the discord Rich Presence system",
|
||||
DiscordRPCplugin::New,
|
||||
{ 0, 0, 0 },
|
||||
DiscordRPCplugin::NewSync };
|
||||
}
|
||||
|
||||
static Plugin* New( PluginManager* pluginManager );
|
||||
|
||||
static Plugin* NewSync( PluginManager* pluginManager );
|
||||
|
||||
virtual ~DiscordRPCplugin() override;
|
||||
|
||||
std::string getId() override { return Definition().id; }
|
||||
public:
|
||||
static PluginDefinition Definition() {
|
||||
return { "discrdrpc",
|
||||
"Discord Rich Presence",
|
||||
"Show your friends what you are up to through the discord Rich Presence system",
|
||||
DiscordRPCplugin::New,
|
||||
{ 0, 0, 0 },
|
||||
DiscordRPCplugin::NewSync };
|
||||
}
|
||||
|
||||
std::string getTitle() override { return Definition().name; }
|
||||
|
||||
std::string getDescription() override { return Definition().description; }
|
||||
|
||||
protected:
|
||||
DiscordIPC mIPC;
|
||||
std::string mLastFile;
|
||||
std::string mProjectName;
|
||||
nlohmann::json mcLangBindings;
|
||||
|
||||
void load ( PluginManager* pluginManager );
|
||||
|
||||
PluginRequestHandle processMessage( const PluginMessage& msg );
|
||||
|
||||
virtual void onRegisterListeners(UICodeEditor* editor, std::vector<Uint32>& listeners ) override;
|
||||
virtual void onRegisterDocument( TextDocument* doc ) override;
|
||||
|
||||
|
||||
DiscordRPCplugin( PluginManager* pluginManager, bool sync );
|
||||
static Plugin* New( PluginManager* pluginManager );
|
||||
|
||||
static Plugin* NewSync( PluginManager* pluginManager );
|
||||
|
||||
virtual ~DiscordRPCplugin() override;
|
||||
|
||||
std::string getId() override { return Definition().id; }
|
||||
|
||||
std::string getTitle() override { return Definition().name; }
|
||||
|
||||
std::string getDescription() override { return Definition().description; }
|
||||
|
||||
protected:
|
||||
DiscordIPC mIPC;
|
||||
std::string mLastFile;
|
||||
std::string mProjectName;
|
||||
nlohmann::json mcLangBindings;
|
||||
bool mcDoLangIcon;
|
||||
|
||||
void load( PluginManager* pluginManager );
|
||||
|
||||
PluginRequestHandle processMessage( const PluginMessage& msg );
|
||||
|
||||
virtual void onRegisterListeners( UICodeEditor* editor,
|
||||
std::vector<Uint32>& listeners ) override;
|
||||
virtual void onRegisterEditor( UICodeEditor* editor ) override;
|
||||
virtual void onUnregisterEditor( UICodeEditor* editor ) override;
|
||||
|
||||
DiscordRPCplugin( PluginManager* pluginManager, bool sync );
|
||||
};
|
||||
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
#endif // ECODE_DISCORDRPCPLUGIN_HPP
|
||||
@@ -3,19 +3,19 @@
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
|
||||
#include <eepp/system/log.hpp>
|
||||
#include <eepp/scene/scenemanager.hpp>
|
||||
#include <eepp/system/log.hpp>
|
||||
#include <eepp/ui/uiscenenode.hpp>
|
||||
|
||||
#if defined( EE_PLATFORM_POSIX )
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#if defined( EE_PLATFORM_POSIX )
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#elif EE_PLATFORM == EE_PLATFORM_WIN
|
||||
#ifndef WIN32LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#ifndef WIN32LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
using namespace EE::System;
|
||||
@@ -27,303 +27,320 @@ DiscordIPC::DiscordIPC() {
|
||||
}
|
||||
|
||||
bool DiscordIPC::tryConnect() {
|
||||
#if EE_PLATFORM == EE_PLATFORM_WIN
|
||||
std::string basePath = "\\\\.\\pipe\\";
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
std::string ipcPath = basePath + "discord-ipc-" + std::to_string(i);
|
||||
|
||||
// Check if exists
|
||||
DWORD attributes = GetFileAttributes(ipcPath.c_str());
|
||||
if (attributes != INVALID_FILE_ATTRIBUTES) {
|
||||
Log::debug("dcIPC: IPC path found! - %s", ipcPath);
|
||||
mIpcPath = ipcPath;
|
||||
|
||||
mSocket = CreateFile(mIpcPath.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
0, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
|
||||
doHandshake();
|
||||
return true;
|
||||
}
|
||||
#if EE_PLATFORM == EE_PLATFORM_WIN
|
||||
std::string basePath = "\\\\.\\pipe\\";
|
||||
|
||||
for ( int i = 0; i < 10; ++i ) {
|
||||
std::string ipcPath = basePath + "discord-ipc-" + std::to_string( i );
|
||||
|
||||
// Check if exists
|
||||
DWORD attributes = GetFileAttributes( ipcPath.c_str() );
|
||||
if ( attributes != INVALID_FILE_ATTRIBUTES ) {
|
||||
Log::debug( "dcIPC: IPC path found! - %s", ipcPath );
|
||||
mIpcPath = ipcPath;
|
||||
|
||||
mSocket = CreateFile( mIpcPath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr,
|
||||
OPEN_EXISTING, 0, nullptr );
|
||||
|
||||
doHandshake();
|
||||
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();
|
||||
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();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return false; // Discord not supported by other OS (if it is, TBA)
|
||||
}
|
||||
|
||||
void DiscordIPC::doHandshake() {
|
||||
json j = {
|
||||
{"v", 1},
|
||||
{"client_id", mcClientID}
|
||||
};
|
||||
|
||||
sendPacket(DiscordIPCOpcodes::Handshake, j);
|
||||
json j = { { "v", 1 }, { "client_id", mcClientID } };
|
||||
|
||||
sendPacket( DiscordIPCOpcodes::Handshake, j );
|
||||
}
|
||||
|
||||
void DiscordIPC::clearActivity() {
|
||||
json j = {
|
||||
{"cmd", "SET_ACTIVITY"},
|
||||
{"args", {
|
||||
{"pid", 0},
|
||||
{"activity", nullptr}
|
||||
}},
|
||||
{"nonce", "-"} // TODO: Null nonce for dev purposes, change to UUIDV4 in finished product
|
||||
};
|
||||
sendPacket(DiscordIPCOpcodes::Frame, j);
|
||||
{ "cmd", "SET_ACTIVITY" },
|
||||
{ "args", { { "pid", 0 }, { "activity", nullptr } } },
|
||||
{ "nonce", "-" } // TODO: Null nonce for dev purposes, change to UUIDV4 in finished product
|
||||
};
|
||||
sendPacket( DiscordIPCOpcodes::Frame, j );
|
||||
}
|
||||
|
||||
void DiscordIPC::setActivity( DiscordIPCActivity a ) {
|
||||
json aj = {
|
||||
{"type", static_cast<int>(a.type)},
|
||||
{"instance", true},
|
||||
};
|
||||
|
||||
if (!a.state.empty())
|
||||
aj["state"] = a.state;
|
||||
if (!a.details.empty())
|
||||
aj["details"] = a.details;
|
||||
{ "type", static_cast<int>( a.type ) },
|
||||
{ "instance", true },
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
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 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()){
|
||||
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()){
|
||||
}
|
||||
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 ( !b.empty() ) {
|
||||
aj["buttons"] = b;
|
||||
}
|
||||
|
||||
json j{ { "cmd", "SET_ACTIVITY" },
|
||||
{ "args",
|
||||
{
|
||||
{ "pid", mPID },
|
||||
{ "activity", aj },
|
||||
} },
|
||||
{ "nonce", "-" } };
|
||||
|
||||
mActivity = a;
|
||||
sendPacket(DiscordIPCOpcodes::Frame, j);
|
||||
sendPacket( DiscordIPCOpcodes::Frame, j );
|
||||
}
|
||||
|
||||
void DiscordIPC::sendPacket(DiscordIPCOpcodes opcode, json j) {
|
||||
if (!std::filesystem::exists(mIpcPath)) { reconnect(); return; }
|
||||
|
||||
const std::string packet = j.dump();
|
||||
std::vector<uint8_t> data;
|
||||
|
||||
void DiscordIPC::sendPacket( DiscordIPCOpcodes opcode, json j ) {
|
||||
if ( !std::filesystem::exists( mIpcPath ) ) {
|
||||
reconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string packet = j.dump();
|
||||
std::vector<uint8_t> data;
|
||||
|
||||
// Add correct ammount of padding for the protocol
|
||||
union {
|
||||
uint32_t value;
|
||||
uint8_t bytes[4];
|
||||
} bytes;
|
||||
union {
|
||||
uint32_t value;
|
||||
uint8_t bytes[4];
|
||||
} bytes;
|
||||
|
||||
bytes.value = opcode;
|
||||
for (int i = 0; i <= 3; ++i) {
|
||||
data.push_back(bytes.bytes[i]);
|
||||
}
|
||||
bytes.value = opcode;
|
||||
for ( int i = 0; i <= 3; ++i ) {
|
||||
data.push_back( bytes.bytes[i] );
|
||||
}
|
||||
|
||||
bytes.value = packet.length();
|
||||
for (int i = 0; i <= 3; ++i) {
|
||||
data.push_back(bytes.bytes[i]);
|
||||
}
|
||||
bytes.value = packet.length();
|
||||
for ( int i = 0; i <= 3; ++i ) {
|
||||
data.push_back( bytes.bytes[i] );
|
||||
}
|
||||
|
||||
for (char c : packet) {
|
||||
data.push_back(static_cast<uint8_t>(c));
|
||||
}
|
||||
|
||||
// Log::debug("Packet is: %s (%u)", j.dump(4), data.size());
|
||||
|
||||
// std::stringstream ss;
|
||||
// for (uint8_t byte : data) {
|
||||
// ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte) << " ";
|
||||
// }
|
||||
for ( char c : packet ) {
|
||||
data.push_back( static_cast<uint8_t>( c ) );
|
||||
}
|
||||
|
||||
// Log::debug(ss.str());
|
||||
|
||||
#if defined( EE_PLATFORM_POSIX )
|
||||
|
||||
ssize_t bytesSent = send(mSocket, data.data(), data.size(), 0);
|
||||
if (bytesSent != data.size()) {
|
||||
Log::error("dcIPC: Failed to send all data to Unix socket: %zu bytes sent, %zu bytes expected", bytesSent, data.size());
|
||||
reconnect();
|
||||
return;
|
||||
}
|
||||
// Log::debug("Packet is: %s (%u)", j.dump(4), data.size());
|
||||
|
||||
|
||||
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));
|
||||
|
||||
char buffer[1024];
|
||||
ssize_t bytesRead = recv(mSocket, buffer, sizeof(buffer), 0);
|
||||
|
||||
// Log::debug("dcIPC: RECV: %s", buffer);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
DWORD bytesRead;
|
||||
char buffer[1024];
|
||||
if ( !ReadFile(mSocket, buffer, 1024, &bytesRead, nullptr ) ) {
|
||||
Log::error("dcIPC: Error reading pipe!!");
|
||||
reconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
// Log::debug("dcIPC: RECV: %s", buffer);
|
||||
// std::stringstream ss;
|
||||
// for (uint8_t byte : data) {
|
||||
// ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte) << " ";
|
||||
// }
|
||||
|
||||
#endif
|
||||
// Log::debug(ss.str());
|
||||
|
||||
#if defined( EE_PLATFORM_POSIX )
|
||||
|
||||
ssize_t bytesSent = send( mSocket, data.data(), data.size(), 0 );
|
||||
if ( bytesSent != data.size() ) {
|
||||
Log::error(
|
||||
"dcIPC: Failed to send all data to Unix socket: %zu bytes sent, %zu bytes expected",
|
||||
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 ) );
|
||||
|
||||
char buffer[1024];
|
||||
ssize_t bytesRead = recv( mSocket, buffer, sizeof( buffer ), 0 );
|
||||
|
||||
// Log::debug("dcIPC: RECV: %s", buffer);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
DWORD bytesRead;
|
||||
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
|
||||
}
|
||||
|
||||
void DiscordIPC::reconnect() {
|
||||
if (mReconnectLock) {Log::warning("dcIPC: Tried to call reconnect while locked"); return;}
|
||||
if (!mUIReady) { Log::debug("dcIPC: Scheduled a reconnect"); mIsReconnectScheduled = true; return; }
|
||||
if (mBackoffIndex < DISCORDIPC_BACKOFF_MAX) { mBackoffIndex++; }
|
||||
int delay = 5 + pow(2, mBackoffIndex);
|
||||
if ( mReconnectLock ) {
|
||||
Log::warning( "dcIPC: Tried to call reconnect while locked" );
|
||||
return;
|
||||
}
|
||||
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;
|
||||
|
||||
Log::warning("dcIPC: Waiting for reconnect delay of %us (%u/%u)", delay, mBackoffIndex, DISCORDIPC_BACKOFF_MAX);
|
||||
EE::Scene::SceneManager::instance()->getUISceneNode()
|
||||
->setTimeout( [this] {
|
||||
EE::Scene::SceneManager::instance()->getUISceneNode()
|
||||
->getThreadPool()->run( [this]{
|
||||
Log::info("dcIPC: Reconnecting...");
|
||||
mReconnectLock = false;
|
||||
if(tryConnect()){ mBackoffIndex = 0; }
|
||||
});
|
||||
}, Seconds(delay));
|
||||
|
||||
Log::warning( "dcIPC: Waiting for reconnect delay of %us (%u/%u)", delay, mBackoffIndex,
|
||||
DISCORDIPC_BACKOFF_MAX );
|
||||
EE::Scene::SceneManager::instance()->getUISceneNode()->setTimeout(
|
||||
[this] {
|
||||
EE::Scene::SceneManager::instance()->getUISceneNode()->getThreadPool()->run( [this] {
|
||||
Log::info( "dcIPC: Reconnecting..." );
|
||||
mReconnectLock = false;
|
||||
if ( tryConnect() ) {
|
||||
mBackoffIndex = 0;
|
||||
}
|
||||
} );
|
||||
},
|
||||
Seconds( delay ) );
|
||||
}
|
||||
|
||||
DiscordIPC::~DiscordIPC() {
|
||||
#if defined( EE_PLATFORM_POSIX )
|
||||
close(mSocket);
|
||||
#elif EE_PLATFORM == EE_PLATFORM_WIN
|
||||
CloseHandle(mSocket);
|
||||
#endif
|
||||
#if defined( EE_PLATFORM_POSIX )
|
||||
close( mSocket );
|
||||
#elif EE_PLATFORM == EE_PLATFORM_WIN
|
||||
CloseHandle( mSocket );
|
||||
#endif
|
||||
}
|
||||
@@ -3,81 +3,78 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
// 2^8 = 256s ~4.3min
|
||||
#define DISCORDIPC_BACKOFF_MAX 8
|
||||
#define DISCORDIPC_BACKOFF_MAX 8
|
||||
|
||||
enum DiscordIPCActivityTypes {
|
||||
Playing = 0,
|
||||
Listening = 2,
|
||||
Watching = 3,
|
||||
Competing = 5,
|
||||
Playing = 0,
|
||||
Listening = 2,
|
||||
Watching = 3,
|
||||
Competing = 5,
|
||||
};
|
||||
|
||||
struct DiscordIPCActivityButton {
|
||||
std::string label;
|
||||
std::string url;
|
||||
std::string label;
|
||||
std::string url;
|
||||
};
|
||||
|
||||
struct DiscordIPCActivity {
|
||||
DiscordIPCActivityTypes type = DiscordIPCActivityTypes::Playing;
|
||||
std::string state;
|
||||
std::string details;
|
||||
|
||||
time_t start = 0;
|
||||
time_t end = 0;
|
||||
|
||||
std::string largeImage;
|
||||
std::string largeText;
|
||||
std::string smallImage;
|
||||
std::string smallText;
|
||||
|
||||
DiscordIPCActivityButton buttons[2];
|
||||
DiscordIPCActivityTypes type = DiscordIPCActivityTypes::Playing;
|
||||
std::string state;
|
||||
std::string details;
|
||||
|
||||
time_t start = 0;
|
||||
time_t end = 0;
|
||||
|
||||
std::string largeImage;
|
||||
std::string largeText;
|
||||
std::string smallImage;
|
||||
std::string smallText;
|
||||
|
||||
// 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 {
|
||||
Handshake = 0,
|
||||
Frame,
|
||||
Close,
|
||||
Ping,
|
||||
Pong
|
||||
};
|
||||
enum DiscordIPCOpcodes { Handshake = 0, Frame, Close, Ping, Pong };
|
||||
|
||||
class DiscordIPC {
|
||||
public:
|
||||
|
||||
virtual ~DiscordIPC();
|
||||
DiscordIPC();
|
||||
public:
|
||||
virtual ~DiscordIPC();
|
||||
DiscordIPC();
|
||||
|
||||
// false - FileNotFound/OSNotSupported
|
||||
// true - Success
|
||||
bool tryConnect();
|
||||
void reconnect();
|
||||
|
||||
void setActivity( DiscordIPCActivity a );
|
||||
DiscordIPCActivity *getActivity() { return &mActivity; }
|
||||
void clearActivity();
|
||||
|
||||
bool mUIReady;
|
||||
bool mIsReconnectScheduled = false; // If we fail to load bofore UI initialises we call reconnect after init
|
||||
|
||||
//Configurables
|
||||
std::string mcClientID;
|
||||
protected:
|
||||
std::string mIpcPath;
|
||||
int mPID;
|
||||
|
||||
int mBackoffIndex;
|
||||
int mReconnectLock = false; // Not quite a mutex because I want to lock any attempts if one is already waiting
|
||||
|
||||
DiscordIPCActivity mActivity;
|
||||
|
||||
|
||||
#if defined( EE_PLATFORM_POSIX )
|
||||
int mSocket;
|
||||
#elif EE_PLATFORM == EE_PLATFORM_WIN
|
||||
void* mSocket;
|
||||
#endif
|
||||
|
||||
void doHandshake();
|
||||
|
||||
void sendPacket( DiscordIPCOpcodes opcode, nlohmann::json j );
|
||||
// false - FileNotFound/OSNotSupported
|
||||
// true - Success
|
||||
bool tryConnect();
|
||||
void reconnect();
|
||||
|
||||
void setActivity( DiscordIPCActivity a );
|
||||
DiscordIPCActivity* getActivity() { return &mActivity; }
|
||||
void clearActivity();
|
||||
|
||||
bool mUIReady;
|
||||
bool mIsReconnectScheduled =
|
||||
false; // If we fail to load bofore UI initialises we call reconnect after init
|
||||
|
||||
// Configurables
|
||||
std::string mcClientID;
|
||||
|
||||
protected:
|
||||
std::string mIpcPath;
|
||||
int mPID;
|
||||
|
||||
int mBackoffIndex;
|
||||
int mReconnectLock =
|
||||
false; // Not quite a mutex because I want to lock any attempts if one is already waiting
|
||||
|
||||
DiscordIPCActivity mActivity;
|
||||
|
||||
#if defined( EE_PLATFORM_POSIX )
|
||||
int mSocket;
|
||||
#elif EE_PLATFORM == EE_PLATFORM_WIN
|
||||
void* mSocket;
|
||||
#endif
|
||||
|
||||
void doHandshake();
|
||||
|
||||
void sendPacket( DiscordIPCOpcodes opcode, nlohmann::json j );
|
||||
};
|
||||
Reference in New Issue
Block a user