util.hpp 10 KB

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