Initial commit with Python .gitignore
This commit is contained in:
107
scientific_surfing/models.py
Normal file
107
scientific_surfing/models.py
Normal file
@ -0,0 +1,107 @@
|
||||
"""
|
||||
Pydantic models for scientific-surfing data structures.
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Dict, List, Optional
|
||||
from pydantic import BaseModel, Field, validator
|
||||
|
||||
|
||||
class Subscription(BaseModel):
|
||||
"""Model for a single subscription."""
|
||||
|
||||
name: str = Field(..., description="Name of the subscription")
|
||||
url: str = Field(..., description="Clash RSS subscription URL")
|
||||
status: str = Field(default="inactive", description="Status: active or inactive")
|
||||
last_refresh: Optional[datetime] = Field(default=None, description="Last refresh timestamp")
|
||||
file_path: Optional[str] = Field(default=None, description="Path to downloaded file")
|
||||
file_size: Optional[int] = Field(default=None, description="Size of downloaded file in bytes")
|
||||
status_code: Optional[int] = Field(default=None, description="HTTP status code of last refresh")
|
||||
content_hash: Optional[int] = Field(default=None, description="Hash of downloaded content")
|
||||
last_error: Optional[str] = Field(default=None, description="Last error message if any")
|
||||
|
||||
@validator('status')
|
||||
def validate_status(cls, v):
|
||||
if v not in ['active', 'inactive']:
|
||||
raise ValueError('Status must be either "active" or "inactive"')
|
||||
return v
|
||||
|
||||
class Config:
|
||||
json_encoders = {
|
||||
datetime: lambda v: v.isoformat() if v else None
|
||||
}
|
||||
|
||||
|
||||
class Config(BaseModel):
|
||||
"""Model for application configuration."""
|
||||
|
||||
auto_refresh: bool = Field(default=False, description="Auto-refresh subscriptions")
|
||||
refresh_interval_hours: int = Field(default=24, description="Refresh interval in hours")
|
||||
default_user_agent: str = Field(
|
||||
default="scientific-surfing/0.1.0",
|
||||
description="Default User-Agent for HTTP requests"
|
||||
)
|
||||
timeout_seconds: int = Field(default=30, description="HTTP request timeout in seconds")
|
||||
|
||||
@validator('refresh_interval_hours')
|
||||
def validate_refresh_interval(cls, v):
|
||||
if v < 1:
|
||||
raise ValueError('Refresh interval must be at least 1 hour')
|
||||
return v
|
||||
|
||||
@validator('timeout_seconds')
|
||||
def validate_timeout(cls, v):
|
||||
if v < 1:
|
||||
raise ValueError('Timeout must be at least 1 second')
|
||||
return v
|
||||
|
||||
|
||||
class SubscriptionsData(BaseModel):
|
||||
"""Model for the entire subscriptions collection."""
|
||||
|
||||
subscriptions: Dict[str, Subscription] = Field(default_factory=dict)
|
||||
|
||||
def get_active_subscription(self) -> Optional[Subscription]:
|
||||
"""Get the currently active subscription."""
|
||||
for subscription in self.subscriptions.values():
|
||||
if subscription.status == 'active':
|
||||
return subscription
|
||||
return None
|
||||
|
||||
def set_active(self, name: str) -> bool:
|
||||
"""Set a subscription as active and deactivate others."""
|
||||
if name not in self.subscriptions:
|
||||
return False
|
||||
|
||||
for sub_name, subscription in self.subscriptions.items():
|
||||
subscription.status = 'active' if sub_name == name else 'inactive'
|
||||
return True
|
||||
|
||||
def add_subscription(self, name: str, url: str) -> Subscription:
|
||||
"""Add a new subscription."""
|
||||
subscription = Subscription(name=name, url=url)
|
||||
|
||||
# If this is the first subscription, set it as active
|
||||
if not self.subscriptions:
|
||||
subscription.status = 'active'
|
||||
|
||||
self.subscriptions[name] = subscription
|
||||
return subscription
|
||||
|
||||
def remove_subscription(self, name: str) -> bool:
|
||||
"""Remove a subscription."""
|
||||
if name not in self.subscriptions:
|
||||
return False
|
||||
|
||||
del self.subscriptions[name]
|
||||
return True
|
||||
|
||||
def rename_subscription(self, old_name: str, new_name: str) -> bool:
|
||||
"""Rename a subscription."""
|
||||
if old_name not in self.subscriptions or new_name in self.subscriptions:
|
||||
return False
|
||||
|
||||
subscription = self.subscriptions.pop(old_name)
|
||||
subscription.name = new_name
|
||||
self.subscriptions[new_name] = subscription
|
||||
return True
|
||||
Reference in New Issue
Block a user