Skip to content

Integration w49#42

Closed
jmoraispk wants to merge 22 commits intomainfrom
dev
Closed

Integration w49#42
jmoraispk wants to merge 22 commits intomainfrom
dev

Conversation

@jmoraispk
Copy link
Owner

@jmoraispk jmoraispk commented Dec 6, 2025

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.

  • Backend (new Flask app):
    • Introduces Flask app factory with routes for /emulator and /webhook and end‑to‑end text/audio/vcard processing.
    • Adds database layer (SQLite client, SQL ops for users/goals/ratings/reminders/states/audio_journals) and reminder service worker.
    • Implements audio journaling (transcribe + summarize) and rich text command handlers (goals, rate, week, lookback, reminders, journaling, transcript toggle).
  • Core messaging & Emulator:
    • Replaces log_queue with LogBroadcaster (SSE) and supports outbound attachments (e.g., transcript files).
    • Upgrades emulator UI (presets, audio recording + visualizer, DB link) and SSE handling for transcript files.
  • WhatsApp client:
    • Handles backend responses more robustly and sends transcript files via MessageMedia.
  • Config/Settings:
    • Moves OpenAI prompt to prompts.py, reads FLASK_ENV/PORT from env, exposes SQLITE_WEB_URL, sets SQLite autocommit.
  • CI/CD & Docs:
    • Adds CI workflow (ruff, pytest+coverage) and dev deploy workflow.
    • Adds API/developer docs and diagrams; updates MkDocs nav.
  • Tests:
    • Comprehensive tests for DB ops, helpers, services, routes, and logic.

Written by Cursor Bugbot for commit df49e01. This will update automatically on new commits. Configure here.

hafiz-ahtasham-ali and others added 22 commits December 2, 2025 13:52
… 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
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web


ASSEMBLYAI_API_KEY = "ceb6a3e8dc0e44e6a1c6581ac53ec35e"

OPENAI_API_KEY = "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"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web


reminder = get_goal_reminder_by_goal_id(goal["id"])

update_goal_reminder(reminder["id"], reminder_time=normalized_time)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

Extracts phone_number from a vcard string.
"""
match: re.Match[str] = re.search(r"waid=([0-9]+)", vcard_str)
return match.group(1)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

result = transcribe_audio(fake_audio)

assert result["status"] == "completed"
assert result["text"].lower() == "hello" or "hello."
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.").

Fix in Cursor Fix in Web


result = transcribe_audio(fake_audio)

assert result["status"] == "completed"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web


params.append(user_id)
with connect() as conn:
conn.execute(f"UPDATE users SET {', '.join(updates)} WHERE id = ?", params)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants