mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-07-22 23:31:12 +02:00
bugs fixed
This commit is contained in:
parent
6037a0dc83
commit
92c0474df4
4 changed files with 88 additions and 23 deletions
|
|
@ -5,7 +5,7 @@ A module for retrieving data from ClickUp.
|
|||
Allows fetching tasks from workspaces and lists.
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any
|
||||
|
||||
import requests
|
||||
|
|
@ -180,40 +180,79 @@ class ClickUpConnector:
|
|||
start_timestamp = int(start_datetime.timestamp() * 1000)
|
||||
end_timestamp = int(end_datetime.timestamp() * 1000)
|
||||
|
||||
params = {
|
||||
# Base parameters for both requests
|
||||
base_params = {
|
||||
"page": 0,
|
||||
"order_by": "created",
|
||||
"reverse": "true",
|
||||
"subtasks": "true",
|
||||
"include_closed": str(include_closed).lower(),
|
||||
# Date filtering - filter by both created and updated dates
|
||||
"date_created_gt": start_timestamp,
|
||||
"date_created_lt": end_timestamp,
|
||||
"date_updated_gt": start_timestamp,
|
||||
"date_updated_lt": end_timestamp,
|
||||
}
|
||||
|
||||
all_tasks = []
|
||||
page = 0
|
||||
# Request 1: Filter by creation date
|
||||
created_params = base_params.copy()
|
||||
created_params.update({
|
||||
"date_created_gt": start_timestamp,
|
||||
"date_created_lt": end_timestamp,
|
||||
})
|
||||
|
||||
while True:
|
||||
params["page"] = page
|
||||
result = self.make_api_request(f"team/{workspace_id}/task", params)
|
||||
# Request 2: Filter by update date
|
||||
updated_params = base_params.copy()
|
||||
updated_params.update({
|
||||
"date_updated_gt": start_timestamp,
|
||||
"date_updated_lt": end_timestamp,
|
||||
})
|
||||
|
||||
if not isinstance(result, dict) or "tasks" not in result:
|
||||
return [], "Invalid response from ClickUp API"
|
||||
def fetch_tasks_with_params(params):
|
||||
"""Helper function to fetch all tasks for given parameters"""
|
||||
all_tasks = []
|
||||
page = 0
|
||||
|
||||
tasks = result["tasks"]
|
||||
if not tasks:
|
||||
break
|
||||
while True:
|
||||
params["page"] = page
|
||||
result = self.make_api_request(f"team/{workspace_id}/task", params)
|
||||
|
||||
all_tasks.extend(tasks)
|
||||
if not isinstance(result, dict) or "tasks" not in result:
|
||||
return [], "Invalid response from ClickUp API"
|
||||
|
||||
# Check if there are more pages
|
||||
if len(tasks) < 100: # ClickUp returns max 100 tasks per page
|
||||
break
|
||||
tasks = result["tasks"]
|
||||
if not tasks:
|
||||
break
|
||||
|
||||
page += 1
|
||||
all_tasks.extend(tasks)
|
||||
|
||||
# Check if there are more pages
|
||||
if len(tasks) < 100: # ClickUp returns max 100 tasks per page
|
||||
break
|
||||
|
||||
page += 1
|
||||
|
||||
return all_tasks, None
|
||||
|
||||
# Fetch tasks created in date range
|
||||
created_tasks, error = fetch_tasks_with_params(created_params)
|
||||
if error:
|
||||
return [], error
|
||||
|
||||
# Fetch tasks updated in date range
|
||||
updated_tasks, error = fetch_tasks_with_params(updated_params)
|
||||
if error:
|
||||
return [], error
|
||||
|
||||
# Merge and deduplicate tasks by ID
|
||||
# Use a dictionary to store unique tasks (ID as key)
|
||||
unique_tasks = {}
|
||||
|
||||
# Add created tasks
|
||||
for task in created_tasks:
|
||||
unique_tasks[task["id"]] = task
|
||||
|
||||
# Add updated tasks (will overwrite duplicates, keeping the latest)
|
||||
for task in updated_tasks:
|
||||
unique_tasks[task["id"]] = task
|
||||
|
||||
# Convert back to list
|
||||
all_tasks = list(unique_tasks.values())
|
||||
|
||||
if not all_tasks:
|
||||
return [], "No tasks found in the specified date range."
|
||||
|
|
|
|||
|
|
@ -336,6 +336,8 @@ class ConnectorSchedule(BaseModel, TimestampMixin):
|
|||
)
|
||||
schedule_type = Column(SQLAlchemyEnum(ScheduleType), nullable=False)
|
||||
cron_expression = Column(String(100), nullable=True)
|
||||
# Timezone for interpreting daily_time and weekly_time (IANA zone name)
|
||||
timezone = Column(String(50), nullable=False, default="UTC")
|
||||
# Optional schedule config fields (persist user selections)
|
||||
daily_time = Column(Time(timezone=False), nullable=True)
|
||||
weekly_day = Column(Integer, nullable=True) # 0=Mon .. 6=Sun
|
||||
|
|
@ -445,6 +447,11 @@ if config.AUTH_TYPE == "GOOGLE":
|
|||
"OAuthAccount", lazy="joined"
|
||||
)
|
||||
search_spaces = relationship("SearchSpace", back_populates="user")
|
||||
search_source_connectors = relationship(
|
||||
"SearchSourceConnector",
|
||||
back_populates="user",
|
||||
cascade="all, delete-orphan",
|
||||
)
|
||||
search_space_preferences = relationship(
|
||||
"UserSearchSpacePreference",
|
||||
back_populates="user",
|
||||
|
|
|
|||
|
|
@ -10,10 +10,11 @@ from sqlalchemy import select, Integer
|
|||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy.orm import selectinload
|
||||
|
||||
from app.db import get_async_session, Log
|
||||
from app.db import get_async_session, Log, ConnectorSchedule, SearchSourceConnector
|
||||
from app.schemas import ConnectorScheduleRead
|
||||
from app.services.connector_scheduler_service import get_scheduler
|
||||
from app.users import User, current_active_user
|
||||
from app.utils.check_ownership import check_ownership
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -49,6 +50,7 @@ async def get_scheduler_status(
|
|||
async def force_execute_schedule(
|
||||
schedule_id: int,
|
||||
background_tasks: BackgroundTasks,
|
||||
session: AsyncSession = Depends(get_async_session),
|
||||
user: User = Depends(current_active_user),
|
||||
):
|
||||
"""
|
||||
|
|
@ -58,6 +60,20 @@ async def force_execute_schedule(
|
|||
the connector sync for the specified schedule.
|
||||
"""
|
||||
try:
|
||||
# First, verify ownership of the schedule
|
||||
# Load the schedule and verify the user owns the associated connector
|
||||
result = await session.execute(
|
||||
select(ConnectorSchedule).filter(ConnectorSchedule.id == schedule_id)
|
||||
)
|
||||
schedule = result.scalars().first()
|
||||
|
||||
if not schedule:
|
||||
raise HTTPException(status_code=404, detail="Schedule not found")
|
||||
|
||||
# Verify schedule's connector belongs to user
|
||||
await check_ownership(session, SearchSourceConnector, schedule.connector_id, user)
|
||||
|
||||
# Only after ownership is confirmed, proceed with scheduling
|
||||
scheduler = await get_scheduler()
|
||||
|
||||
# Add the force execution to background tasks
|
||||
|
|
@ -72,6 +88,8 @@ async def force_execute_schedule(
|
|||
"schedule_id": schedule_id
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Error force executing schedule {schedule_id}: {e}")
|
||||
raise HTTPException(
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ class ConnectorScheduleBase(BaseModel):
|
|||
schedule_type: ScheduleType
|
||||
cron_expression: str | None = None
|
||||
is_active: bool = True
|
||||
timezone: str = "UTC" # IANA timezone name for interpreting daily_time and weekly_time
|
||||
|
||||
# Enhanced time selection options
|
||||
daily_time: Optional[time] = None # For DAILY schedules (default: 02:00)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue