Skip to content

Commit a24cf50

Browse files
authored
Merge pull request #219 from OpenBrickProtocolFoundation/use_discord_social_sdk
Feat: Use discord social sdk
2 parents 12240a1 + f27dcd1 commit a24cf50

File tree

24 files changed

+390
-455
lines changed

24 files changed

+390
-455
lines changed

.github/workflows/musl.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
- name: Install dependencies
3333
run: |
3434
apk update
35-
apk add wget meson ca-certificates samurai git openssl-dev openssl pkgconf sdl2 sdl2-dev sdl2_mixer-dev sdl2_ttf-dev sdl2_mixer-dev sdl2_image-dev dbus-dev patchelf ${{ ( matrix.config.use-clang == true ) && 'clang19' || 'gcc g++' }} ${{ ( matrix.config.use-clang == true && matrix.config.use-clang_stdlib == true ) && 'libc++ libc++-dev llvm-libunwind llvm-libunwind-dev ' || '' }}
35+
apk add wget meson ca-certificates samurai git openssl-dev openssl pkgconf sdl2 sdl2-dev sdl2_mixer-dev sdl2_ttf-dev sdl2_mixer-dev sdl2_image-dev dbus-dev ${{ ( matrix.config.use-clang == true ) && 'clang19' || 'gcc g++' }} ${{ ( matrix.config.use-clang == true && matrix.config.use-clang_stdlib == true ) && 'libc++ libc++-dev llvm-libunwind llvm-libunwind-dev ' || '' }}
3636
echo "CC=${{ matrix.config.use-clang == true && 'clang-19' || 'gcc' }}" >> "$GITHUB_ENV"
3737
echo "CXX=${{ matrix.config.use-clang == true && 'clang++-19' || 'g++' }}" >> "$GITHUB_ENV"
3838

io.github.openbrickprotocolfoundation.oopetris.yml

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,6 @@ runtime-version: '24.08'
44
sdk: org.freedesktop.Sdk
55
command: oopetris
66
modules:
7-
#TODO: remove after discord sets SONAME
8-
- name: patchelf
9-
buildsystem: simple
10-
sources:
11-
- type: archive
12-
url: https://github.com/NixOS/patchelf/releases/download/0.18.0/patchelf-0.18.0.tar.gz
13-
sha256: 64de10e4c6b8b8379db7e87f58030f336ea747c0515f381132e810dbf84a86e7
14-
build-commands:
15-
- ./configure --prefix=/app
16-
- make
17-
- make install
18-
197
- name: OOPetris
208
buildsystem: meson
219
config-opts:
@@ -42,13 +30,6 @@ cleanup:
4230
- /include
4331
- /lib/pkgconfig
4432
- /share/pkgconfig
45-
## all for the patchelf executable
46-
#TODO: remove after removing patchelf build
47-
- /bin/patchelf
48-
- /lib/debug
49-
- /share/doc
50-
- /share/man
51-
- /share/zsh
5233

5334
finish-args:
5435
- --socket=x11

src/discord/core.cpp

Lines changed: 142 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11

2-
#include <core/helper/magic_enum_wrapper.hpp>
32
#include <core/helper/utils.hpp>
43

54
#include "./core.hpp"
@@ -18,165 +17,222 @@
1817
}
1918
}
2019

