Skip to content
This repository was archived by the owner on Jun 19, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/backend/app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ def create_app(settings: Settings | None = None) -> Flask:
# Blueprint routes
register_routes(app)

# Weekly digest scheduler – skipped when TESTING=true or DISABLE_SCHEDULER env var is set
import os as _os
if not _os.environ.get("TESTING") and not _os.environ.get("DISABLE_SCHEDULER"):
from .services.digest import init_digest_scheduler
init_digest_scheduler(app)

# Backward-compatible schema patch for existing databases.
with app.app_context():
_ensure_schema_compatibility(app)
Expand Down
2 changes: 2 additions & 0 deletions packages/backend/app/routes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from .categories import bp as categories_bp
from .docs import bp as docs_bp
from .dashboard import bp as dashboard_bp
from .digest import bp as digest_bp


def register_routes(app: Flask):
Expand All @@ -18,3 +19,4 @@ def register_routes(app: Flask):
app.register_blueprint(categories_bp, url_prefix="/categories")
app.register_blueprint(docs_bp, url_prefix="/docs")
app.register_blueprint(dashboard_bp, url_prefix="/dashboard")
app.register_blueprint(digest_bp, url_prefix="/digest")
50 changes: 50 additions & 0 deletions packages/backend/app/routes/digest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""Digest routes.

GET /digest/preview – return this week's digest data as JSON (auth required)
POST /digest/send-test – immediately email the digest to the authenticated user
"""
from flask import Blueprint, jsonify
from flask_jwt_extended import get_jwt_identity, jwt_required
import logging

from ..extensions import db
from ..models import User
from ..services.digest import build_weekly_digest, send_weekly_digest

bp = Blueprint("digest", __name__)
logger = logging.getLogger("finmind.digest")


@bp.get("/preview")
@jwt_required()
def preview_digest():
"""Return the current week's digest data as JSON for the authenticated user."""
uid = int(get_jwt_identity())
data = build_weekly_digest(uid)
logger.info("Digest preview requested by user=%s", uid)
return jsonify(data), 200


@bp.post("/send-test")
@jwt_required()
def send_test_digest():
"""Immediately send a digest email to the authenticated user.

Returns 200 when the email was dispatched via SMTP, or 202 when SMTP
is not configured (digest was built but not sent).
"""
uid = int(get_jwt_identity())
user = db.session.get(User, uid)
if not user:
return jsonify(error="user not found"), 404

ok = send_weekly_digest(user)
if ok:
logger.info("Test digest sent to user=%s (%s)", uid, user.email)
return jsonify(message="digest sent", email=user.email), 200

logger.info("Test digest built but not sent (SMTP unconfigured) user=%s", uid)
return jsonify(
message="digest built but not sent — configure SMTP_URL to enable email delivery",
email=user.email,
), 202
Loading