Unix functional setActivity(); working connection

This commit is contained in:
Bytequill
2025-02-04 21:10:29 +01:00
parent 0b25c118ef
commit 4dd6629b0b
2 changed files with 179 additions and 68 deletions

View File

@@ -1,14 +1,15 @@
#include "ipc.hpp"
#include <eepp/system/log.hpp>
#include <netinet/in.h>
using namespace EE::System;
using json = nlohmann::json;
DiscordIPC::DiscordIPC() {
mPID = Sys::getProcessID(); // Before we get to live testing stage, I assume plugin thread PID is fine
mPID = Sys::getProcessID();
mcClientID = "133573039394874989"; // TODO: Implement actual config reading
mcClientID = "1335730393948749898"; // TODO: Implement actual config reading
#if defined(__unix__) || defined(_APPLE__)
mSocket = -1;
@@ -88,7 +89,8 @@ bool DiscordIPC::tryConnect() {
close(mSocket);
return false;
}
doHandshake();
return true;
}
}
@@ -99,9 +101,7 @@ bool DiscordIPC::tryConnect() {
}
void DiscordIPC::doHandshake() {
json j;
j = json{
json j = {
{"v", 1},
{"client_id", mcClientID}
};
@@ -110,30 +110,126 @@ void DiscordIPC::doHandshake() {
}
void DiscordIPC::clearActivity() {
json j;
j = json{
{"cmd", "SET_ACTIVITY"},
{"args", {
{"pid",0},
{"activity", NULL}
},
{"nonce", "-"} // TODO: Null nonce for dev purposes, change to UUIDV4 in finished product
}};
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);
}
void DiscordIPC::setActivity( DiscordIPCActivity a ) {
json j;
// TODO, map out the request json
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;
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", "-"}
};
sendPacket(DiscordIPCOpcodes::Frame, j);
mActivity = a;
}
void DiscordIPC::sendPacket(DiscordIPCOpcodes opcode, json j) {
// TODO
Log::debug("Packet is: %s", j.dump(4)); // Packet json logging before we start sending to ipc
#if defined(__unix__) || defined(_APPLE__)
const std::string packet = j.dump();
std::vector<uint8_t> data;
// Conversion to little endian
union {
uint32_t value;
uint8_t bytes[4];
} bytes;
bytes.value = htonl(opcode);
for (int i = 3; i >= 0; --i) {
data.push_back(bytes.bytes[i]);
}
bytes.value = htonl(packet.length());
for (int i = 3; i >= 0; --i) {
data.push_back(bytes.bytes[i]);
}
for (char c : packet) {
data.push_back(static_cast<uint8_t>(c));
}
long unsigned int bytesSent = send(mSocket, data.data(), data.size(), 0);
if (bytesSent != data.size()) {
Log::error("Failed to send all data to Unix socket: %zu bytes sent, %zu bytes expected", bytesSent, 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);
// TODO: Implement nonce checking? (does it even really matter?)
//return bytesRead;
#endif
}
void DiscordIPC::reconnect() {

View File

@@ -1,4 +1,3 @@
#include <iostream>
#include <filesystem>
#include <vector>
@@ -8,59 +7,75 @@
#include <nlohmann/json.hpp>
#if defined(__unix__) || defined(_APPLE__)
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <sys/un.h>
#endif
enum DiscordIPCActivityTypes {
Playing = 0,
Listening = 2,
Watching = 3,
Competing = 5,
};
struct DiscordIPCActivityButton {
std::string label = "";
std::string url = "";
};
struct DiscordIPCActivity {
std::string state = "";
std::string details = "";
time_t start = NULL;
time_t stop = NULL;
std::string largeImage = "";
std::string largeText = "";
std::string smallImage = "";
std::string smallText = "";
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];
};
enum DiscordIPCOpcodes {
Handshake = 0,
Frame,
Close,
Ping,
Pong
Handshake = 0,
Frame,
Close,
Ping,
Pong
};
class DiscordIPC {
public:
virtual ~DiscordIPC();
DiscordIPC();
// false - FileNotFound/OSNotSupported
// true - Success
bool tryConnect();
void setActivity( DiscordIPCActivity a );
void clearActivity();
protected:
std::string mIpcPath;
int mPID;
//Configurables
std::string mcClientID;
#if defined(__unix__) || defined(_APPLE__)
int mSocket;
#endif
void doHandshake();
void reconnect();
void sendPacket( DiscordIPCOpcodes opcode, nlohmann::json j );
};
public:
virtual ~DiscordIPC();
DiscordIPC();
// false - FileNotFound/OSNotSupported
// true - Success
bool tryConnect();
void setActivity( DiscordIPCActivity a );
DiscordIPCActivity *getActivity() { return &mActivity; }
void clearActivity();
protected:
std::string mIpcPath;
int mPID;
DiscordIPCActivity mActivity;
//Configurables
std::string mcClientID;
#if defined(__unix__) || defined(_APPLE__)
int mSocket;
#endif
void doHandshake();
void reconnect();
void sendPacket( DiscordIPCOpcodes opcode, nlohmann::json j );
};