21-
DiscordInstance::DiscordInstance(discord::Core* core) : m_core{ core }, m_current_user{ nullptr } { }
20+
DiscordInstance::DiscordInstance()
21+
: m_current_user{ discordpp::UserHandle::nullobj },
22+
m_status{ DiscordStatus::Starting } {
2223

23-
void DiscordInstance::after_setup() {
24-
m_core->UserManager().OnCurrentUserUpdate.Connect([this]() {
25-
auto* user = new discord::User; // NOLINT(cppcoreguidelines-owning-memory)
26-
this->m_core->UserManager().GetCurrentUser(user);
27-
this->m_current_user.reset(user);
28-
spdlog::info(
29-
"Current user updated: {}#{}", this->m_current_user->GetUsername(),
30-
this->m_current_user->GetDiscriminator()
31-
);
32-
});
33-
34-
auto result = m_core->ActivityManager().RegisterCommand(constants::discord::platform_dependent_launch_arguments);
35-
if (result != discord::Result::Ok) {
36-
spdlog::warn("ActivityManager: Failed to RegisterCommand: {}", magic_enum::enum_name(result));
37-
};
38-
}
39-
40-
[[nodiscard]] helper::expected<DiscordInstance, std::string> DiscordInstance::initialize() {
41-
42-
discord::Core* core{};
43-
auto result = discord::Core::Create(constants::discord::client_id, DiscordCreateFlags_Default, &core);
44-
if (core == nullptr) {
45-
return helper::unexpected<std::string>{
46-
fmt::format("Failed to instantiate discord core: {}", magic_enum::enum_name(result))
47-
};
48-
}
49-
50-
51-
core->SetLogHook(
52-
#if !defined(NDEBUG)
53-
discord::LogLevel::Debug
54-
#else
55-
discord::LogLevel::Error
56-
#endif
57-
,
58-
[](discord::LogLevel level, const char* message) {
59-
switch (level) {
60-
case discord::LogLevel::Error:
24+
m_client.AddLogCallback(
25+
[](std::string message, discordpp::LoggingSeverity severity) -> void {
26+
switch (severity) {
27+
case discordpp::LoggingSeverity::Error:
6128
spdlog::error("DISCORD SDK: {}", message);
6229
break;
63-
case discord::LogLevel::Warn:
30+
case discordpp::LoggingSeverity::Warning:
6431
spdlog::warn("DISCORD SDK: {}", message);
6532
break;
66-
case discord::LogLevel::Info:
33+
case discordpp::LoggingSeverity::Info:
6734
spdlog::info("DISCORD SDK: {}", message);
6835
break;
69-
case discord::LogLevel::Debug:
36+
case discordpp::LoggingSeverity::Verbose:
7037
spdlog::debug("DISCORD SDK: {}", message);
7138
break;
39+
case discordpp::LoggingSeverity::None:
40+
break;
41+
}
42+
},
43+
#if !defined(NDEBUG)
44+
discordpp::LoggingSeverity::Verbose
45+
#else
46+
discordpp::LoggingSeverity::Error
47+
#endif
48+
);
49+
50+
51+
m_client.SetStatusChangedCallback(
52+
[this](discordpp::Client::Status status, discordpp::Client::Error error, int32_t error_detail) -> void {
53+
if (error != discordpp::Client::Error::None) {
54+
this->m_status = DiscordStatus::Error;
55+
spdlog::error(
56+
"Connection Error: {} - Details: {}", discordpp::Client::ErrorToString(error), error_detail
57+
);
58+
return;
59+
}
60+
61+
if (status == discordpp::Client::Status::Ready) {
62+
this->m_status = DiscordStatus::Ok;
63+
this->after_ready();
64+
return;
7265
}
7366
}
7467
);
7568

76-
return DiscordInstance{ core };
69+
m_client.SetApplicationId(constants::discord::application_id);
70+
71+
m_client.Connect();
72+
}
73+
74+
void DiscordInstance::after_ready() {
75+
76+
this->m_client.GetDiscordClientConnectedUser(
77+
constants::discord::application_id,
78+
[this](const discordpp::ClientResult& result, std::optional<discordpp::UserHandle> user) -> void {
79+
if (result.Successful() and user.has_value()) {
80+
81+
auto user_handle = m_client.GetUser(user->Id());
82+
if (not user_handle.has_value()) {
83+
spdlog::error("Current Connected User Error: Can't get userhandle from id: {}", user->Id());
84+
85+
return;
86+
}
87+
88+
this->m_current_user = user_handle.value();
89+
spdlog::info("Current user updated: {}", user_handle->Username());
90+
91+
return;
92+
}
93+
94+
spdlog::error("Current Connected User Error: {}", result.ToString());
95+
}
96+
);
7797
}
7898

7999

80100
DiscordInstance::DiscordInstance(DiscordInstance&& old) noexcept
81-
: m_core{ std::move(old.m_core) },
82-
m_current_user{ std::move(old.m_current_user) } {
83-
old.m_core = nullptr;
84-
old.m_current_user = nullptr;
101+
: m_client{ std::move(old.m_client) },
102+
m_current_user{ std::move(old.m_current_user) },
103+
m_status{ old.m_status } {
104+
old.m_client = discordpp::Client{};
105+
old.m_current_user = discordpp::UserHandle::nullobj;
106+
old.m_status = DiscordStatus::Error;
85107
}
86108

87109

88110
DiscordInstance& DiscordInstance::operator=(DiscordInstance&& other) noexcept {
89111
if (this != &other) {
90112

91-
m_core = std::move(other.m_core);
113+
m_client = std::move(other.m_client);
92114
m_current_user = std::move(other.m_current_user);
115+
m_status = other.m_status;
93116

94-
other.m_core = nullptr;
95-
other.m_current_user = nullptr;
117+
other.m_client = discordpp::Client{};
118+
other.m_current_user = discordpp::UserHandle::nullobj;
119+
other.m_status = DiscordStatus::Error;
96120
}
97121
return *this;
98122
};
99123

100124
DiscordInstance::~DiscordInstance() {
101-
if (m_core != nullptr) {
125+
if (m_client.operator bool()) {
102126
clear_activity();
127+
m_client.Disconnect();
103128
}
104129
}
105130

131+
[[nodiscard]] DiscordStatus DiscordInstance::get_status() {
132+
return m_status;
133+
}
134+
106135
void DiscordInstance::update() {
107-
m_core->RunCallbacks();
136+
discordpp::RunCallbacks();
108137
}
109138

110139

111140
void DiscordInstance::set_activity(const DiscordActivityWrapper& activity) {
112141

113-
m_core->ActivityManager().UpdateActivity(activity.get_raw(), [](discord::Result result) {
114-
spdlog::info("Result to UpdateActivity: {}", magic_enum::enum_name(result));
115-
});
116-
}
142+
const auto& raw_activity = activity.get_raw();
117143

144+
if (not raw_activity.operator bool()) {
145+
spdlog::error("Tried to set an invalid Discord Activity!");
146+
return;
147+
}
118148

119-
void DiscordInstance::clear_activity(bool wait) {
120-
bool received_callback = false;
121-
m_core->ActivityManager().ClearActivity([&received_callback](discord::Result result) {
122-
spdlog::info("Result to ClearActivity: {}", magic_enum::enum_name(result));
123-
received_callback = true;
149+
// Update rich presence
150+
m_client.UpdateRichPresence(raw_activity, [](const discordpp::ClientResult& result) {
151+
if (result.Successful()) {
152+
spdlog::info("Rich Presence updated successfully");
153+
} else {
154+
spdlog::error("Rich Presence update failed: {}", result.ToString());
155+
}
124156
});
157+
}
125158

126-
using namespace std::chrono_literals;
127-
128-
if (wait) {
129-
130-
constexpr auto max_waittime = 1s;
131-
132-
const auto start_time = std::chrono::steady_clock::now();
133159

134-
while (not received_callback) {
135-
this->update();
136-
std::this_thread::sleep_for(1ms);
137-
const auto now = std::chrono::steady_clock::now();
138-
if (now - start_time >= max_waittime) {
139-
break;
140-
}
141-
}
142-
}
160+
void DiscordInstance::clear_activity() {
161+
m_client.ClearRichPresence();
143162
}
144163

145164

146-
DiscordActivityWrapper::DiscordActivityWrapper(const std::string& details, discord::ActivityType type) {
147-
m_activity.SetDetails(details.c_str());
165+
DiscordActivityWrapper::DiscordActivityWrapper(const std::string& details, discordpp::ActivityTypes type) {
166+
// NOTE: this are partial fields, that are set by the final call, do not set them manually
167+
// https://discord.com/developers/docs/rich-presence/using-with-the-game-sdk#partial-activity-struct
168+
// m_activity.SetName(constants::program_name);
169+
// m_activity.SetApplicationId(constants::application_id);
170+
171+
m_activity.SetDetails(details);
148172
m_activity.SetType(type);
149173
m_activity.SetSupportedPlatforms(constants::discord::supported_platforms);
150174
}
151175

152176

153177
DiscordActivityWrapper&
154178
DiscordActivityWrapper::set_large_image(const std::string& text, constants::discord::ArtAsset asset) {
155-
m_activity.GetAssets().SetLargeText(text.c_str());
179+
auto assets = this->get_assets();
156180

157181
const auto asset_key = constants::discord::get_asset_key(asset);
158-
m_activity.GetAssets().SetLargeImage(asset_key.c_str());
182+
183+
assets.SetLargeImage(asset_key);
184+
assets.SetLargeText(text);
185+
186+
m_activity.SetAssets(assets);
159187

160188
return *this;
161189
}
162190

163191

164192
DiscordActivityWrapper&
165193
DiscordActivityWrapper::set_small_image(const std::string& text, constants::discord::ArtAsset asset) {
166-
m_activity.GetAssets().SetSmallText(text.c_str());
194+
auto assets = this->get_assets();
167195

168196
const auto asset_key = constants::discord::get_asset_key(asset);
169-
m_activity.GetAssets().SetSmallImage(asset_key.c_str());
197+
198+
assets.SetSmallImage(asset_key);
199+
assets.SetSmallText(text);
200+
201+
m_activity.SetAssets(assets);
202+
170203
return *this;
171204
}
172205

173206
DiscordActivityWrapper& DiscordActivityWrapper::set_details(const std::string& text) {
174-
m_activity.SetState(text.c_str());
207+
m_activity.SetState(text);
175208

176209
return *this;
177210
}
178211

179212

180-
[[nodiscard]] const discord::Activity& DiscordActivityWrapper::get_raw() const {
213+
[[nodiscard]] const discordpp::Activity& DiscordActivityWrapper::get_raw() const {
181214
return m_activity;
182215
}
216+
217+
218+
discordpp::ActivityTimestamps DiscordActivityWrapper::get_timestamps() {
219+
220+
std::optional<discordpp::ActivityTimestamps> timestamps = this->m_activity.Timestamps();
221+
222+
if (timestamps.has_value()) {
223+
return timestamps.value();
224+
}
225+
226+
return discordpp::ActivityTimestamps();
227+
}
228+
229+
230+
[[nodiscard]] discordpp::ActivityAssets DiscordActivityWrapper::get_assets() {
231+
std::optional<discordpp::ActivityAssets> assets = this->m_activity.Assets();
232+
233+
if (assets.has_value()) {
234+
return assets.value();
235+
}
236+
237+
return discordpp::ActivityAssets();
238+
}

0 commit comments

Comments
 (0)