discord_impl.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. // SPDX-FileCopyrightText: 2018 Citra Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <chrono>
  4. #include <string>
  5. #include <discord_rpc.h>
  6. #include <fmt/format.h>
  7. #include <httplib.h>
  8. #include "common/common_types.h"
  9. #include "common/string_util.h"
  10. #include "core/core.h"
  11. #include "core/loader/loader.h"
  12. #include "yuzu/discord_impl.h"
  13. #include "yuzu/uisettings.h"
  14. namespace DiscordRPC {
  15. DiscordImpl::DiscordImpl(Core::System& system_) : system{system_} {
  16. DiscordEventHandlers handlers{};
  17. // The number is the client ID for yuzu, it's used for images and the
  18. // application name
  19. Discord_Initialize("712465656758665259", &handlers, 1, nullptr);
  20. }
  21. DiscordImpl::~DiscordImpl() {
  22. Discord_ClearPresence();
  23. Discord_Shutdown();
  24. }
  25. void DiscordImpl::Pause() {
  26. Discord_ClearPresence();
  27. }
  28. static std::string GetGameString(const std::string& title) {
  29. // Convert to lowercase
  30. std::string icon_name = Common::ToLower(title);
  31. // Replace spaces with dashes
  32. std::replace(icon_name.begin(), icon_name.end(), ' ', '-');
  33. // Remove non-alphanumeric characters but keep dashes
  34. std::erase_if(icon_name, [](char c) { return !std::isalnum(c) && c != '-'; });
  35. // Remove dashes from the start and end of the string
  36. icon_name.erase(icon_name.begin(), std::find_if(icon_name.begin(), icon_name.end(),
  37. [](int ch) { return ch != '-'; }));
  38. icon_name.erase(
  39. std::find_if(icon_name.rbegin(), icon_name.rend(), [](int ch) { return ch != '-'; }).base(),
  40. icon_name.end());
  41. // Remove double dashes
  42. icon_name.erase(std::unique(icon_name.begin(), icon_name.end(),
  43. [](char a, char b) { return a == '-' && b == '-'; }),
  44. icon_name.end());
  45. return icon_name;
  46. }
  47. void DiscordImpl::Update() {
  48. s64 start_time = std::chrono::duration_cast<std::chrono::seconds>(
  49. std::chrono::system_clock::now().time_since_epoch())
  50. .count();
  51. const std::string default_text = "yuzu is an emulator for the Nintendo Switch";
  52. const std::string default_image = "yuzu_logo";
  53. std::string game_cover_url = "https://yuzu-emu.org";
  54. std::string title;
  55. DiscordRichPresence presence{};
  56. if (system.IsPoweredOn()) {
  57. system.GetAppLoader().ReadTitle(title);
  58. // Used to format Icon URL for yuzu website game compatibility page
  59. std::string icon_name = GetGameString(title);
  60. // New Check for game cover
  61. httplib::Client cli(game_cover_url);
  62. if (auto res = cli.Head(fmt::format("/images/game/boxart/{}.png", icon_name).c_str())) {
  63. if (res->status == 200) {
  64. game_cover_url += fmt::format("/images/game/boxart/{}.png", icon_name);
  65. } else {
  66. game_cover_url = "yuzu_logo";
  67. }
  68. } else {
  69. game_cover_url = "yuzu_logo";
  70. }
  71. presence.largeImageKey = game_cover_url.c_str();
  72. presence.largeImageText = title.c_str();
  73. presence.smallImageKey = default_image.c_str();
  74. presence.smallImageText = default_text.c_str();
  75. presence.state = title.c_str();
  76. presence.details = "Currently in game";
  77. } else {
  78. presence.largeImageKey = default_image.c_str();
  79. presence.largeImageText = default_text.c_str();
  80. presence.details = "Currently not in game";
  81. }
  82. presence.startTimestamp = start_time;
  83. Discord_UpdatePresence(&presence);
  84. }
  85. } // namespace DiscordRPC