|
| 1 | +#include <iostream> |
| 2 | +#include "../core/globals.h" |
| 3 | +#include "crashlog.h" |
| 4 | +#include "discord_rpc.h" |
| 5 | + |
| 6 | +void Discord_Ready(const DiscordUser* user) { |
| 7 | + std::cout << "[DISCORD]: Connected to Discord user: " + std::string(user->username); |
| 8 | +} |
| 9 | + |
| 10 | +void Discord_Disconnected(int errorCode, const char* message) { |
| 11 | + std::cout << "[DISCORD]: Disconnected (" + std::to_string(errorCode) + "): " + std::string(message); |
| 12 | +} |
| 13 | + |
| 14 | +void Discord_Error(int errorCode, const char* message) { |
| 15 | + std::cout << "[DISCORD]: Error (" + std::to_string(errorCode) + "): " + std::string(message); |
| 16 | + AppendToCrashLog("[DISCORD]: Error (" + std::to_string(errorCode) + "): " + std::string(message)); |
| 17 | +} |
| 18 | + |
| 19 | +void InitializeDiscord() |
| 20 | +{ |
| 21 | + DiscordEventHandlers handlers{}; |
| 22 | + memset(&handlers, 0, sizeof(handlers)); |
| 23 | + handlers.ready = Discord_Ready; |
| 24 | + handlers.disconnected = Discord_Disconnected; |
| 25 | + handlers.errored = Discord_Error; |
| 26 | + |
| 27 | + Discord_Initialize("1361448446862692492", &handlers, 1, nullptr); |
| 28 | +} |
| 29 | + |
| 30 | +// Encapsulated presence setters |
| 31 | + |
| 32 | +static void SetDiscordWatchingPresence( |
| 33 | + const std::vector<std::string>& args |
| 34 | +) { |
| 35 | + // expects: |
| 36 | + // 0: generic "watching" identifier |
| 37 | + // 1: type (movie, series) |
| 38 | + // 2: title |
| 39 | + // 3: season |
| 40 | + // 4: episode |
| 41 | + // 5: episode name |
| 42 | + // 6: episode thumbnail (small image) (Optional) |
| 43 | + // 7: show/movie image (large image) |
| 44 | + // 8: elapsed seconds |
| 45 | + // 9: duration seconds |
| 46 | + // 10: isPaused ("yes" or "no") (Optional) |
| 47 | + // 11: more detail button link (imdb link) (Optional) |
| 48 | + // 12: watch on stremio button link (stremio link) (Optional) |
| 49 | + DiscordRichPresence discordPresence{}; |
| 50 | + memset(&discordPresence, 0, sizeof(discordPresence)); |
| 51 | + |
| 52 | + discordPresence.type = DISCORD_ACTIVITY_TYPE_WATCHING; |
| 53 | + |
| 54 | + // Common fields (required) |
| 55 | + discordPresence.details = args[2].c_str(); // Title |
| 56 | + discordPresence.largeImageKey = args[7].c_str(); |
| 57 | + discordPresence.largeImageText = args[2].c_str(); |
| 58 | + |
| 59 | + // Handle paused state (optional) |
| 60 | + bool isPaused = (!args[10].empty() && args[10] == "yes"); |
| 61 | + |
| 62 | + if (isPaused) { |
| 63 | + discordPresence.state = "Paused"; |
| 64 | + discordPresence.startTimestamp = 0; |
| 65 | + discordPresence.endTimestamp = 0; |
| 66 | + } else { |
| 67 | + std::time_t currentTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); |
| 68 | + int elapsedSeconds = std::stoi(args[8]); |
| 69 | + int durationSeconds = std::stoi(args[9]); |
| 70 | + |
| 71 | + discordPresence.startTimestamp = currentTime - elapsedSeconds; |
| 72 | + discordPresence.endTimestamp = currentTime + (durationSeconds - elapsedSeconds); |
| 73 | + |
| 74 | + if (args[1] == "series") { |
| 75 | + // Series-specific fields |
| 76 | + std::string state = args[5] + " (S" + args[3] + "-E" + args[4] + ")"; |
| 77 | + discordPresence.state = state.c_str(); |
| 78 | + |
| 79 | + if (!args[6].empty()) { |
| 80 | + discordPresence.smallImageKey = args[6].c_str(); |
| 81 | + discordPresence.smallImageText = args[5].c_str(); |
| 82 | + } |
| 83 | + } else { |
| 84 | + discordPresence.state = "Enjoying a Movie"; |
| 85 | + } |
| 86 | + } |
| 87 | + |
| 88 | + // Buttons setup (optional) |
| 89 | + if (!args[11].empty()) { |
| 90 | + discordPresence.button1Label = "More Details"; |
| 91 | + discordPresence.button1Url = args[11].c_str(); |
| 92 | + } |
| 93 | + |
| 94 | + if (!args[12].empty()) { |
| 95 | + discordPresence.button2Label = "Watch on Stremio"; |
| 96 | + discordPresence.button2Url = args[12].c_str(); |
| 97 | + } |
| 98 | + |
| 99 | + Discord_UpdatePresence(&discordPresence); |
| 100 | +} |
| 101 | + |
| 102 | +static void SetDiscordMetaDetailPresence(const std::vector<std::string>& args) { |
| 103 | + // args structure: |
| 104 | + // 0: embed type ("meta-detail") |
| 105 | + // 1: type ("movie" or "series") |
| 106 | + // 2: title |
| 107 | + // 3: image URL |
| 108 | + |
| 109 | + DiscordRichPresence discordPresence{}; |
| 110 | + memset(&discordPresence, 0, sizeof(discordPresence)); |
| 111 | + |
| 112 | + discordPresence.type = DISCORD_ACTIVITY_TYPE_WATCHING; |
| 113 | + discordPresence.details = args[2].c_str(); // Title (show/movie) |
| 114 | + discordPresence.largeImageKey = args[3].c_str(); |
| 115 | + discordPresence.largeImageText = args[2].c_str(); |
| 116 | + |
| 117 | + // Engaging state |
| 118 | + discordPresence.state = args[1] == "movie" |
| 119 | + ? "Exploring a Movie" |
| 120 | + : "Exploring a Series"; |
| 121 | + |
| 122 | + Discord_UpdatePresence(&discordPresence); |
| 123 | +} |
| 124 | + |
| 125 | +static void SetDiscordDiscoverPresence(const char *const details, const char *const state) { |
| 126 | + std::cout << "[DISCORD]: Setting discover Presence"; |
| 127 | + |
| 128 | + DiscordRichPresence discordPresence{}; |
| 129 | + memset(&discordPresence, 0, sizeof(discordPresence)); |
| 130 | + discordPresence.type = DISCORD_ACTIVITY_TYPE_WATCHING; |
| 131 | + discordPresence.state = state; |
| 132 | + discordPresence.details = details; |
| 133 | + discordPresence.largeImageKey = "https://raw.githubusercontent.com/Stremio/stremio-web/refs/heads/development/images/icon.png"; |
| 134 | + discordPresence.largeImageText = "Stremio"; |
| 135 | + Discord_UpdatePresence(&discordPresence); |
| 136 | +} |
| 137 | + |
| 138 | +void SetDiscordPresenceFromArgs(const std::vector<std::string>& args) { |
| 139 | + if (!g_isRpcOn || args.empty()) { |
| 140 | + return; |
| 141 | + } |
| 142 | + |
| 143 | + const std::string& embedType = args[0]; |
| 144 | + if (embedType == "watching" && args.size() >= 12) { |
| 145 | + SetDiscordWatchingPresence(args); |
| 146 | + } else if (embedType == "meta-detail" && args.size() >= 4) { |
| 147 | + SetDiscordMetaDetailPresence(args); |
| 148 | + } else if (embedType == "board") { |
| 149 | + SetDiscordDiscoverPresence("Resuming Favorites", "On Board"); |
| 150 | + } else if (embedType == "discover") { |
| 151 | + SetDiscordDiscoverPresence("Finding New Gems", "In Discover"); |
| 152 | + } else if (embedType == "library") { |
| 153 | + SetDiscordDiscoverPresence("Revisiting Old Favorites", "In Library"); |
| 154 | + } else if (embedType == "calendar") { |
| 155 | + SetDiscordDiscoverPresence("Planning My Next Binge", "On Calendar"); |
| 156 | + } else if (embedType == "addons") { |
| 157 | + SetDiscordDiscoverPresence("Exploring Add-ons", "In Add-ons"); |
| 158 | + } else if (embedType == "settings") { |
| 159 | + SetDiscordDiscoverPresence("Tuning Preferences", "In Settings"); |
| 160 | + } else if (embedType == "search") { |
| 161 | + SetDiscordDiscoverPresence("Searching for Shows & Movies", "In Search"); |
| 162 | + } else if (embedType == "clear") { |
| 163 | + Discord_ClearPresence(); |
| 164 | + } |
| 165 | + // Add more presence types here... |
| 166 | +} |
0 commit comments