Skip to content

angee.posts.models ​

Source models for the posts addon — public feeds, engagement, and following.

Posts is the public-post surface layered on messaging. It reuses the one idempotent Message.objects.ingest write path (a public post is a messaging.Message in a messaging.Thread) and adds the posts overlay:

  • :class:Feed — an integrate.Integration child + Bridge (exactly like messaging.Channel) that polls an external platform for public posts; its FeedBackend does the transport+parse, and sync() maps each post onto the messaging ingest, then overlays engagement.
  • :class:FeedFollow — the following / timeline subscription edge.
  • :class:PostMetrics — rolled-up public engagement counts for a message.
  • per-actor post reactions (like / repost / emoji) reuse the single messaging.Reaction table — posts writes like/repost as reaction values on the shared messaging.Message rather than owning a parallel table.
  • :class:Quota — the per-integration API-unit ledger feed backends spend.
  • :class:ThreadPublic / :class:MessagePublic — the public-thread fields posts contributes onto messaging.Thread / messaging.Message through the same-row extends seam.

The dependency points one way (posts → messaging → parties/integrate/storage); posts never edits or forks messaging.

Feed ​

python
class Feed(Bridge)

A connected public-content source that polls an external platform for posts.

An integrate.Integration child (identity / credential / status / owner from the connection substrate) and a Bridge (the scheduler + run_sync drive it through sync; integrate.scheduler.run_due_bridges auto-discovers any concrete Bridge subclass, so no registration is needed). backend_class selects the platform — youtube / facebook are contributed by downstream posts_integrate_* addons; manual is the neutral null-object.

A paused feed carries a NULL next_sync_at (not scheduled); activating it schedules the first poll. handle is the parties.Handle the feed monitors and posts as (its OAuth token lives on the handle / the integration credential).

backend_class ​

Registry key for the feed backend bound to this feed.

external_id ​

The external channel/page/account id this feed follows on its platform.

Meta ​

python
class Meta()

Django model options for the feed child model.

backend ​

python
@property
def backend() -> FeedBackend

Return this feed's selected backend, bound to this row.

sync ​

python
def sync() -> int

Fetch new posts, ingest their message core, and overlay engagement.

The message core (thread/message/parts) is the messaging owner's job, so a public post shares email's one idempotent write path; posts only writes the overlay it owns (public payload / metrics / reactions / post edges). The ingest is told the structural facts a public feed differs on: every thread is born a PUBLIC_THREAD with PUBLIC visibility — the ingest owner derives the COMMENT kind from that shape — and the RFC-5322 quotation builder is skipped (quote_edges=False) so a post's short shared text does not mint spurious email quote edges.

FeedFollow ​

python
class FeedFollow(SqidMixin, AuditMixin, AngeeModel)

A follow of a :class:Feed by a parties.Handle — the timeline subscription.

The following edge behind a public timeline: a handle subscribes to a feed's posts. ended_at closes a follow (an open/closed interval), so unfollowing is an update, not a delete, and the history is retained. The timeline itself is the derived join FeedFollow → Feed → Thread → Message (a downstream query owner).

Meta ​

python
class Meta()

Django model options for the feed-follow source model.

__str__ ​

python
def __str__() -> str

Return a readable follow label for Django displays.

PostMetrics ​

python
class PostMetrics(SqidMixin, AuditMixin, AngeeModel)

Rolled-up public engagement counts for one message (the platform snapshot).

Flat one-to-one, not MTI — the counter set overlaps heavily across platforms; platform extras go in metadata. Counters are overwritten with the latest platform snapshot (no F() delta), so the feed sync is the single writer.

Meta ​

python
class Meta()

Django model options for the post-metrics source model.

__str__ ​

python
def __str__() -> str

Return a readable metrics label for Django displays.

Quota ​

python
class Quota(SqidMixin, AuditMixin, AngeeModel)

A per-integration API-unit ledger for one billing period.

Feed backends spend platform API units (search, list, insert) against a per-period budget; :meth:~angee.posts.managers.QuotaManager.consume atomically debits this ledger and refuses when the budget is insufficient. Enforcement is cooperative — the backend must ask before it spends.

Meta ​

python
class Meta()

Django model options for the quota source model.

__str__ ​

python
def __str__() -> str

Return a readable quota label for Django displays.

ThreadPublic ​

python
class ThreadPublic(AngeeModel)

Public-post payload posts contributes onto messaging.Thread (same row).

subject_url links a public thread to its post's canonical URL. It has no producer in base messaging, so posts owns it; the structural modality/ visibility discriminators stay owned by messaging.

Meta ​

python
class Meta()

Abstract same-row extension composed into messaging.Thread.

MessagePublic ​

python
class MessagePublic(AngeeModel)

Public-post fields posts contributes onto messaging.Message (same row).

is_original_post marks the root post of a public thread (a post with no parent). It has no producer in base messaging, so posts owns it and the composer folds it onto the single messaging.Message table.

Meta ​

python
class Meta()

Abstract same-row extension composed into messaging.Message.

Released under the AGPL-3.0 License.