Add interaction logging and tighten model NOT NULL constraints

Log searches (article/category) and message-generation events to a new
interaction_log table, capturing IP address and User-Agent.

Also apply NOT NULL constraints to Contribution, SentMessage, FlickrUpload,
and ThumbnailCache fields that are always populated, and remove stale
continue_token references from category.html.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Edward Betts 2026-02-08 12:34:04 +00:00
parent 252a854e76
commit 08f5128e8d
5 changed files with 160 additions and 76 deletions

View file

@ -12,20 +12,20 @@ class Contribution(Base):
__tablename__ = "contributions"
id: Mapped[int] = mapped_column(primary_key=True)
userid: Mapped[int | None]
user: Mapped[str | None]
pageid: Mapped[int | None]
revid: Mapped[int | None] = mapped_column(unique=True)
parentid: Mapped[int | None]
ns: Mapped[int | None]
title: Mapped[str | None]
timestamp: Mapped[str | None]
userid: Mapped[int]
user: Mapped[str]
pageid: Mapped[int]
revid: Mapped[int] = mapped_column(unique=True)
parentid: Mapped[int]
ns: Mapped[int]
title: Mapped[str]
timestamp: Mapped[str]
minor: Mapped[str | None]
top: Mapped[str | None]
comment: Mapped[str | None] = mapped_column(Text)
size: Mapped[int | None]
sizediff: Mapped[int | None]
tags: Mapped[str | None] = mapped_column(Text) # JSON array stored as text
comment: Mapped[str] = mapped_column(Text)
size: Mapped[int]
sizediff: Mapped[int]
tags: Mapped[str] = mapped_column(Text) # JSON array stored as text
__table_args__ = (
Index("ix_contributions_timestamp", "timestamp"),
@ -37,16 +37,16 @@ class SentMessage(Base):
__tablename__ = "sent_messages"
message_id: Mapped[str] = mapped_column(primary_key=True)
subject: Mapped[str | None]
url: Mapped[str | None]
recipient: Mapped[str | None]
date: Mapped[str | None]
body: Mapped[str | None] = mapped_column(Text)
body_html: Mapped[str | None] = mapped_column(Text)
flickr_url: Mapped[str | None]
normalized_flickr_url: Mapped[str | None]
wikipedia_url: Mapped[str | None]
creator_profile_url: Mapped[str | None]
subject: Mapped[str]
url: Mapped[str]
recipient: Mapped[str]
date: Mapped[str]
body: Mapped[str] = mapped_column(Text)
body_html: Mapped[str] = mapped_column(Text)
flickr_url: Mapped[str]
normalized_flickr_url: Mapped[str]
wikipedia_url: Mapped[str]
creator_profile_url: Mapped[str]
flickr_uploads: Mapped[list["FlickrUpload"]] = relationship(
back_populates="sent_message"
@ -62,15 +62,15 @@ class FlickrUpload(Base):
__tablename__ = "flickr_uploads"
id: Mapped[int] = mapped_column(primary_key=True)
pageid: Mapped[int | None]
revid: Mapped[int | None]
title: Mapped[str | None]
timestamp: Mapped[str | None]
flickr_url: Mapped[str | None]
normalized_flickr_url: Mapped[str | None]
pageid: Mapped[int]
revid: Mapped[int]
title: Mapped[str]
timestamp: Mapped[str]
flickr_url: Mapped[str]
normalized_flickr_url: Mapped[str]
creator: Mapped[str | None]
wikipedia_url: Mapped[str | None]
creator_profile_url: Mapped[str | None]
wikipedia_url: Mapped[str]
creator_profile_url: Mapped[str]
sent_message_id: Mapped[str | None] = mapped_column(
ForeignKey("sent_messages.message_id")
)
@ -89,5 +89,23 @@ class ThumbnailCache(Base):
__tablename__ = "thumbnail_cache"
title: Mapped[str] = mapped_column(primary_key=True)
thumb_url: Mapped[str | None]
fetched_at: Mapped[int | None] # Unix timestamp
thumb_url: Mapped[str]
fetched_at: Mapped[int] # Unix timestamp
class InteractionLog(Base):
__tablename__ = "interaction_log"
id: Mapped[int] = mapped_column(primary_key=True)
timestamp: Mapped[int] # Unix timestamp
interaction_type: Mapped[str] # "search_article", "search_category", "generate_message"
ip_address: Mapped[str | None]
user_agent: Mapped[str | None] = mapped_column(Text)
query: Mapped[str | None] # search term or category name
flickr_url: Mapped[str | None]
wikipedia_url: Mapped[str | None]
__table_args__ = (
Index("ix_interaction_log_timestamp", "timestamp"),
Index("ix_interaction_log_type", "interaction_type"),
)