Files
Bacruru Sakaguchi 1ddfe375e5 feat(core): add recursive loading and analyzer tools
Add recursive thread loading method to load threads with all messages and images from the database.

Add support for image captions in the database schema and Image model.

Introduce new analyzer tools for thread management:
- Load thread names from database
- Group threads by similarity
- Merge thread groups

Update main menu to include new Analyzer submenu and options to process threads without downloading images.
2026-02-18 18:19:33 +00:00

70 lines
2.2 KiB
Python
Executable File

"""
Thread data model for forum thread structure (2ch.life).
This module defines the Thread entity for forum data.
"""
from dataclasses import dataclass, field
from typing import List, Optional
from .Message import Message
@dataclass
class Thread:
"""
Represents a forum thread containing multiple messages.
Attributes:
id: Unique identifier for the thread
title: Thread title
board_id: ID of the board this thread belongs to
messages: List of messages in the thread
view_count: Number of views (optional)
"""
id: str
title: str
board_id: str
messages: List[Message] = field(default_factory=list)
view_count: Optional[int] = None
def __post_init__(self):
"""Validate thread data after initialization."""
if not self.id or not isinstance(self.id, int):
try: self.id = int(self.id)
except Exception as e:
raise ValueError("Thread ID must be an integer")
if not self.title or not isinstance(self.title, str):
raise ValueError("Thread title must be a non-empty string")
if not isinstance(self.messages, list):
raise ValueError("Messages must be a list")
if not isinstance(self.view_count, (int, type(None))):
raise ValueError("View count must be an integer or None")
@property
def reply_count(self) -> int:
"""
Get the number of replies in the thread.
Returns:
Number of replies (messages excluding the first one)
"""
return len(self.messages) - 1 if self.messages else 0
def add_message(self, message: Message) -> None:
"""Add a message to the thread."""
if not isinstance(message, Message):
raise ValueError("Must add a Message object")
self.messages.append(message)
def get_first_message(self) -> Optional[Message]:
"""Get the first message (original post) of the thread."""
if self.messages:
return self.messages[0]
return None
def get_last_message(self) -> Optional[Message]:
"""Get the last message in the thread."""
if self.messages:
return self.messages[-1]
return None