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.
70 lines
2.2 KiB
Python
Executable File
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 |