PlayerLink/src/utils.hpp

167 lines
5.1 KiB
C++
Raw Normal View History

2024-11-01 14:10:00 +01:00
#ifndef _UTILS_
#define _UTILS_
2024-11-01 15:04:43 +01:00
#include <curl/include/curl/curl.h>
2024-11-02 17:17:12 +01:00
#include <wx/mstream.h>
#include <wx/wx.h>
2024-11-01 15:04:43 +01:00
2024-11-01 14:10:00 +01:00
#include <filesystem>
#include <fstream>
#include <nlohmann-json/single_include/nlohmann/json.hpp>
#include <sstream>
#include <string>
2024-11-03 12:56:42 +01:00
#include <vector>
2024-11-01 14:10:00 +01:00
#define DEFAULT_CLIENT_ID "1301849203378622545"
#define DEFAULT_APP_NAME "Music"
2024-11-03 12:56:42 +01:00
#define CONFIG_FILENAME "settings.json"
2024-11-01 14:10:00 +01:00
namespace utils {
2024-11-03 12:56:42 +01:00
struct App {
bool enabled;
std::string appName;
std::string clientId;
std::string searchEndpoint;
std::vector<std::string> processNames;
};
2024-11-02 17:17:12 +01:00
inline wxIcon loadIconFromMemory(const unsigned char* data, size_t size) {
wxMemoryInputStream stream(data, size);
2024-11-03 12:56:42 +01:00
wxImage img(stream, wxBITMAP_TYPE_PNG);
2024-11-02 17:17:12 +01:00
if (img.IsOk()) {
wxBitmap bmp(img);
wxIcon icon;
icon.CopyFromBitmap(bmp);
return icon;
}
return wxNullIcon;
}
2024-11-03 12:56:42 +01:00
2024-11-01 16:49:48 +01:00
inline std::string ltrim(std::string& s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); }));
return s;
}
inline std::string rtrim(std::string& s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end());
return s;
}
2024-11-03 12:56:42 +01:00
2024-11-01 16:49:48 +01:00
inline std::string trim(std::string& s) {
ltrim(s);
rtrim(s);
return s;
}
2024-11-03 12:56:42 +01:00
2024-11-01 15:04:43 +01:00
inline std::string urlEncode(std::string str) {
2024-11-04 15:32:46 +01:00
std::ostringstream encoded;
encoded << std::hex << std::uppercase;
for (unsigned char c : str) {
if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
encoded << c;
} else {
encoded << '%' << std::setw(2) << std::setfill('0') << static_cast<int>(c);
2024-11-01 15:04:43 +01:00
}
}
2024-11-04 15:32:46 +01:00
return encoded.str();
2024-11-01 15:04:43 +01:00
}
2024-11-01 16:49:48 +01:00
2024-11-01 15:04:43 +01:00
inline size_t curlWriteCallback(char* contents, size_t size, size_t nmemb, void* userp) {
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
2024-11-01 16:49:48 +01:00
2024-11-01 15:04:43 +01:00
inline std::string getRequest(std::string url) {
CURL* curl;
CURLcode res;
std::string buf;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriteCallback);
2024-11-01 16:49:48 +01:00
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
2024-11-01 15:04:43 +01:00
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buf);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return buf;
}
2024-11-01 16:49:48 +01:00
2024-11-01 15:04:43 +01:00
inline std::string getArtworkURL(std::string query) {
std::string response =
getRequest("https://itunes.apple.com/search?media=music&entity=song&term=" + urlEncode(query));
nlohmann::json j = nlohmann::json::parse(response);
auto results = j["results"];
if (results.size() > 0) {
return results[0]["artworkUrl100"].get<std::string>();
}
return "";
}
2024-11-01 16:49:48 +01:00
2024-11-03 12:56:42 +01:00
inline std::vector<App> getAllApps() {
std::vector<App> results;
if (!std::filesystem::exists(CONFIG_FILENAME))
return results;
std::ifstream i(CONFIG_FILENAME);
2024-11-01 14:10:00 +01:00
std::stringstream s;
s << i.rdbuf();
i.close();
try {
nlohmann::json j = nlohmann::json::parse(s.str());
auto apps = j["apps"];
for (auto app : apps) {
2024-11-03 12:56:42 +01:00
App a;
a.appName = app["name"].get<std::string>();
a.clientId = app["client_id"].get<std::string>();
a.searchEndpoint = app["search_endpoint"].get<std::string>();
a.enabled = app["enabled"].get<bool>();
2024-11-01 14:10:00 +01:00
auto processNames = app["process_names"];
2024-11-03 12:56:42 +01:00
for (auto process : processNames) a.processNames.push_back(process.get<std::string>());
results.push_back(a);
2024-11-01 14:10:00 +01:00
}
} catch (nlohmann::json::parse_error& ex) {
} // TODO: handle parse errors
2024-11-03 12:56:42 +01:00
return results;
}
inline App getApp(std::string processName) {
auto apps = getAllApps();
for (auto app : apps) {
2024-11-04 15:32:46 +01:00
for (auto procName : app.processNames) {
if (procName == processName)
2024-11-03 12:56:42 +01:00
return app;
}
}
App a;
a.clientId = DEFAULT_CLIENT_ID;
a.appName = DEFAULT_APP_NAME;
a.enabled = true;
a.searchEndpoint = "";
return a;
2024-11-01 14:10:00 +01:00
}
inline std::string getClientID(std::string processName) {
auto app = getApp(processName);
2024-11-03 12:56:42 +01:00
return app.clientId;
2024-11-01 14:10:00 +01:00
}
inline std::string getAppName(std::string processName) {
auto app = getApp(processName);
2024-11-03 12:56:42 +01:00
return app.appName;
2024-11-01 14:10:00 +01:00
}
inline std::string getSearchEndpoint(std::string processName) {
auto app = getApp(processName);
2024-11-03 12:56:42 +01:00
return app.searchEndpoint;
2024-11-01 14:10:00 +01:00
}
} // namespace utils
#undef DEFAULT_APP_NAME
#undef CONFIG_FILENAME
#undef DEFAULT_CLIENT_ID
#endif