flip_social_messages.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. #ifndef FLIP_SOCIAL_MESSAGES_H
  2. #define FLIP_SOCIAL_MESSAGES_H
  3. static FlipSocialModel2 *flip_social_messages_alloc()
  4. {
  5. // Allocate memory for each username only if not already allocated
  6. FlipSocialModel2 *users = malloc(sizeof(FlipSocialModel2));
  7. if (users == NULL)
  8. {
  9. FURI_LOG_E(TAG, "Failed to allocate memory for message users");
  10. return NULL;
  11. }
  12. for (size_t i = 0; i < MAX_MESSAGE_USERS; i++)
  13. {
  14. if (users->usernames[i] == NULL)
  15. {
  16. users->usernames[i] = malloc(MAX_USER_LENGTH);
  17. if (users->usernames[i] == NULL)
  18. {
  19. FURI_LOG_E(TAG, "Failed to allocate memory for username %zu", i);
  20. return NULL; // Return false on memory allocation failure
  21. }
  22. }
  23. }
  24. return users;
  25. }
  26. static FlipSocialMessage *flip_social_user_messages_alloc()
  27. {
  28. // Allocate memory for each username only if not already allocated
  29. FlipSocialMessage *messages = malloc(sizeof(FlipSocialMessage));
  30. if (messages == NULL)
  31. {
  32. FURI_LOG_E(TAG, "Failed to allocate memory for messages");
  33. return NULL;
  34. }
  35. for (size_t i = 0; i < MAX_MESSAGE_USERS; i++)
  36. {
  37. if (messages->usernames[i] == NULL)
  38. {
  39. messages->usernames[i] = malloc(MAX_USER_LENGTH);
  40. if (messages->usernames[i] == NULL)
  41. {
  42. FURI_LOG_E(TAG, "Failed to allocate memory for username %zu", i);
  43. return NULL; // Return false on memory allocation failure
  44. }
  45. }
  46. if (messages->messages[i] == NULL)
  47. {
  48. messages->messages[i] = malloc(MAX_MESSAGE_LENGTH);
  49. if (messages->messages[i] == NULL)
  50. {
  51. FURI_LOG_E(TAG, "Failed to allocate memory for message %zu", i);
  52. return NULL; // Return false on memory allocation failure
  53. }
  54. }
  55. }
  56. return messages;
  57. }
  58. static void flip_social_free_message_users()
  59. {
  60. if (flip_social_message_users == NULL)
  61. {
  62. FURI_LOG_E(TAG, "Message users model is NULL");
  63. return;
  64. }
  65. for (int i = 0; i < flip_social_message_users->count; i++)
  66. {
  67. free(flip_social_message_users->usernames[i]);
  68. }
  69. }
  70. static void flip_social_free_messages()
  71. {
  72. if (flip_social_messages == NULL)
  73. {
  74. FURI_LOG_E(TAG, "Messages model is NULL");
  75. return;
  76. }
  77. for (int i = 0; i < flip_social_messages->count; i++)
  78. {
  79. free(flip_social_messages->usernames[i]);
  80. free(flip_social_messages->messages[i]);
  81. }
  82. }
  83. static bool flip_social_update_messages_submenu()
  84. {
  85. if (app_instance->submenu_messages == NULL)
  86. {
  87. FURI_LOG_E(TAG, "Submenu is NULL");
  88. return false;
  89. }
  90. if (flip_social_message_users == NULL)
  91. {
  92. FURI_LOG_E(TAG, "Message users model is NULL");
  93. return false;
  94. }
  95. submenu_reset(app_instance->submenu_messages);
  96. submenu_set_header(app_instance->submenu_messages, "Messages");
  97. submenu_add_item(app_instance->submenu_messages, "[New Message]", FlipSocialSubmenuLoggedInIndexMessagesNewMessage, flip_social_callback_submenu_choices, app_instance);
  98. for (int i = 0; i < flip_social_message_users->count; i++)
  99. {
  100. submenu_add_item(app_instance->submenu_messages, flip_social_message_users->usernames[i], FlipSocialSubmenuLoggedInIndexMessagesUsersStart + i, flip_social_callback_submenu_choices, app_instance);
  101. }
  102. return true;
  103. }
  104. static bool flip_social_update_submenu_user_choices()
  105. {
  106. if (app_instance->submenu_messages_user_choices == NULL)
  107. {
  108. FURI_LOG_E(TAG, "Submenu is NULL");
  109. return false;
  110. }
  111. if (flip_social_explore == NULL)
  112. {
  113. FURI_LOG_E(TAG, "Explore model is NULL");
  114. return false;
  115. }
  116. submenu_reset(app_instance->submenu_messages_user_choices);
  117. submenu_set_header(app_instance->submenu_messages_user_choices, "Users");
  118. for (int i = 0; i < flip_social_explore->count; i++)
  119. {
  120. submenu_add_item(app_instance->submenu_messages_user_choices, flip_social_explore->usernames[i], FlipSocialSubmenuLoggedInIndexMessagesUserChoicesIndexStart + i, flip_social_callback_submenu_choices, app_instance);
  121. }
  122. return true;
  123. }
  124. // Get all the users that have sent messages to the logged in user
  125. static bool flip_social_get_message_users()
  126. {
  127. if (app_instance->login_username_logged_out == NULL)
  128. {
  129. FURI_LOG_E(TAG, "Username is NULL");
  130. return false;
  131. }
  132. char command[128];
  133. snprintf(command, 128, "https://www.flipsocial.net/api/messages/%s/get/list/", app_instance->login_username_logged_out);
  134. bool success = flipper_http_get_request_with_headers(command, "{\"Content-Type\":\"application/json\"}");
  135. if (!success)
  136. {
  137. FURI_LOG_E(TAG, "Failed to send HTTP request for messages");
  138. return false;
  139. }
  140. fhttp.state = RECEIVING;
  141. return true;
  142. }
  143. // Get all the messages between the logged in user and the selected user
  144. static bool flip_social_get_messages_with_user()
  145. {
  146. if (app_instance->login_username_logged_out == NULL)
  147. {
  148. FURI_LOG_E(TAG, "Username is NULL");
  149. return false;
  150. }
  151. char command[128];
  152. snprintf(command, 128, "https://www.flipsocial.net/api/messages/%s/get/%s/", app_instance->login_username_logged_out, flip_social_message_users->usernames[flip_social_message_users->index]);
  153. bool success = flipper_http_get_request_with_headers(command, "{\"Content-Type\":\"application/json\"}");
  154. if (!success)
  155. {
  156. FURI_LOG_E(TAG, "Failed to send HTTP request for messages");
  157. return false;
  158. }
  159. fhttp.state = RECEIVING;
  160. return true;
  161. }
  162. // Parse the users that have sent messages to the logged-in user
  163. static bool flip_social_parse_json_message_users()
  164. {
  165. if (fhttp.received_data == NULL)
  166. {
  167. FURI_LOG_E(TAG, "No data received.");
  168. return false;
  169. }
  170. // Allocate memory for each username only if not already allocated
  171. flip_social_message_users = flip_social_messages_alloc();
  172. if (flip_social_message_users == NULL)
  173. {
  174. FURI_LOG_E(TAG, "Failed to allocate memory for message users.");
  175. return false;
  176. }
  177. // Remove newlines
  178. char *pos = fhttp.received_data;
  179. while ((pos = strchr(pos, '\n')) != NULL)
  180. {
  181. *pos = ' ';
  182. }
  183. // Initialize message users count
  184. flip_social_message_users->count = 0;
  185. // Extract the users array from the JSON
  186. char *json_users = get_json_value("users", fhttp.received_data, MAX_TOKENS);
  187. if (json_users == NULL)
  188. {
  189. FURI_LOG_E(TAG, "Failed to parse users array.");
  190. return false;
  191. }
  192. // Manual tokenization for comma-separated values
  193. char *start = json_users + 1; // Skip the opening bracket
  194. char *end;
  195. while ((end = strchr(start, ',')) != NULL && flip_social_message_users->count < MAX_MESSAGE_USERS)
  196. {
  197. *end = '\0'; // Null-terminate the current token
  198. // Remove quotes
  199. if (*start == '"')
  200. start++;
  201. if (*(end - 1) == '"')
  202. *(end - 1) = '\0';
  203. // Copy username to pre-allocated memory
  204. strncpy(flip_social_message_users->usernames[flip_social_message_users->count], start, MAX_USER_LENGTH - 1);
  205. flip_social_message_users->usernames[flip_social_message_users->count][MAX_USER_LENGTH - 1] = '\0'; // Ensure null termination
  206. flip_social_message_users->count++;
  207. start = end + 1;
  208. }
  209. // Handle the last token
  210. if (*start != '\0' && flip_social_message_users->count < MAX_MESSAGE_USERS)
  211. {
  212. if (*start == '"')
  213. start++;
  214. if (*(start + strlen(start) - 1) == ']')
  215. *(start + strlen(start) - 1) = '\0';
  216. if (*(start + strlen(start) - 1) == '"')
  217. *(start + strlen(start) - 1) = '\0';
  218. strncpy(flip_social_message_users->usernames[flip_social_message_users->count], start, MAX_USER_LENGTH - 1);
  219. flip_social_message_users->usernames[flip_social_message_users->count][MAX_USER_LENGTH - 1] = '\0'; // Ensure null termination
  220. flip_social_message_users->count++;
  221. }
  222. // Add submenu items for the users
  223. flip_social_update_messages_submenu();
  224. // Free the JSON data
  225. free(json_users);
  226. free(start);
  227. free(end);
  228. return true;
  229. }
  230. // Parse the users that the logged in user can message
  231. static bool flip_social_parse_json_message_user_choices()
  232. {
  233. if (fhttp.received_data == NULL)
  234. {
  235. FURI_LOG_E(TAG, "No data received.");
  236. return false;
  237. }
  238. // Allocate memory for each username only if not already allocated
  239. flip_social_explore = flip_social_explore_alloc();
  240. if (flip_social_explore == NULL)
  241. {
  242. FURI_LOG_E(TAG, "Failed to allocate memory for explore usernames.");
  243. return false;
  244. }
  245. // Remove newlines
  246. char *pos = fhttp.received_data;
  247. while ((pos = strchr(pos, '\n')) != NULL)
  248. {
  249. *pos = ' ';
  250. }
  251. // Initialize explore count
  252. flip_social_explore->count = 0;
  253. // Extract the users array from the JSON
  254. char *json_users = get_json_value("users", fhttp.received_data, MAX_TOKENS);
  255. if (json_users == NULL)
  256. {
  257. FURI_LOG_E(TAG, "Failed to parse users array.");
  258. return false;
  259. }
  260. // Manual tokenization for comma-separated values
  261. char *start = json_users + 1; // Skip the opening bracket
  262. char *end;
  263. while ((end = strchr(start, ',')) != NULL && flip_social_explore->count < MAX_EXPLORE_USERS)
  264. {
  265. *end = '\0'; // Null-terminate the current token
  266. // Remove quotes
  267. if (*start == '"')
  268. start++;
  269. if (*(end - 1) == '"')
  270. *(end - 1) = '\0';
  271. // Copy username to pre-allocated memory
  272. strncpy(flip_social_explore->usernames[flip_social_explore->count], start, MAX_USER_LENGTH - 1);
  273. flip_social_explore->usernames[flip_social_explore->count][MAX_USER_LENGTH - 1] = '\0'; // Ensure null termination
  274. flip_social_explore->count++;
  275. start = end + 1;
  276. }
  277. // Handle the last token
  278. if (*start != '\0' && flip_social_explore->count < MAX_EXPLORE_USERS)
  279. {
  280. if (*start == '"')
  281. start++;
  282. if (*(start + strlen(start) - 1) == ']')
  283. *(start + strlen(start) - 1) = '\0';
  284. if (*(start + strlen(start) - 1) == '"')
  285. *(start + strlen(start) - 1) = '\0';
  286. strncpy(flip_social_explore->usernames[flip_social_explore->count], start, MAX_USER_LENGTH - 1);
  287. flip_social_explore->usernames[flip_social_explore->count][MAX_USER_LENGTH - 1] = '\0'; // Ensure null termination
  288. flip_social_explore->count++;
  289. }
  290. // Add submenu items for the users
  291. flip_social_update_submenu_user_choices();
  292. // Free the JSON data
  293. free(json_users);
  294. free(start);
  295. free(end);
  296. return true;
  297. }
  298. // parse messages between the logged in user and the selected user
  299. static bool flip_social_parse_json_messages()
  300. {
  301. if (fhttp.received_data == NULL)
  302. {
  303. FURI_LOG_E(TAG, "No data received.");
  304. return false;
  305. }
  306. // Allocate memory for each message only if not already allocated
  307. flip_social_messages = flip_social_user_messages_alloc();
  308. if (!flip_social_messages)
  309. {
  310. FURI_LOG_E(TAG, "Failed to allocate memory for messages.");
  311. return false;
  312. }
  313. // Remove newlines
  314. char *pos = fhttp.received_data;
  315. while ((pos = strchr(pos, '\n')) != NULL)
  316. {
  317. *pos = ' ';
  318. }
  319. // Initialize messages count
  320. flip_social_messages->count = 0;
  321. // Iterate through the messages array
  322. for (int i = 0; i < MAX_MESSAGES; i++)
  323. {
  324. // Parse each item in the array
  325. char *item = get_json_array_value("conversations", i, fhttp.received_data, MAX_TOKENS);
  326. if (item == NULL)
  327. {
  328. break;
  329. }
  330. // Extract individual fields from the JSON object
  331. char *sender = get_json_value("sender", item, MAX_TOKENS);
  332. char *content = get_json_value("content", item, MAX_TOKENS);
  333. if (sender == NULL || content == NULL)
  334. {
  335. FURI_LOG_E(TAG, "Failed to parse item fields.");
  336. free(item);
  337. continue;
  338. }
  339. // Store parsed values
  340. strncpy(flip_social_messages->usernames[i], sender, MAX_USER_LENGTH - 1);
  341. flip_social_messages->usernames[i][MAX_USER_LENGTH - 1] = '\0';
  342. strncpy(flip_social_messages->messages[i], content, MAX_MESSAGE_LENGTH - 1);
  343. flip_social_messages->messages[i][MAX_MESSAGE_LENGTH - 1] = '\0';
  344. flip_social_messages->count++;
  345. free(item);
  346. free(sender);
  347. free(content);
  348. }
  349. return true;
  350. }
  351. #endif // FLIP_SOCIAL_MESSAGES_H