Created
August 20, 2021 22:22
-
-
Save AndrewBelt/2b386003f949b79f73e9f21c64983f3f to your computer and use it in GitHub Desktop.
Discord activity updater
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if defined ARCH_LIN || defined ARCH_MAC | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <sys/un.h> | |
#endif | |
#if defined ARCH_WIN | |
#include <fcntl.h> | |
#endif | |
#include <jansson.h> | |
int sendJson(int fd, int32_t opcode, json_t* j) { | |
// Encode payload | |
char* json = json_dumps(j, 0); | |
if (!json) | |
return 1; | |
DEFER({free(json);}); | |
size_t len = strlen(json); | |
// Send header | |
int32_t header[2] = {opcode, int32_t(len)}; | |
if (write(fd, header, sizeof(header)) != sizeof(header)) | |
return 1; | |
// Send payload | |
if (write(fd, json, len) != ssize_t(len)) | |
return 1; | |
return 0; | |
} | |
json_t* receiveJson(int fd) { | |
// Receive header | |
int32_t header[2]; | |
if (read(fd, header, sizeof(header)) != sizeof(header)) | |
return NULL; | |
// Receive payload | |
size_t len = header[1]; | |
char json[len]; | |
if (read(fd, json, len) != ssize_t(len)) | |
return NULL; | |
// DEBUG("Payload: %.*s", int(len), json); | |
// Parse payload | |
json_t* j = json_loadb(json, len, 0, NULL); | |
return j; | |
} | |
void discordUpdateActivity() { | |
// Open socket | |
#if defined ARCH_LIN || defined ARCH_MAC | |
int fd = socket(AF_UNIX, SOCK_STREAM, 0); | |
if (fd < 0) { | |
WARN("Could not open Discord socket"); | |
return; | |
} | |
DEFER({close(fd);}); | |
// Get socket path | |
const char* env = getenv("XDG_RUNTIME_DIR"); | |
if (!env) | |
env = getenv("TMPDIR"); | |
if (!env) | |
env = getenv("TMP"); | |
if (!env) | |
env = getenv("TEMP"); | |
if (!env) | |
env = "/tmp"; | |
std::string path = std::string() + env + "/discord-ipc-0"; | |
// Connect to socket | |
struct sockaddr_un addr; | |
addr.sun_family = AF_UNIX; | |
snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path.c_str()); | |
if (connect(fd, (struct sockaddr*) &addr, sizeof(addr))) { | |
// Fail silently since this just means Discord isn't open. | |
// WARN("Could not bind Discord socket"); | |
return; | |
} | |
#endif | |
#if defined ARCH_WIN | |
const char* path = "\\\\?\\pipe\\discord-ipc-0"; | |
int fd = open(path, O_RDWR | O_APPEND); | |
if (fd < 0) { | |
// Fail silently since this just means Discord isn't open. | |
// WARN("Could not open Discord socket"); | |
return; | |
} | |
DEFER({close(fd);}); | |
#endif | |
// Send handshake | |
json_t* handshakeJ = json_object(); | |
json_object_set(handshakeJ, "v", json_integer(1)); | |
json_object_set(handshakeJ, "client_id", json_string(CLIENT_ID)); | |
DEFER({json_decref(handshakeJ);}); | |
if (sendJson(fd, 0, handshakeJ)) { | |
WARN("Could not request Discord handshake"); | |
return; | |
} | |
// Receive handshake response | |
json_t* handshakeResJ = receiveJson(fd); | |
if (!handshakeResJ) { | |
WARN("Could not receive Discord handshake response"); | |
return; | |
} | |
DEFER({json_decref(handshakeResJ);}); | |
// Send activity | |
json_t* payloadJ = json_object(); | |
json_object_set(payloadJ, "cmd", json_string("SET_ACTIVITY")); | |
json_object_set(payloadJ, "nonce", json_string(std::to_string(random::u64()).c_str())); | |
{ | |
json_t* argsJ = json_object(); | |
json_object_set(argsJ, "pid", json_integer(getpid())); | |
{ | |
json_t* activityJ = json_object(); | |
{ | |
json_t* timestampsJ = json_object(); | |
json_object_set(timestampsJ, "start", json_integer(system::getUnixTime())); | |
json_object_set(activityJ, "timestamps", timestampsJ); | |
} | |
json_object_set(argsJ, "activity", activityJ); | |
} | |
json_object_set(payloadJ, "args", argsJ); | |
} | |
DEFER({json_decref(payloadJ);}); | |
if (sendJson(fd, 1, payloadJ)) { | |
WARN("Could not set activity on Discord"); | |
return; | |
} | |
// Receive activity response | |
json_t* payloadResJ = receiveJson(fd); | |
if (!payloadResJ) { | |
WARN("Could not receive Discord activity response"); | |
return; | |
} | |
DEFER({json_decref(payloadResJ);}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment