mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-25 16:56:22 +02:00
131 lines
4 KiB
Python
131 lines
4 KiB
Python
"""
|
|
Incentive Tasks API routes.
|
|
Allows users to complete tasks (like starring GitHub repo) to earn free pages.
|
|
Each task can only be completed once per user.
|
|
"""
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.db import (
|
|
INCENTIVE_TASKS_CONFIG,
|
|
IncentiveTaskType,
|
|
User,
|
|
UserIncentiveTask,
|
|
get_async_session,
|
|
)
|
|
from app.schemas.incentive_tasks import (
|
|
CompleteTaskResponse,
|
|
IncentiveTaskInfo,
|
|
IncentiveTasksResponse,
|
|
TaskAlreadyCompletedResponse,
|
|
)
|
|
from app.users import current_active_user
|
|
|
|
router = APIRouter(prefix="/incentive-tasks", tags=["incentive-tasks"])
|
|
|
|
|
|
@router.get("", response_model=IncentiveTasksResponse)
|
|
async def get_incentive_tasks(
|
|
user: User = Depends(current_active_user),
|
|
session: AsyncSession = Depends(get_async_session),
|
|
) -> IncentiveTasksResponse:
|
|
"""
|
|
Get all available incentive tasks with the user's completion status.
|
|
"""
|
|
# Get all completed tasks for this user
|
|
result = await session.execute(
|
|
select(UserIncentiveTask).where(UserIncentiveTask.user_id == user.id)
|
|
)
|
|
completed_tasks = {task.task_type: task for task in result.scalars().all()}
|
|
|
|
# Build task list with completion status
|
|
tasks = []
|
|
total_pages_earned = 0
|
|
|
|
for task_type, config in INCENTIVE_TASKS_CONFIG.items():
|
|
completed_task = completed_tasks.get(task_type)
|
|
is_completed = completed_task is not None
|
|
|
|
if is_completed:
|
|
total_pages_earned += completed_task.pages_awarded
|
|
|
|
tasks.append(
|
|
IncentiveTaskInfo(
|
|
task_type=task_type,
|
|
title=config["title"],
|
|
description=config["description"],
|
|
pages_reward=config["pages_reward"],
|
|
action_url=config["action_url"],
|
|
completed=is_completed,
|
|
completed_at=completed_task.completed_at if completed_task else None,
|
|
)
|
|
)
|
|
|
|
return IncentiveTasksResponse(
|
|
tasks=tasks,
|
|
total_pages_earned=total_pages_earned,
|
|
)
|
|
|
|
|
|
@router.post(
|
|
"/{task_type}/complete",
|
|
response_model=CompleteTaskResponse | TaskAlreadyCompletedResponse,
|
|
)
|
|
async def complete_task(
|
|
task_type: IncentiveTaskType,
|
|
user: User = Depends(current_active_user),
|
|
session: AsyncSession = Depends(get_async_session),
|
|
) -> CompleteTaskResponse | TaskAlreadyCompletedResponse:
|
|
"""
|
|
Mark an incentive task as completed and award pages to the user.
|
|
|
|
Each task can only be completed once. If the task was already completed,
|
|
returns the existing completion information without awarding additional pages.
|
|
"""
|
|
# Validate task type exists in config
|
|
task_config = INCENTIVE_TASKS_CONFIG.get(task_type)
|
|
if not task_config:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail=f"Unknown task type: {task_type}",
|
|
)
|
|
|
|
# Check if task was already completed
|
|
existing_task = await session.execute(
|
|
select(UserIncentiveTask).where(
|
|
UserIncentiveTask.user_id == user.id,
|
|
UserIncentiveTask.task_type == task_type,
|
|
)
|
|
)
|
|
existing = existing_task.scalar_one_or_none()
|
|
|
|
if existing:
|
|
return TaskAlreadyCompletedResponse(
|
|
success=False,
|
|
message="Task already completed",
|
|
completed_at=existing.completed_at,
|
|
)
|
|
|
|
# Create the task completion record
|
|
pages_reward = task_config["pages_reward"]
|
|
new_task = UserIncentiveTask(
|
|
user_id=user.id,
|
|
task_type=task_type,
|
|
pages_awarded=pages_reward,
|
|
)
|
|
session.add(new_task)
|
|
|
|
# Update user's pages_limit
|
|
user.pages_limit += pages_reward
|
|
|
|
await session.commit()
|
|
await session.refresh(user)
|
|
|
|
return CompleteTaskResponse(
|
|
success=True,
|
|
message=f"Task completed! You earned {pages_reward} pages.",
|
|
pages_awarded=pages_reward,
|
|
new_pages_limit=user.pages_limit,
|
|
)
|