flip_social_feed.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. #ifndef FLIP_SOCIAL_FEED_H
  2. #define FLIP_SOCIAL_FEED_H
  3. static FlipSocialApp *app_instance = NULL;
  4. #define MAX_TOKENS 128 // Adjust based on expected JSON tokens
  5. typedef struct
  6. {
  7. char *usernames[128];
  8. char *messages[128];
  9. bool is_flipped[128];
  10. uint32_t ids[128];
  11. size_t count;
  12. size_t index;
  13. } FlipSocialFeed;
  14. #define MAX_FEED_ITEMS 128
  15. #define MAX_LINE_LENGTH 30
  16. // temporary FlipSocialFeed object
  17. static FlipSocialFeed flip_social_feed = {
  18. .usernames = {"JBlanked", "FlipperKing", "FlipperQueen"},
  19. .messages = {"Welcome. This is a temp message. Either the feed didn't load or there was a server error.", "I am the Chosen Flipper.", "No one can flip like me."},
  20. .is_flipped = {false, false, true},
  21. .ids = {0, 1, 2},
  22. .count = 3,
  23. .index = 0};
  24. bool flip_social_get_feed()
  25. {
  26. // Get the feed from the server
  27. if (app_instance->login_username_logged_out == NULL)
  28. {
  29. FURI_LOG_E(TAG, "Username is NULL");
  30. return false;
  31. }
  32. char command[256];
  33. snprintf(command, 128, "https://www.flipsocial.net/api/feed/20/%s/", app_instance->login_username_logged_out);
  34. bool success = flipper_http_get_request_with_headers(command, "{\"Content-Type\":\"application/json\"}");
  35. if (!success)
  36. {
  37. FURI_LOG_E(TAG, "Failed to send HTTP request for feed");
  38. return false;
  39. }
  40. fhttp.state = RECEIVING;
  41. return true;
  42. }
  43. bool flip_social_parse_json_feed()
  44. {
  45. // Parse the JSON feed
  46. if (fhttp.received_data != NULL)
  47. {
  48. jsmn_parser parser;
  49. jsmn_init(&parser);
  50. // Allocate tokens array on the heap
  51. jsmntok_t *tokens = malloc(sizeof(jsmntok_t) * MAX_TOKENS);
  52. if (tokens == NULL)
  53. {
  54. FURI_LOG_E(TAG, "Failed to allocate memory for JSON tokens.");
  55. return false;
  56. }
  57. int ret = jsmn_parse(&parser, fhttp.received_data, strlen(fhttp.received_data), tokens, MAX_TOKENS);
  58. if (ret < 0)
  59. {
  60. // Handle parsing errors
  61. FURI_LOG_E(TAG, "Failed to parse JSON: %d", ret);
  62. free(tokens);
  63. return false;
  64. }
  65. // Ensure that the root element is an object
  66. if (ret < 1 || tokens[0].type != JSMN_OBJECT)
  67. {
  68. FURI_LOG_E(TAG, "Root element is not an object.");
  69. free(tokens);
  70. return false;
  71. }
  72. // Initialize feed count
  73. flip_social_feed.count = 0;
  74. // Loop over all keys in the root object
  75. int i = 0;
  76. for (i = 1; i < ret; i++)
  77. {
  78. if (jsoneq(fhttp.received_data, &tokens[i], "feed") == 0)
  79. {
  80. // Found "feed" key
  81. jsmntok_t *feed_array = &tokens[i + 1];
  82. if (feed_array->type != JSMN_ARRAY)
  83. {
  84. FURI_LOG_E(TAG, "'feed' is not an array.");
  85. break;
  86. }
  87. int j, k;
  88. int feed_index = 0;
  89. // Iterate over the feed array
  90. for (j = 0; j < feed_array->size; j++)
  91. {
  92. int idx = i + 2; // Position of the first feed item
  93. for (k = 0; k < j; k++)
  94. {
  95. // Skip tokens of previous feed items
  96. idx += tokens[idx].size * 2 + 1;
  97. }
  98. if (idx >= ret)
  99. {
  100. FURI_LOG_E(TAG, "Index out of bounds while accessing feed items.");
  101. break;
  102. }
  103. jsmntok_t *item = &tokens[idx];
  104. if (item->type != JSMN_OBJECT)
  105. {
  106. FURI_LOG_E(TAG, "Feed item is not an object.");
  107. continue;
  108. }
  109. // Variables to hold item data
  110. char *username = NULL;
  111. char *message = NULL;
  112. int flipped = 0;
  113. int id = 0;
  114. // Iterate over keys in the feed item
  115. int l;
  116. int item_size = item->size;
  117. int item_idx = idx + 1; // Position of the first key in the item
  118. for (l = 0; l < item_size; l++)
  119. {
  120. if (item_idx + 1 >= ret)
  121. {
  122. FURI_LOG_E(TAG, "Index out of bounds while accessing item properties.");
  123. break;
  124. }
  125. jsmntok_t *key = &tokens[item_idx];
  126. jsmntok_t *val = &tokens[item_idx + 1];
  127. if (jsoneq(fhttp.received_data, key, "username") == 0)
  128. {
  129. username = strndup(fhttp.received_data + val->start, val->end - val->start);
  130. }
  131. else if (jsoneq(fhttp.received_data, key, "message") == 0)
  132. {
  133. message = strndup(fhttp.received_data + val->start, val->end - val->start);
  134. }
  135. else if (jsoneq(fhttp.received_data, key, "flipped") == 0)
  136. {
  137. if (val->type == JSMN_PRIMITIVE)
  138. {
  139. if (strncmp(fhttp.received_data + val->start, "true", val->end - val->start) == 0)
  140. flipped = 1;
  141. else
  142. flipped = 0;
  143. }
  144. }
  145. else if (jsoneq(fhttp.received_data, key, "id") == 0)
  146. {
  147. if (val->type == JSMN_PRIMITIVE)
  148. {
  149. char id_str[16] = {0};
  150. uint32_t id_len = val->end - val->start;
  151. if (id_len >= sizeof(id_str))
  152. id_len = sizeof(id_str) - 1;
  153. strncpy(id_str, fhttp.received_data + val->start, id_len);
  154. id = atoi(id_str);
  155. }
  156. }
  157. item_idx += 2; // Move to the next key-value pair
  158. }
  159. // Store the data in flip_social_feed
  160. if (username && message && feed_index < MAX_FEED_ITEMS)
  161. {
  162. flip_social_feed.usernames[feed_index] = username;
  163. flip_social_feed.messages[feed_index] = message;
  164. flip_social_feed.is_flipped[feed_index] = flipped;
  165. flip_social_feed.ids[feed_index] = id;
  166. feed_index++;
  167. flip_social_feed.count = feed_index;
  168. }
  169. else
  170. {
  171. // Free allocated memory if not stored
  172. if (username)
  173. free(username);
  174. if (message)
  175. free(message);
  176. }
  177. }
  178. break; // Feed processed
  179. }
  180. }
  181. free(tokens); // Free the allocated tokens array
  182. }
  183. else
  184. {
  185. FURI_LOG_E(TAG, "No data received.");
  186. return false;
  187. }
  188. return true;
  189. }
  190. bool flip_social_board_is_active(Canvas *canvas)
  191. {
  192. if (fhttp.state == INACTIVE)
  193. {
  194. canvas_draw_str(canvas, 0, 7, "Wifi Dev Board disconnected.");
  195. canvas_draw_str(canvas, 0, 17, "Please connect to the board.");
  196. canvas_draw_str(canvas, 0, 32, "If your board is connected,");
  197. canvas_draw_str(canvas, 0, 42, "make sure you have flashed");
  198. canvas_draw_str(canvas, 0, 52, "your WiFi Devboard with the");
  199. canvas_draw_str(canvas, 0, 62, "latest FlipperHTTP flash.");
  200. return false;
  201. }
  202. return true;
  203. }
  204. void flip_social_handle_error(Canvas *canvas)
  205. {
  206. if (fhttp.received_data != NULL)
  207. {
  208. if (strstr(fhttp.received_data, "[ERROR] Not connected to Wifi. Failed to reconnect.") != NULL)
  209. {
  210. canvas_clear(canvas);
  211. canvas_draw_str(canvas, 0, 10, "[ERROR] Not connected to Wifi.");
  212. canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
  213. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  214. }
  215. else if (strstr(fhttp.received_data, "[ERROR] Failed to connect to Wifi.") != NULL)
  216. {
  217. canvas_clear(canvas);
  218. canvas_draw_str(canvas, 0, 10, "[ERROR] Not connected to Wifi.");
  219. canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
  220. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  221. }
  222. else
  223. {
  224. canvas_draw_str(canvas, 0, 42, "Failed...");
  225. canvas_draw_str(canvas, 0, 52, "Update your credentials.");
  226. canvas_draw_str(canvas, 0, 62, "Press BACK to return.");
  227. }
  228. }
  229. else
  230. {
  231. canvas_draw_str(canvas, 0, 42, "Failed...");
  232. canvas_draw_str(canvas, 0, 52, "Update your credentials.");
  233. canvas_draw_str(canvas, 0, 62, "Press BACK to return.");
  234. }
  235. }
  236. #endif // FLIP_SOCIAL_FEED_H