From 8b5b1b41b5386e43cf70bf7ede1b9e80d8b73b48 Mon Sep 17 00:00:00 2001 From: Cameron Aaron Date: Mon, 24 Jun 2024 09:32:58 -0700 Subject: [PATCH 1/2] added some new logging --- gae/main.py | 39 +++- src/comm.c | 579 ++++++++++++++++++++++++++-------------------------- 2 files changed, 331 insertions(+), 287 deletions(-) diff --git a/gae/main.py b/gae/main.py index c0bd00e..583c33a 100644 --- a/gae/main.py +++ b/gae/main.py @@ -12,6 +12,11 @@ from datetime import datetime, timedelta import uvicorn from starlette.middleware.sessions import SessionMiddleware +import logging + +# Configure logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) app = FastAPI() @@ -34,6 +39,7 @@ ).split() async def get_redis(): + logger.info("Connecting to Redis") redis = Redis.from_url(f"redis://:{redis_pass}@{redis_ip}:6379/0") return redis @@ -42,9 +48,13 @@ async def query_json(url, data): if not isinstance(data, str): data = urllib.parse.urlencode(data) async with aiohttp.ClientSession() as session: + logger.info(f"Sending request to {url} with data: {data}") async with session.post(url, headers=headers, data=data) as response: + logger.info(f"Response status: {response.status}") response.raise_for_status() - return await response.json() + result = await response.json() + logger.info(f"Response JSON: {result}") + return result @app.get('/auth') async def auth_redirect(): @@ -58,6 +68,7 @@ async def auth_redirect(): approval_prompt='force', include_granted_scopes='true', )) + logger.info(f"Redirecting to Google Auth URL: {url}") return RedirectResponse(url) def json_compactify(data): @@ -71,44 +82,58 @@ async def fetch_tokens(code): "redirect_uri": auth_redir_uri, "grant_type": "authorization_code", } + logger.info(f"Fetching tokens with code: {code}") result = await query_json("https://accounts.google.com/o/oauth2/token", q) if 'access_token' not in result: + logger.error(f"Failed to retrieve tokens: {result}") return {'error': 'Failed to retrieve tokens'} + logger.info(f"Tokens retrieved: {result}") return result def generate_passcode(): - return ' '.join(random.sample(WORDS, 4)) + passcode = ' '.join(random.sample(WORDS, 4)) + logger.info(f"Generated passcode: {passcode}") + return passcode @app.get('/auth/callback', response_class=HTMLResponse) async def auth_callback(request: Request, redis: Redis = Depends(get_redis)): code = request.query_params.get("code") if not code: + logger.error("Missing authorization code in callback request") raise HTTPException(status_code=400, detail="Missing authorization code") + logger.info(f"Authorization code received: {code}") tokens = await fetch_tokens(code) if 'error' in tokens: + logger.error(f"Error fetching tokens: {tokens['error']}") raise HTTPException(status_code=400, detail=tokens['error']) # Add token expiry time tokens['expires_at'] = (datetime.now() + timedelta(seconds=tokens['expires_in'])).timestamp() + logger.info(f"Tokens with expiry added: {tokens}") passcode = generate_passcode() await redis.setex(passcode, timedelta(minutes=10), json.dumps(tokens)) # Cache passcode with tokens for 10 minutes + logger.info(f"Stored tokens in Redis with passcode: {passcode}") return templates.TemplateResponse("intermediate.html", {"request": request, "passcode": passcode}) @app.post('/auth/check') async def auth_check(data: dict, redis: Redis = Depends(get_redis)): if 'passcode' not in data: + logger.error("Missing passcode in auth check request") raise HTTPException(status_code=400, detail="Missing passcode") passcode = data['passcode'] + logger.info(f"Checking tokens for passcode: {passcode}") tokens = await redis.get(passcode) if not tokens: + logger.error("Invalid or expired passcode") raise HTTPException(status_code=401, detail="Invalid or expired passcode") tokens = json.loads(tokens) + logger.info(f"Tokens retrieved for passcode: {tokens}") return tokens class AuthRefresh: @@ -120,24 +145,32 @@ async def refresh(refresh_token): "client_secret": client_secret, "grant_type": "refresh_token", } + logger.info(f"Refreshing token with refresh token: {refresh_token}") result = await query_json("https://accounts.google.com/o/oauth2/token", q) if 'access_token' not in result: + logger.error(f"Failed to refresh token: {result}") return None result['expires_at'] = (datetime.now() + timedelta(seconds=result['expires_in'])).timestamp() + logger.info(f"Refreshed tokens: {result}") return result @app.post('/refresh_token') async def refresh_access_token(data: dict): if 'refresh_token' not in data: + logger.error("Missing refresh token in request") raise HTTPException(status_code=400, detail="Missing refresh token") refresh_token = data['refresh_token'] + logger.info(f"Refreshing access token for refresh token: {refresh_token}") new_tokens = await AuthRefresh.refresh(refresh_token) if new_tokens: + logger.info(f"New tokens obtained: {new_tokens}") return new_tokens else: + logger.error("Failed to refresh access token") raise HTTPException(status_code=401, detail="Failed to refresh access token") if __name__ == '__main__': - uvicorn.run(app, host='0.0.0.0', port=8000) \ No newline at end of file + logger.info("Starting server") + uvicorn.run(app, host='0.0.0.0', port=8000) diff --git a/src/comm.c b/src/comm.c index 468bbdd..5cbda55 100644 --- a/src/comm.c +++ b/src/comm.c @@ -14,326 +14,337 @@ static void *comm_js_ready_cb_data; static int comm_array_size = -1; static bool comm_is_bluetooth_available() { - if(!bluetooth_connection_service_peek()) { - sb_show("No bluetooth connection!"); - return false; - } - return true; + if(!bluetooth_connection_service_peek()) { + sb_show("No bluetooth connection!"); + return false; + } + return true; } + bool comm_is_available() { - if(!comm_is_bluetooth_available()) - return false; - if(!comm_js_ready) { - sb_show("JS not available, please try again later"); - return false; - } - return true; + if(!comm_is_bluetooth_available()) + return false; + if(!comm_js_ready) { + sb_show("JS not available, please try again later"); + return false; + } + return true; } + bool comm_is_available_silent() { - return bluetooth_connection_service_peek() && comm_js_ready; + return bluetooth_connection_service_peek() && comm_js_ready; } void comm_query_tasklists_cb(void *arg) { - comm_query_tasklists(); + comm_query_tasklists(); } + void comm_query_tasklists() { - if(!comm_js_ready) { - comm_js_ready_cb = comm_query_tasklists_cb; - sb_show("Waiting for JS..."); - comm_is_bluetooth_available(); // check bluetooth connection and show message if needed - return; - } - if(!comm_is_available()) - return; - sb_show("Connecting..."); - LOG("Querying tasklists"); - DictionaryIterator *iter; - Tuplet code = TupletInteger(KEY_CODE, CODE_GET); - Tuplet scope = TupletInteger(KEY_SCOPE, SCOPE_LISTS); - - app_message_outbox_begin(&iter); - dict_write_tuplet(iter, &code); - dict_write_tuplet(iter, &scope); - app_message_outbox_send(); + if(!comm_js_ready) { + comm_js_ready_cb = comm_query_tasklists_cb; + sb_show("Waiting for JS..."); + comm_is_bluetooth_available(); // check bluetooth connection and show message if needed + return; + } + if(!comm_is_available()) + return; + sb_show("Connecting..."); + LOG("Querying tasklists"); + DictionaryIterator *iter; + Tuplet code = TupletInteger(KEY_CODE, CODE_GET); + Tuplet scope = TupletInteger(KEY_SCOPE, SCOPE_LISTS); + + app_message_outbox_begin(&iter); + dict_write_tuplet(iter, &code); + dict_write_tuplet(iter, &scope); + app_message_outbox_send(); } + void comm_query_tasks_cb(void *arg) { - comm_query_tasks((int)arg); + comm_query_tasks((int)arg); } + void comm_query_tasks(int listId) { - if(!comm_js_ready) { - comm_js_ready_cb = comm_query_tasks_cb; - comm_js_ready_cb_data = (void*)listId; - comm_is_available(); // show message if needed - return; - } - if(!comm_is_available()) - return; - sb_show("Connecting..."); - LOG("Querying tasks for listId=%d", listId); - DictionaryIterator *iter; - Tuplet code = TupletInteger(KEY_CODE, CODE_GET); - Tuplet scope = TupletInteger(KEY_SCOPE, SCOPE_TASKS); - Tuplet tListId = TupletInteger(KEY_LISTID, listId); - - app_message_outbox_begin(&iter); - dict_write_tuplet(iter, &code); - dict_write_tuplet(iter, &scope); - dict_write_tuplet(iter, &tListId); - app_message_outbox_send(); + if(!comm_js_ready) { + comm_js_ready_cb = comm_query_tasks_cb; + comm_js_ready_cb_data = (void*)listId; + comm_is_available(); // show message if needed + return; + } + if(!comm_is_available()) + return; + sb_show("Connecting..."); + LOG("Querying tasks for listId=%d", listId); + DictionaryIterator *iter; + Tuplet code = TupletInteger(KEY_CODE, CODE_GET); + Tuplet scope = TupletInteger(KEY_SCOPE, SCOPE_TASKS); + Tuplet tListId = TupletInteger(KEY_LISTID, listId); + + app_message_outbox_begin(&iter); + dict_write_tuplet(iter, &code); + dict_write_tuplet(iter, &scope); + dict_write_tuplet(iter, &tListId); + app_message_outbox_send(); } + void comm_query_task_details(int listId, int taskId) { - LOG("Querying task details for %d, %d (not implemented)", listId, taskId); + LOG("Querying task details for %d, %d (not implemented)", listId, taskId); } void comm_update_task_status(int listId, int taskId, bool newStatus) { - if(!comm_is_available()) - return; - LOG("Updating status for task %d->%d to %d (NI)", listId, taskId, newStatus); - sb_show("Updating..."); - DictionaryIterator *iter; - Tuplet code = TupletInteger(KEY_CODE, CODE_UPDATE); - Tuplet scope = TupletInteger(KEY_SCOPE, SCOPE_TASK); - Tuplet tListId = TupletInteger(KEY_LISTID, listId); - Tuplet tTaskId = TupletInteger(KEY_TASKID, taskId); - Tuplet tIsDone = TupletInteger(KEY_ISDONE, newStatus); - - app_message_outbox_begin(&iter); - dict_write_tuplet(iter, &code); - dict_write_tuplet(iter, &scope); - dict_write_tuplet(iter, &tListId); - dict_write_tuplet(iter, &tTaskId); - dict_write_tuplet(iter, &tIsDone); - app_message_outbox_send(); + if(!comm_is_available()) + return; + LOG("Updating status for task %d->%d to %d (NI)", listId, taskId, newStatus); + sb_show("Updating..."); + DictionaryIterator *iter; + Tuplet code = TupletInteger(KEY_CODE, CODE_UPDATE); + Tuplet scope = TupletInteger(KEY_SCOPE, SCOPE_TASK); + Tuplet tListId = TupletInteger(KEY_LISTID, listId); + Tuplet tTaskId = TupletInteger(KEY_TASKID, taskId); + Tuplet tIsDone = TupletInteger(KEY_ISDONE, newStatus); + + app_message_outbox_begin(&iter); + dict_write_tuplet(iter, &code); + dict_write_tuplet(iter, &scope); + dict_write_tuplet(iter, &tListId); + dict_write_tuplet(iter, &tTaskId); + dict_write_tuplet(iter, &tIsDone); + app_message_outbox_send(); } void comm_create_task(int listId, char* title, char* notes) { - if(!comm_is_available()) { - // TODO: alert? - return; - } - LOG("Creating new task with title %s in list %d", title, listId); - sb_show("Creating..."); - DictionaryIterator *iter; - Tuplet code = TupletInteger(KEY_CODE, CODE_POST); - Tuplet scope = TupletInteger(KEY_SCOPE, SCOPE_TASK); - Tuplet tListId = TupletInteger(KEY_LISTID, listId); - Tuplet tTitle = TupletCString(KEY_TITLE, title); - - app_message_outbox_begin(&iter); - dict_write_tuplet(iter, &code); - dict_write_tuplet(iter, &scope); - dict_write_tuplet(iter, &tListId); - dict_write_tuplet(iter, &tTitle); - if(notes) { - Tuplet tNotes = TupletCString(KEY_NOTES, notes); - dict_write_tuplet(iter, &tNotes); - } - app_message_outbox_send(); + if(!comm_is_available()) { + // TODO: alert? + return; + } + LOG("Creating new task with title %s in list %d", title, listId); + sb_show("Creating..."); + DictionaryIterator *iter; + Tuplet code = TupletInteger(KEY_CODE, CODE_POST); + Tuplet scope = TupletInteger(KEY_SCOPE, SCOPE_TASK); + Tuplet tListId = TupletInteger(KEY_LISTID, listId); + Tuplet tTitle = TupletCString(KEY_TITLE, title); + + app_message_outbox_begin(&iter); + dict_write_tuplet(iter, &code); + dict_write_tuplet(iter, &scope); + dict_write_tuplet(iter, &tListId); + dict_write_tuplet(iter, &tTitle); + if(notes) { + Tuplet tNotes = TupletCString(KEY_NOTES, notes); + dict_write_tuplet(iter, &tNotes); + } + app_message_outbox_send(); } void comm_retrieve_tokens() { - // loading - char *szAccessToken = NULL, *szRefreshToken = NULL; - int size; - if(persist_exists(KEY_REFRESH_TOKEN)) { // use the same keys for appMessage and for storage - size = persist_get_size(KEY_REFRESH_TOKEN); - szRefreshToken = malloc(size); - persist_read_string(KEY_REFRESH_TOKEN, szRefreshToken, size); - LOG("got refresh token: %s", szRefreshToken); - - if(persist_exists(KEY_ACCESS_TOKEN)) { // only try access token if we have refresh token, as AT alone is not useful - size = persist_get_size(KEY_ACCESS_TOKEN); - szAccessToken = malloc(size); - persist_read_string(KEY_ACCESS_TOKEN, szAccessToken, size); - LOG("got access token: %s", szRefreshToken); - } - } - - // sending - DictionaryIterator *iter; - app_message_outbox_begin(&iter); - Tuplet code = TupletInteger(KEY_CODE, CODE_RETRIEVE_TOKEN); - dict_write_tuplet(iter, &code); - if(szAccessToken) { - Tuplet tAccessToken = TupletCString(KEY_ACCESS_TOKEN, szAccessToken); - dict_write_tuplet(iter, &tAccessToken); - } - if(szRefreshToken) { - Tuplet tRefreshToken = TupletCString(KEY_REFRESH_TOKEN, szRefreshToken); - dict_write_tuplet(iter, &tRefreshToken); - } - app_message_outbox_send(); - - if(szAccessToken) - free(szAccessToken); - if(szRefreshToken) - free(szRefreshToken); + // loading + char *szAccessToken = NULL, *szRefreshToken = NULL; + int size; + if(persist_exists(KEY_REFRESH_TOKEN)) { // use the same keys for appMessage and for storage + size = persist_get_size(KEY_REFRESH_TOKEN); + szRefreshToken = malloc(size); + persist_read_string(KEY_REFRESH_TOKEN, szRefreshToken, size); + LOG("got refresh token: %s", szRefreshToken); + + if(persist_exists(KEY_ACCESS_TOKEN)) { // only try access token if we have refresh token, as AT alone is not useful + size = persist_get_size(KEY_ACCESS_TOKEN); + szAccessToken = malloc(size); + persist_read_string(KEY_ACCESS_TOKEN, szAccessToken, size); + LOG("got access token: %s", szRefreshToken); + } + } + + // sending + DictionaryIterator *iter; + app_message_outbox_begin(&iter); + Tuplet code = TupletInteger(KEY_CODE, CODE_RETRIEVE_TOKEN); + dict_write_tuplet(iter, &code); + if(szAccessToken) { + Tuplet tAccessToken = TupletCString(KEY_ACCESS_TOKEN, szAccessToken); + dict_write_tuplet(iter, &tAccessToken); + } + if(szRefreshToken) { + Tuplet tRefreshToken = TupletCString(KEY_REFRESH_TOKEN, szRefreshToken); + dict_write_tuplet(iter, &tRefreshToken); + } + app_message_outbox_send(); + + if(szAccessToken) + free(szAccessToken); + if(szRefreshToken) + free(szRefreshToken); } static void comm_in_received_handler(DictionaryIterator *iter, void *context) { - Tuple *tCode, *tMessage, *tScope; - - LOG("Used: %d, free: %d", heap_bytes_used(), heap_bytes_free()); - - tCode = dict_find(iter, KEY_CODE); - assert(tCode, "Message without code"); - int code = (int)tCode->value->int32; - LOG("Message code: %d", code); - - if(code == CODE_ERROR) { - tMessage = dict_find(iter, KEY_ERROR); - char* message = "Unknown error"; - if(tMessage && tMessage->type == TUPLE_CSTRING) - message = tMessage->value->cstring; - LOG("Error received: %s", message); - sb_show(message); - return; - } else if(code == CODE_SAVE_TOKEN) { // JS wants to save token - LOG("Saving tokens"); - Tuple *tAccessToken = dict_find(iter, KEY_ACCESS_TOKEN); - if(tAccessToken && tAccessToken->type == TUPLE_CSTRING) - persist_write_string(KEY_ACCESS_TOKEN, tAccessToken->value->cstring); // use the same key for storage as for appMessage - else // if no token was passed, assume logout - delete saved token - persist_delete(KEY_ACCESS_TOKEN); - - Tuple *tRefreshToken = dict_find(iter, KEY_REFRESH_TOKEN); - if(tRefreshToken && tRefreshToken->type == TUPLE_CSTRING) - persist_write_string(KEY_REFRESH_TOKEN, tAccessToken->value->cstring); - else - persist_delete(KEY_REFRESH_TOKEN); - - return; - } else if(code == CODE_RETRIEVE_TOKEN) { // JS requires saved token - LOG("Retrieving tokens"); - comm_retrieve_tokens(); - return; - } else if(code == CODE_SET_OPTION) { - LOG("Updating option"); - Tuple *tOptionId = dict_find(iter, KEY_OPTION_ID); - Tuple *tOptionVal = dict_find(iter, KEY_OPTION_VALUE); - options_update(tOptionId->value->int32, tOptionVal->value->int32); - return; - } else if(code == CODE_READY) { // JS just loaded - comm_js_ready = true; - if(comm_js_ready_cb) { - LOG("JS Ready Callback awaiting, calling"); - comm_js_ready_cb(comm_js_ready_cb_data); - } - return; - } - - tScope = dict_find(iter, KEY_SCOPE); - assert(tScope, "No scope!"); - int scope = (int)tScope->value->int32; - LOG("Message scope: %d", scope); - - if(scope == SCOPE_LISTS) { - // this might be legal if we auto-switched to the only list - //assert(tl_is_active(), "Ignoring TaskLists-related message because that list is inactive"); - } else if(scope == SCOPE_TASKS) { - assert(ts_is_active(), "Ignoring Tasks-related message because tasks is inactive"); - } else if(scope == SCOPE_TASK) { - assert(ts_is_active()||ti_is_active(), "Ignoring Task-related message because neither tasks nor taskinfo is inactive"); - } else { - APP_LOG(APP_LOG_LEVEL_ERROR, "Unexpected scope: %d", scope); - return; - } - - if(code == CODE_ARRAY_START) { - int count = (int)dict_find(iter, KEY_COUNT)->value->int32; - LOG("Items count: %d", count); - comm_array_size = count; - if(scope == SCOPE_LISTS) - tl_set_count(count); - else if(scope == SCOPE_TASKS) - ts_set_count(count); - else LOG("Err!"); - snprintf(sb_printf_alloc(32), 32, "Loading..."); - sb_printf_update(); - } else if(code == CODE_ARRAY_ITEM) { - assert(comm_array_size > 0, "Unexpected array_item!"); - int i = (int)dict_find(iter, KEY_ITEM)->value->int32; - assert(i < comm_array_size, "Index %d exceeds size %d", i, comm_array_size); - snprintf(sb_printf_get(), 32, "Loading... %d%%", - 100 * (i+1) / comm_array_size); - sb_printf_update(); - LOG("Statusbar Updated: %d", 100 * (i+1) / comm_array_size); - char *title = dict_find(iter, KEY_TITLE)->value->cstring; - if(scope == SCOPE_LISTS) { - int listId = (int)dict_find(iter, KEY_LISTID)->value->int32; - LOG("Item No: %d, Id=%d", i, listId); - tl_set_item(i, (TL_Item){ - .id = listId, - .title = title, - }); - } else { - // TODO: check listId? - int taskId = (int)dict_find(iter, KEY_TASKID)->value->int32; - Tuple *tNotes = dict_find(iter, KEY_NOTES); - char *notes = NULL; - if(tNotes) - notes = tNotes->value->cstring; - bool isDone = (bool)dict_find(iter, KEY_ISDONE)->value->int32; - LOG("Item No: %d, Id=%d, done=%d", i, taskId, isDone); - ts_set_item(i, (TS_Item){ - .id = taskId, - .done = isDone, - .title = title, - .notes = notes, - }); - } - } else if(code == CODE_ITEM_UPDATED) { - assert(scope == SCOPE_TASK, "Unexpected scope %d, expected TASK", scope); - int listId = (int)dict_find(iter, KEY_LISTID)->value->int32; - assert(listId == ts_current_listId(), "Ignoring message for non-current listId %d, current is %d", listId, ts_current_listId()); - int taskId = (int)dict_find(iter, KEY_TASKID)->value->int32; - bool isDone = (bool)dict_find(iter, KEY_ISDONE)->value->int32; - LOG("List id: %d, Item id: %d, New status: %d", listId, taskId, isDone); - ts_update_item_state_by_id(taskId, isDone); - sb_hide(); // hide "Updating" message - } else if(code == CODE_ITEM_ADDED) { - assert(scope == SCOPE_TASKS, "Unexpected scope %d, expected TASKS", scope); - int listId = (int)dict_find(iter, KEY_LISTID)->value->int32; - assert(listId == ts_current_listId(), "Ignoring message for non-current listId %d, current is %d", listId, ts_current_listId()); - int taskId = (int)dict_find(iter, KEY_TASKID)->value->int32; - char *title = dict_find(iter, KEY_TITLE)->value->cstring; - Tuple *tNotes = dict_find(iter, KEY_NOTES); - char *notes = NULL; - if(tNotes) - notes = tNotes->value->cstring; - bool isDone = (bool)dict_find(iter, KEY_ISDONE)->value->int32; - LOG("Item Id=%d, done=%d", taskId, isDone); - ts_append_item((TS_Item){ - .id = taskId, - .done = isDone, - .title = title, - .notes = notes, - }); - sb_hide(); // hide "Creating" message - } else if(code == CODE_ARRAY_END) { - comm_array_size = -1; // no current array - sb_hide(); // hide load percentage - } else { - LOG("Unexpected message code: %d", code); - } + Tuple *tCode, *tMessage, *tScope; + + LOG("Used: %d, free: %d", heap_bytes_used(), heap_bytes_free()); + + tCode = dict_find(iter, KEY_CODE); + assert(tCode, "Message without code"); + int code = (int)tCode->value->int32; + LOG("Message code: %d", code); + + if(code == CODE_ERROR) { + tMessage = dict_find(iter, KEY_ERROR); + char* message = "Unknown error"; + if(tMessage && tMessage->type == TUPLE_CSTRING) + message = tMessage->value->cstring; + LOG("Error received: %s", message); + sb_show(message); + return; + } else if(code == CODE_SAVE_TOKEN) { // JS wants to save token + LOG("Saving tokens"); + Tuple *tAccessToken = dict_find(iter, KEY_ACCESS_TOKEN); + if(tAccessToken && tAccessToken->type == TUPLE_CSTRING) + persist_write_string(KEY_ACCESS_TOKEN, tAccessToken->value->cstring); // use the same key for storage as for appMessage + else // if no token was passed, assume logout - delete saved token + persist_delete(KEY_ACCESS_TOKEN); + + Tuple *tRefreshToken = dict_find(iter, KEY_REFRESH_TOKEN); + if(tRefreshToken && tRefreshToken->type == TUPLE_CSTRING) + persist_write_string(KEY_REFRESH_TOKEN, tAccessToken->value->cstring); + else + persist_delete(KEY_REFRESH_TOKEN); + + return; + } else if(code == CODE_RETRIEVE_TOKEN) { // JS requires saved token + LOG("Retrieving tokens"); + comm_retrieve_tokens(); + return; + } else if(code == CODE_SET_OPTION) { + LOG("Updating option"); + Tuple *tOptionId = dict_find(iter, KEY_OPTION_ID); + Tuple *tOptionVal = dict_find(iter, KEY_OPTION_VALUE); + options_update(tOptionId->value->int32, tOptionVal->value->int32); + return; + } else if(code == CODE_READY) { // JS just loaded + comm_js_ready = true; + if(comm_js_ready_cb) { + LOG("JS Ready Callback awaiting, calling"); + comm_js_ready_cb(comm_js_ready_cb_data); + } + return; + } + + tScope = dict_find(iter, KEY_SCOPE); + assert(tScope, "No scope!"); + int scope = (int)tScope->value->int32; + LOG("Message scope: %d", scope); + + if(scope == SCOPE_LISTS) { + // this might be legal if we auto-switched to the only list + //assert(tl_is_active(), "Ignoring TaskLists-related message because that list is inactive"); + } else if(scope == SCOPE_TASKS) { + assert(ts_is_active(), "Ignoring Tasks-related message because tasks is inactive"); + } else if(scope == SCOPE_TASK) { + assert(ts_is_active()||ti_is_active(), "Ignoring Task-related message because neither tasks nor taskinfo is inactive"); + } else { + APP_LOG(APP_LOG_LEVEL_ERROR, "Unexpected scope: %d", scope); + return; + } + + if(code == CODE_ARRAY_START) { + int count = (int)dict_find(iter, KEY_COUNT)->value->int32; + LOG("Items count: %d", count); + comm_array_size = count; + if(scope == SCOPE_LISTS) + tl_set_count(count); + else if(scope == SCOPE_TASKS) + ts_set_count(count); + else LOG("Err!"); + snprintf(sb_printf_alloc(32), 32, "Loading..."); + sb_printf_update(); + } else if(code == CODE_ARRAY_ITEM) { + assert(comm_array_size > 0, "Unexpected array_item!"); + int i = (int)dict_find(iter, KEY_ITEM)->value->int32; + assert(i < comm_array_size, "Index %d exceeds size %d", i, comm_array_size); + snprintf(sb_printf_get(), 32, "Loading... %d%%", + 100 * (i+1) / comm_array_size); + sb_printf_update(); + LOG("Statusbar Updated: %d", 100 * (i+1) / comm_array_size); + char *title = dict_find(iter, KEY_TITLE)->value->cstring; + if(scope == SCOPE_LISTS) { + int listId = (int)dict_find(iter, KEY_LISTID)->value->int32; + LOG("Item No: %d, Id=%d", i, listId); + tl_set_item(i, (TL_Item){ + .id = listId, + .title = title, + }); + } else { + // TODO: check listId? + int taskId = (int)dict_find(iter, KEY_TASKID)->value->int32; + Tuple *tNotes = dict_find(iter, KEY_NOTES); + char *notes = NULL; + if(tNotes) + notes = tNotes->value->cstring; + bool isDone = (bool)dict_find(iter, KEY_ISDONE)->value->int32; + LOG("Item No: %d, Id=%d, done=%d", i, taskId, isDone); + ts_set_item(i, (TS_Item){ + .id = taskId, + .done = isDone, + .title = title, + .notes = notes, + }); + } + } else if(code == CODE_ITEM_UPDATED) { + assert(scope == SCOPE_TASK, "Unexpected scope %d, expected TASK", scope); + int listId = (int)dict_find(iter, KEY_LISTID)->value->int32; + assert(listId == ts_current_listId(), "Ignoring message for non-current listId %d, current is %d", listId, ts_current_listId()); + int taskId = (int)dict_find(iter, KEY_TASKID)->value->int32; + bool isDone = (bool)dict_find(iter, KEY_ISDONE)->value->int32; + LOG("List id: %d, Item id: %d, New status: %d", listId, taskId, isDone); + ts_update_item_state_by_id(taskId, isDone); + sb_hide(); // hide "Updating" message + } else if(code == CODE_ITEM_ADDED) { + assert(scope == SCOPE_TASKS, "Unexpected scope %d, expected TASKS", scope); + int listId = (int)dict_find(iter, KEY_LISTID)->value->int32; + assert(listId == ts_current_listId(), "Ignoring message for non-current listId %d, current is %d", listId, ts_current_listId()); + int taskId = (int)dict_find(iter, KEY_TASKID)->value->int32; + char *title = dict_find(iter, KEY_TITLE)->value->cstring; + Tuple *tNotes = dict_find(iter, KEY_NOTES); + char *notes = NULL; + if(tNotes) + notes = tNotes->value->cstring; + bool isDone = (bool)dict_find(iter, KEY_ISDONE)->value->int32; + LOG("Item Id=%d, done=%d", taskId, isDone); + ts_append_item((TS_Item){ + .id = taskId, + .done = isDone, + .title = title, + .notes = notes, + }); + sb_hide(); // hide "Creating" message + } else if(code == CODE_ARRAY_END) { + comm_array_size = -1; // no current array + sb_hide(); // hide load percentage + } else { + LOG("Unexpected message code: %d", code); + } } + static void comm_in_dropped_handler(AppMessageResult reason, void *context) { - LOG("Message dropped: reason=%d", reason); + LOG("Message dropped: reason=%d", reason); } + static void comm_out_sent_handler(DictionaryIterator *sent, void *context) { - LOG("Message sent"); + LOG("Message sent"); } + static void comm_out_failed_handler(DictionaryIterator *failed, AppMessageResult reason, void *context) { - LOG("Message send failed: reason=%d", reason); + LOG("Message send failed: reason=%d", reason); } + void comm_init() { - app_message_register_inbox_received(comm_in_received_handler); - app_message_register_inbox_dropped(comm_in_dropped_handler); - app_message_register_outbox_sent(comm_out_sent_handler); - app_message_register_outbox_failed(comm_out_failed_handler); + app_message_register_inbox_received(comm_in_received_handler); + app_message_register_inbox_dropped(comm_in_dropped_handler); + app_message_register_outbox_sent(comm_out_sent_handler); + app_message_register_outbox_failed(comm_out_failed_handler); - app_message_open(MIN(app_message_inbox_size_maximum(), OUTBOX_DESIRED_MAX), APP_MESSAGE_OUTBOX_SIZE_MINIMUM); // We only need large buffer for inbox + app_message_open(MIN(app_message_inbox_size_maximum(), OUTBOX_DESIRED_MAX), APP_MESSAGE_OUTBOX_SIZE_MINIMUM); // We only need large buffer for inbox } + void comm_deinit() { - app_message_deregister_callbacks(); + app_message_deregister_callbacks(); } From 38eb7e6281706793acf3fca2ff249c4b4d631639 Mon Sep 17 00:00:00 2001 From: Cameron Aaron Date: Mon, 24 Jun 2024 10:35:36 -0700 Subject: [PATCH 2/2] added logging --- gae/requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gae/requirements.txt b/gae/requirements.txt index 8c3b65d..12f267c 100644 --- a/gae/requirements.txt +++ b/gae/requirements.txt @@ -4,4 +4,5 @@ aiohttp redis==4.6.0 jinja2 python-dotenv -itsdangerous \ No newline at end of file +itsdangerous +logging \ No newline at end of file