Conversation
… buttons for fill/send actions and improve message formatting.
* ci: add initial feature branch workflow using uv * test: fix webhook response assertion and messaging worker race condition
* isolate dev deployment resources and update sqlite web url * feat: support PORT env var with 5000 fallback
There was a problem hiding this comment.
This is the final PR Bugbot will review for you during this billing cycle
Your free Bugbot reviews will reset on January 31
Details
You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
| app = create_app() | ||
|
|
||
| if __name__ == "__main__": | ||
| port = int(os.environ.get("PORT", "5000")) # default for dev |
There was a problem hiding this comment.
Bug: Port variable defined but never passed to app.run()
The port variable is read from the environment variable PORT but never passed to app.run(). The server will always run on Flask's default port (5000) regardless of the PORT environment variable setting. The port variable needs to be passed to app.run(port=port) for the environment configuration to take effect.
backend/app/config/secrets.py
Outdated
|
|
||
| ASSEMBLYAI_API_KEY = "ceb6a3e8dc0e44e6a1c6581ac53ec35e" | ||
|
|
||
| OPENAI_API_KEY = "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" |
There was a problem hiding this comment.
Bug: Hardcoded API keys committed to repository
Sensitive API credentials for AssemblyAI and OpenAI are hardcoded directly in secrets.py. These keys provide access to paid external services and are now exposed in version control. This is a critical security vulnerability - the keys need to be immediately rotated and moved to environment variables or a secrets manager.
backend/app/logic/process_text.py
Outdated
|
|
||
| reminder = get_goal_reminder_by_goal_id(goal["id"]) | ||
|
|
||
| update_goal_reminder(reminder["id"], reminder_time=normalized_time) |
There was a problem hiding this comment.
Bug: Update reminder crashes when goal has no reminder
The update command retrieves a goal's reminder using get_goal_reminder_by_goal_id() which can return None if no reminder exists for that goal. The code then directly accesses reminder["id"] without checking if reminder is None, causing an unhandled TypeError crash when a user tries to update a reminder for a goal that was created before reminders were added or if reminder creation failed.
backend/app/helpers/vcard/vcard.py
Outdated
| Extracts phone_number from a vcard string. | ||
| """ | ||
| match: re.Match[str] = re.search(r"waid=([0-9]+)", vcard_str) | ||
| return match.group(1) |
There was a problem hiding this comment.
Bug: VCARD extraction crashes on missing waid field
The extract_phone_number function calls match.group(1) on the regex result without checking if match is None. When a VCARD string doesn't contain the expected waid= pattern, this causes an AttributeError: 'NoneType' object has no attribute 'group' crash. Not all VCARDs include the WhatsApp ID field.
| result = transcribe_audio(fake_audio) | ||
|
|
||
| assert result["status"] == "completed" | ||
| assert result["text"].lower() == "hello" or "hello." |
There was a problem hiding this comment.
Bug: Test assertion always evaluates to True
The assertion result["text"].lower() == "hello" or "hello." is incorrect due to operator precedence. It evaluates as (result["text"].lower() == "hello") or ("hello."), and since "hello." is a non-empty string (truthy), the assertion will always pass regardless of the actual transcription result. The intent was likely assert result["text"].lower() in ("hello", "hello.").
|
|
||
| result = transcribe_audio(fake_audio) | ||
|
|
||
| assert result["status"] == "completed" |
There was a problem hiding this comment.
Bug: Test expects dict but function returns string
The test calls transcribe_audio() and expects to access result["status"] and result["text"] as dictionary keys, but the function's return type is str (returning transcript["text"]). Attempting to subscript a string with "status" will raise TypeError: string indices must be integers, causing the test to always fail.
backend/app/db/operations/users.py
Outdated
|
|
||
| params.append(user_id) | ||
| with connect() as conn: | ||
| conn.execute(f"UPDATE users SET {', '.join(updates)} WHERE id = ?", params) |
There was a problem hiding this comment.
Bug: Missing empty updates check causes invalid SQL syntax
The update_user function lacks the defensive if not updates: return get_user(user_id) check that all other similar update functions have (update_rating, update_goal, update_user_state, update_goal_reminder). If called with no optional arguments, the SQL generated will be UPDATE users SET WHERE id = ? which is syntactically invalid and will raise a sqlite3.OperationalError.
df49e01 to
6891a48
Compare
Note
Adds a full Flask backend with DB ops and reminder service, overhauls messaging/emulator (SSE, attachments), enhances the WhatsApp client, introduces CI/deploy workflows, and expands docs/tests.
/emulatorand/webhookand end‑to‑end text/audio/vcard processing.log_queuewithLogBroadcaster(SSE) and supports outboundattachments(e.g., transcript files).MessageMedia.prompts.py, readsFLASK_ENV/PORTfrom env, exposesSQLITE_WEB_URL, sets SQLite autocommit.Written by Cursor Bugbot for commit df49e01. This will update automatically on new commits. Configure here.