Add Profile/Channel entities with CRUD and remove legacy parser builder.

Introduce reusable ParserProfile and ParseChannel, pair jobs with enqueue flatten, Events admin CRUD, and drop inline/legacy parser-builder UI and aliases.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-16 14:51:03 +03:00
co-authored by Cursor
parent e196de7320
commit 71f8cf169e
30 changed files with 2157 additions and 954 deletions
+45
View File
@@ -93,12 +93,54 @@ class Event(Base):
)
class ParserProfile(Base):
__tablename__ = "parser_profiles"
id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True)
name: Mapped[str] = mapped_column(String(255), nullable=False)
sample_post: Mapped[str] = mapped_column(Text, default="")
heuristic_profile: Mapped[dict | None] = mapped_column(JSON, nullable=True)
status: Mapped[str] = mapped_column(String(50), default="draft", index=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
)
jobs: Mapped[list["ParseJob"]] = relationship(back_populates="profile")
class ParseChannel(Base):
__tablename__ = "parse_channels"
id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True)
name: Mapped[str] = mapped_column(String(255), nullable=False)
source_type: Mapped[str] = mapped_column(String(50), nullable=False, default="telegram")
channel: Mapped[str] = mapped_column(String(255), nullable=False)
is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
)
jobs: Mapped[list["ParseJob"]] = relationship(back_populates="channel")
class ParseJob(Base):
__tablename__ = "parse_jobs"
id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True)
source_type: Mapped[str] = mapped_column(String(50), nullable=False)
source_config: Mapped[dict] = mapped_column(JSON, nullable=False, default=dict)
profile_id: Mapped[int | None] = mapped_column(
ForeignKey("parser_profiles.id", ondelete="SET NULL"),
nullable=True,
index=True,
)
channel_id: Mapped[int | None] = mapped_column(
ForeignKey("parse_channels.id", ondelete="SET NULL"),
nullable=True,
index=True,
)
schedule: Mapped[str | None] = mapped_column(String(100), nullable=True)
interval_seconds: Mapped[int] = mapped_column(Integer, default=3600, nullable=False)
is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
@@ -110,6 +152,9 @@ class ParseJob(Base):
default=lambda: datetime.now(timezone.utc),
)
profile: Mapped["ParserProfile | None"] = relationship(back_populates="jobs")
channel: Mapped["ParseChannel | None"] = relationship(back_populates="jobs")
class Consumer(Base):
__tablename__ = "consumers"