""" Rewards API - variable reward system for routine completion """ import os import uuid import random import flask import jwt import core.auth as auth import core.postgres as postgres def _get_user_uuid(token): try: payload = jwt.decode(token, os.getenv("JWT_SECRET"), algorithms=["HS256"]) return payload.get("sub") except (jwt.ExpiredSignatureError, jwt.InvalidTokenError): return None def _auth(request): header = request.headers.get("Authorization", "") if not header.startswith("Bearer "): return None token = header[7:] user_uuid = _get_user_uuid(token) if not user_uuid or not auth.verifyLoginToken(token, userUUID=user_uuid): return None return user_uuid def register(app): @app.route("/api/rewards/random", methods=["GET"]) def api_getRandomReward(): """Get a weighted random reward. Query: ?context=completion""" user_uuid = _auth(flask.request) if not user_uuid: return flask.jsonify({"error": "unauthorized"}), 401 context = flask.request.args.get("context", "completion") # Fetch all rewards from pool all_rewards = postgres.select("reward_pool", where={}) if not all_rewards: return flask.jsonify({"reward": None}), 200 # Weight by rarity: common=70%, uncommon=25%, rare=5% weights = { "common": 70, "uncommon": 25, "rare": 5, } weighted = [] for reward in all_rewards: w = weights.get(reward.get("rarity", "common"), 70) weighted.extend([reward] * w) if not weighted: return flask.jsonify({"reward": None}), 200 selected = random.choice(weighted) # Record that user earned this reward try: postgres.insert("user_rewards", { "id": str(uuid.uuid4()), "user_uuid": user_uuid, "reward_id": selected["id"], "context": context, }) except Exception: pass # Don't fail if recording fails return flask.jsonify({ "reward": { "id": selected["id"], "category": selected["category"], "content": selected["content"], "emoji": selected.get("emoji"), "rarity": selected.get("rarity", "common"), } }), 200 @app.route("/api/rewards/history", methods=["GET"]) def api_getRewardHistory(): """Get user's past earned rewards.""" user_uuid = _auth(flask.request) if not user_uuid: return flask.jsonify({"error": "unauthorized"}), 401 earned = postgres.select( "user_rewards", where={"user_uuid": user_uuid}, order_by="earned_at DESC", limit=50, ) # Enrich with reward content result = [] for entry in earned: reward = postgres.select_one("reward_pool", {"id": entry["reward_id"]}) if reward: result.append({ "earned_at": entry["earned_at"], "context": entry.get("context"), "category": reward["category"], "content": reward["content"], "emoji": reward.get("emoji"), "rarity": reward.get("rarity"), }) return flask.jsonify(result), 200