util.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. #ifndef UTIL_HPP
  2. #define UTIL_HPP
  3. #pragma GCC system_header
  4. #include <QDebug>
  5. #include <QJsonDocument>
  6. #include <QJsonObject>
  7. #include <QJsonArray>
  8. #include <QQueue>
  9. #include <QString>
  10. #include <QMessageBox>
  11. #include <QDateTime>
  12. #include <QVector>
  13. #include <charconv>
  14. #include <string>
  15. #include <utility>
  16. #include <vector>
  17. #include "rapidjson/document.h"
  18. #include "rapidjson/pointer.h"
  19. #include "rapidjson/prettywriter.h"
  20. #include "rapidjson/stringbuffer.h"
  21. #include "rapidjson/writer.h"
  22. namespace Kontainer {
  23. /** Reverse Iterator */
  24. template <class T>
  25. class ReverseIterator {
  26. T& _obj;
  27. public:
  28. ReverseIterator(T &obj) : _obj(obj) {}
  29. auto begin() {return _obj.rbegin();}
  30. auto end() {return _obj.rend();}
  31. };
  32. } // namespace Kontainer
  33. namespace {
  34. using namespace rapidjson;
  35. typedef std::string KOperation;
  36. typedef std::vector<std::pair<std::string, std::string>> TupVec;
  37. typedef std::vector<std::map<int, std::string>> MapVec;
  38. typedef std::map<int, std::string> CommandMap;
  39. struct KSession {
  40. int id;
  41. int fd;
  42. int status;
  43. };
  44. static QString escapeText(QString s) {
  45. s.replace("\t", "\\t");
  46. s.replace('"', "\\\"");
  47. s.replace("'", "'\"\'\"'");
  48. return s;
  49. }
  50. static QString escapeMessage(QString s) {
  51. s.replace("\t", "\\t");
  52. s.replace('"', "\\\"");
  53. s.replace("'", "\'");
  54. return s;
  55. }
  56. static QString escapeTextToRaw(QString s) {
  57. return escapeText(s).toUtf8().constData();
  58. }
  59. /**
  60. * @brief configValue
  61. * @param [in] {QString} key The key whose corresponding value is to be sought from the
  62. * ConfigJson param
  63. * @param [in] {QJsonObject}config JSON Config object
  64. * @param [in] {bool} use_default Indicates that the default key will be sought if no value
  65. * matching the key parameter is found
  66. * @return {QString} The value which corresonds to the key, or an empty string
  67. *
  68. * TODO: ConfigJson should probably be called something else, like
  69. * ConfigJsonObject
  70. */
  71. QString configValue(QString key, QJsonObject config, bool use_default = false) {
  72. if (!config.contains(key) && use_default) {
  73. if (config.contains("default")) {
  74. return config.value("default").toString();
  75. }
  76. } else {
  77. return config.value(key).toString();
  78. }
  79. return "";
  80. }
  81. QList<QString> configValueToQList(QString key, QJsonObject config) {
  82. QList<QString> list{};
  83. if (config.contains(key)) {
  84. auto value = config.value(key);
  85. if (value.isArray()) {
  86. for (auto && item : value.toArray()) {
  87. list.append(item.toString());
  88. }
  89. }
  90. }
  91. return list;
  92. }
  93. QJsonObject configObject(QString key, QJsonObject config, bool use_default = false) {
  94. auto key_value = key.toLower();
  95. if (!config.contains(key_value) && use_default) {
  96. if (config.contains("default")) {
  97. return config["default"].toObject();
  98. }
  99. } else {
  100. return config[key_value].toObject();
  101. }
  102. qDebug() << "Returning empty QJsonObject :(";
  103. return QJsonObject{};
  104. }
  105. QJsonObject loadJsonConfig(QString json_string) {
  106. return QJsonDocument::fromJson(json_string.toUtf8()).object();
  107. }
  108. bool configBoolValue(QString key, QJsonObject config) {
  109. if (config.contains(key)) {
  110. return bool{config.value(key).toString().compare("true") == 0};
  111. }
  112. }
  113. std::string getJsonString(std::string s) {
  114. Document d;
  115. d.Parse(s.c_str());
  116. StringBuffer buffer;
  117. PrettyWriter<StringBuffer> writer(buffer);
  118. d.Accept(writer);
  119. return buffer.GetString();
  120. }
  121. std::string createMessage(const char* data, std::string args = "") {
  122. StringBuffer s;
  123. Writer<StringBuffer> w(s);
  124. w.StartObject();
  125. w.Key("type");
  126. w.String("custom");
  127. w.Key("message");
  128. w.String(data);
  129. w.Key("args");
  130. w.String(args.c_str());
  131. w.EndObject();
  132. return s.GetString();
  133. }
  134. bool isOperation(const char* data) {
  135. Document d;
  136. d.Parse(data);
  137. return strcmp(d["type"].GetString(), "operation") == 0;
  138. }
  139. bool isUploadCompleteEvent(const char* event) {
  140. return strcmp(event, "File Transfer Complete") == 0;
  141. }
  142. bool isEvent(const char* data) {
  143. Document d;
  144. d.Parse(data);
  145. if (d.HasMember("type")); {
  146. return strcmp(d["type"].GetString(), "event") == 0;
  147. }
  148. return false;
  149. }
  150. template <typename T>
  151. bool isKEvent(T event, const char* kEvent) {
  152. if constexpr (std::is_same_v<T, std::string>) {
  153. return strcmp(event.c_str(), kEvent) == 0;
  154. } else if constexpr (std::is_same_v<T, QString>) {
  155. return strcmp(event.toUtf8(), kEvent) == 0;
  156. } else {
  157. return strcmp(event, kEvent) == 0;
  158. }
  159. }
  160. bool isPong(const char* data) {
  161. return strcmp(data, "PONG") == 0;
  162. }
  163. // TODO: This should be "message", no?
  164. bool isMessage(const char* data) {
  165. Document d;
  166. d.Parse(data);
  167. if (d.HasMember("message")) {
  168. return true;
  169. } else {
  170. return false;
  171. }
  172. }
  173. std::string createOperation(const char* op, std::vector<std::string> args) {
  174. StringBuffer s;
  175. Writer<StringBuffer, Document::EncodingType, ASCII<>> w(s);
  176. w.StartObject();
  177. w.Key("type");
  178. w.String("operation");
  179. w.Key("command");
  180. w.String(op);
  181. w.Key("args");
  182. w.StartArray();
  183. if (!args.empty()) {
  184. for (const auto& arg : args) {
  185. w.String(arg.c_str());
  186. }
  187. }
  188. w.EndArray();
  189. w.EndObject();
  190. return s.GetString();
  191. }
  192. std::string getOperation(const char* data) {
  193. Document d;
  194. d.Parse(data);
  195. if (d.HasMember("command")) {
  196. return d["command"].GetString();
  197. }
  198. return "";
  199. }
  200. QString getEvent(const char* data) {
  201. Document d;
  202. d.Parse(data);
  203. if (d.HasMember("event")) {
  204. return d["event"].GetString();
  205. }
  206. return "";
  207. }
  208. QString getMessage(const char* data) {
  209. Document d;
  210. d.Parse(data);
  211. if (d.HasMember("message")) {
  212. return d["message"].GetString();
  213. }
  214. return "";
  215. }
  216. QVector<QString> getShortArgs(const char* data) {
  217. Document d;
  218. d.Parse(data);
  219. QVector<QString> args{};
  220. if (d.HasMember("args")) {
  221. if (d["args"].IsArray()) {
  222. for (const auto& m : d["args"].GetArray()) {
  223. if (m.GetStringLength() < 100) {
  224. args.push_back(m.GetString());
  225. }
  226. }
  227. } else {
  228. for (const auto& m : d["args"].GetObject()) {
  229. QString arg = m.name.GetString();
  230. arg += ": ";
  231. arg += m.value.GetString();
  232. args.push_back(arg);
  233. }
  234. }
  235. }
  236. return args;
  237. }
  238. QVector<QString> getArgs(const char* data) {
  239. Document d;
  240. d.Parse(data);
  241. QVector<QString> args{};
  242. if (d.HasMember("args")) {
  243. for (const auto& m : d["args"].GetArray()) {
  244. args.push_back(m.GetString());
  245. }
  246. }
  247. return args;
  248. }
  249. QList<QString> getValueArgs(const char* data, QString key) {
  250. auto key_value = key.toUtf8();
  251. Document d;
  252. d.Parse(data);
  253. QList<QString> args{};
  254. if (d.IsObject()) {
  255. for (const auto& m : d.GetObject()) {
  256. auto name = m.name.GetString();
  257. if (name == key.toUtf8()) {
  258. if (m.value.IsArray()) {
  259. for (const auto& a : m.value.GetArray()) {
  260. args.push_back(a.GetString());
  261. }
  262. }
  263. }
  264. }
  265. }
  266. return args;
  267. }
  268. CommandMap getArgMap(const char* data) {
  269. Document d;
  270. d.Parse(data);
  271. CommandMap cm{};
  272. if (d.HasMember("args")) {
  273. for (const auto& m : d["args"].GetObject()) {
  274. cm.emplace(std::stoi(m.name.GetString()), m.value.GetString());
  275. }
  276. }
  277. return cm;
  278. }
  279. std::string createMessage(const char* data,
  280. std::map<int, std::string> map = {}) {
  281. StringBuffer s;
  282. Writer<StringBuffer> w(s);
  283. w.StartObject();
  284. w.Key("type");
  285. w.String("custom");
  286. w.Key("message");
  287. w.String(data);
  288. w.Key("args");
  289. w.StartObject();
  290. if (!map.empty()) {
  291. for (const auto& [k, v] : map) {
  292. w.Key(std::to_string(k).c_str());
  293. w.String(v.c_str());
  294. }
  295. }
  296. w.EndObject();
  297. w.EndObject();
  298. return s.GetString();
  299. }
  300. std::string createMessage(const char* data, std::map<int, std::vector<std::string>> map = {}) {
  301. StringBuffer s;
  302. Writer<StringBuffer> w(s);
  303. w.StartObject();
  304. w.Key("type");
  305. w.String("custom");
  306. w.Key("message");
  307. w.String(data);
  308. w.Key("args");
  309. w.StartObject();
  310. if (!map.empty()) {
  311. for (const auto& [k, v] : map) {
  312. w.Key(std::to_string(k).c_str());
  313. if (!v.empty()) {
  314. w.StartArray();
  315. for (const auto& arg : v) {
  316. w.String(arg.c_str());
  317. }
  318. w.EndArray();
  319. }
  320. }
  321. }
  322. w.EndObject();
  323. w.EndObject();
  324. return s.GetString();
  325. }
  326. std::string rapidCreateMessage(const char* data,
  327. std::map<int, std::string> map = {}) {
  328. StringBuffer s;
  329. Writer<StringBuffer> w(s);
  330. w.StartObject();
  331. w.Key("type");
  332. w.String("custom");
  333. w.Key("message");
  334. w.String(data);
  335. w.Key("args");
  336. w.StartObject();
  337. if (!map.empty()) {
  338. for (const auto& [k, v] : map) {
  339. w.Key(std::to_string(k).c_str());
  340. w.String(v.c_str());
  341. }
  342. }
  343. w.EndObject();
  344. w.EndObject();
  345. return s.GetString();
  346. }
  347. bool isStartOperation(const char* data) {
  348. Document d;
  349. d.Parse(data);
  350. return strcmp(d["command"].GetString(), "start") == 0;
  351. }
  352. bool isStopOperation(const char* data) {
  353. Document d;
  354. d.Parse(data);
  355. return strcmp(d["command"].GetString(), "stop") == 0;
  356. }
  357. bool isNewSession(const char* data) {
  358. Document d;
  359. d.Parse(data);
  360. if (d.IsObject() && d.HasMember("message")) {
  361. return strcmp(d["message"].GetString(), "New Session") == 0;
  362. }
  363. return false;
  364. }
  365. bool serverWaitingForFile(const char* data) {
  366. Document d;
  367. d.Parse(data);
  368. if (d.IsObject() && d.HasMember("message")) {
  369. return strcmp(d["message"].GetString(), "File Ready") == 0;
  370. }
  371. return false;
  372. }
  373. inline size_t findNullIndex(uint8_t* data) {
  374. size_t index = 0;
  375. while (data) {
  376. if (strcmp(const_cast<const char*>((char*)data), "\0") == 0) {
  377. break;
  378. }
  379. index++;
  380. data++;
  381. }
  382. return index;
  383. }
  384. namespace FileUtils {
  385. QString generatePreview(QString video_path, QString video_name) {
  386. QString preview_name =
  387. video_name.left(video_name.size() - 4) + "-preview.jpg";
  388. QString command{
  389. "ffmpeg -y -ss 0 -i '" + video_path +
  390. "' -vf \"scale=w=640:h=640:force_original_aspect_ratio=decrease\" "
  391. "-vframes 1 './assets/previews/" +
  392. preview_name + "'"};
  393. std::system(command.toUtf8());
  394. return preview_name;
  395. }
  396. }; // namespace FileUtils
  397. namespace UI {
  398. inline void infoMessageBox(QString text, QString title = "KYGUI") {
  399. QMessageBox box;
  400. box.setWindowTitle(title);
  401. box.setText(text);
  402. box.setButtonText(0, "Close");
  403. box.exec();
  404. }
  405. } // namespace UI
  406. namespace TimeUtils {
  407. inline QString getTime() { return QDateTime::currentDateTime().toString("hh:mm:ss"); }
  408. inline uint unixtime() { return QDateTime::currentDateTime().toTime_t(); }
  409. } // namespace TimeUtils
  410. } // namespace
  411. #endif // UTIL_HPP