Skip to content

Data Models Reference

Entry

The Entry class represents a single RSS entry/article.

Represents a Miniflux feed entry.

Source code in miniflux_tui/api/models.py
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
@dataclass
class Entry:
    """Represents a Miniflux feed entry."""

    id: int
    feed_id: int
    title: str
    url: str
    content: str
    feed: Feed
    status: str  # "read" or "unread"
    starred: bool
    published_at: datetime
    original_content: str | None = None
    enclosures: list[Enclosure] | None = None

    @classmethod
    def from_dict(cls, data: dict) -> "Entry":
        """Create an Entry from API response data.

        Raises:
            KeyError: If the entry or its feed has no ``id``
            TypeError: If ``feed`` or ``enclosures`` have the wrong shape
        """
        # Parse enclosures if present; skip malformed ones rather than fail the entry
        enclosures: list[Enclosure] | None = None
        raw_enclosures = data.get("enclosures")
        if isinstance(raw_enclosures, list) and raw_enclosures:
            enclosures = []
            for raw in raw_enclosures:
                if isinstance(raw, dict) and "id" in raw:
                    enclosures.append(Enclosure.from_dict(raw))

        feed_data = data.get("feed")
        feed_id = _as_int(data.get("feed_id"), default=-1)
        if not isinstance(feed_data, dict):
            if feed_id < 0:
                msg = "feed"
                raise KeyError(msg)
            feed_data = {"id": feed_id}
        feed = Feed.from_dict(feed_data)

        original_content = data.get("original_content")
        return cls(
            id=_as_int(data["id"]),
            feed_id=feed.id if feed_id < 0 else feed_id,
            title=_as_str(data.get("title")),
            url=_as_str(data.get("url")),
            content=_as_str(data.get("content")),
            feed=feed,
            status=_as_str(data.get("status"), default="unread"),
            starred=_as_bool(data.get("starred")),
            published_at=_parse_datetime(data.get("published_at")),
            original_content=_as_str(original_content) if original_content is not None else None,
            enclosures=enclosures,
        )

    @property
    def is_read(self) -> bool:
        """Check if entry is marked as read."""
        return self.status == "read"

    @property
    def is_unread(self) -> bool:
        """Check if entry is marked as unread."""
        return self.status == "unread"

    @property
    def image_enclosures(self) -> list[Enclosure]:
        """Get all image enclosures for this entry."""
        if not self.enclosures:
            return []
        return [enc for enc in self.enclosures if enc.is_image]

image_enclosures property

Get all image enclosures for this entry.

is_read property

Check if entry is marked as read.

is_unread property

Check if entry is marked as unread.

from_dict(data) classmethod

Create an Entry from API response data.

Raises:

Type Description
KeyError

If the entry or its feed has no id

TypeError

If feed or enclosures have the wrong shape

Source code in miniflux_tui/api/models.py
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
@classmethod
def from_dict(cls, data: dict) -> "Entry":
    """Create an Entry from API response data.

    Raises:
        KeyError: If the entry or its feed has no ``id``
        TypeError: If ``feed`` or ``enclosures`` have the wrong shape
    """
    # Parse enclosures if present; skip malformed ones rather than fail the entry
    enclosures: list[Enclosure] | None = None
    raw_enclosures = data.get("enclosures")
    if isinstance(raw_enclosures, list) and raw_enclosures:
        enclosures = []
        for raw in raw_enclosures:
            if isinstance(raw, dict) and "id" in raw:
                enclosures.append(Enclosure.from_dict(raw))

    feed_data = data.get("feed")
    feed_id = _as_int(data.get("feed_id"), default=-1)
    if not isinstance(feed_data, dict):
        if feed_id < 0:
            msg = "feed"
            raise KeyError(msg)
        feed_data = {"id": feed_id}
    feed = Feed.from_dict(feed_data)

    original_content = data.get("original_content")
    return cls(
        id=_as_int(data["id"]),
        feed_id=feed.id if feed_id < 0 else feed_id,
        title=_as_str(data.get("title")),
        url=_as_str(data.get("url")),
        content=_as_str(data.get("content")),
        feed=feed,
        status=_as_str(data.get("status"), default="unread"),
        starred=_as_bool(data.get("starred")),
        published_at=_parse_datetime(data.get("published_at")),
        original_content=_as_str(original_content) if original_content is not None else None,
        enclosures=enclosures,
    )

Properties

  • id: Unique identifier for the entry
  • title: Entry title
  • content: Entry HTML content
  • published_at: Publication timestamp
  • is_read: Whether the entry has been read
  • starred: Whether the entry is starred/favorited
  • feed: The Feed this entry belongs to

Helper Methods

  • is_unread: Property that returns True if not read
  • status: Property that returns "read" or "unread"

Feed

The Feed class represents an RSS feed.

Represents a Miniflux feed.

Source code in miniflux_tui/api/models.py
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
@dataclass
class Feed:
    """Represents a Miniflux feed."""

    id: int
    title: str
    site_url: str
    feed_url: str
    category_id: int | None = None
    description: str = ""  # User-provided description or notes for the feed
    parsing_error_message: str = ""
    parsing_error_count: int = 0
    checked_at: str | None = None
    disabled: bool = False
    # Network settings
    username: str = ""
    password: str = ""
    user_agent: str = ""
    proxy_url: str = ""
    ignore_https_errors: bool = False
    # Rules & filtering (API uses blocklist_rules and keeplist_rules, not blocking_rules and keep_rules)
    scraper_rules: str = ""
    rewrite_rules: str = ""
    blocklist_rules: str = ""
    keeplist_rules: str = ""
    # Feed behavior options
    hide_globally: bool = False
    no_media_player: bool = False
    # Additional feed settings
    crawler: bool = False
    ignore_http_cache: bool = False
    fetch_via_proxy: bool = False
    check_interval: int | None = None

    @classmethod
    def from_dict(cls, data: dict) -> "Feed":
        """Create a Feed from API response data."""
        checked_at = data.get("checked_at")
        return cls(
            id=_as_int(data["id"]),
            title=_as_str(data.get("title")),
            site_url=_as_str(data.get("site_url")),
            feed_url=_as_str(data.get("feed_url")),
            category_id=_as_optional_int(data.get("category_id")),
            description=_as_str(data.get("description")),
            parsing_error_message=_as_str(data.get("parsing_error_message")),
            parsing_error_count=_as_int(data.get("parsing_error_count")),
            checked_at=_as_str(checked_at) if checked_at is not None else None,
            disabled=_as_bool(data.get("disabled")),
            username=_as_str(data.get("username")),
            password=_as_str(data.get("password")),
            user_agent=_as_str(data.get("user_agent")),
            proxy_url=_as_str(data.get("proxy_url")),
            ignore_https_errors=_as_bool(data.get("ignore_https_errors")),
            scraper_rules=_as_str(data.get("scraper_rules")),
            rewrite_rules=_as_str(data.get("rewrite_rules")),
            blocklist_rules=_as_str(data.get("blocklist_rules")),
            keeplist_rules=_as_str(data.get("keeplist_rules")),
            hide_globally=_as_bool(data.get("hide_globally")),
            no_media_player=_as_bool(data.get("no_media_player")),
            crawler=_as_bool(data.get("crawler")),
            ignore_http_cache=_as_bool(data.get("ignore_http_cache")),
            fetch_via_proxy=_as_bool(data.get("fetch_via_proxy")),
            check_interval=_as_optional_int(data.get("check_interval")),
        )

    @property
    def has_errors(self) -> bool:
        """Check if feed has parsing errors."""
        return bool(self.parsing_error_message or self.parsing_error_count > 0)

has_errors property

Check if feed has parsing errors.

from_dict(data) classmethod

Create a Feed from API response data.

Source code in miniflux_tui/api/models.py
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
@classmethod
def from_dict(cls, data: dict) -> "Feed":
    """Create a Feed from API response data."""
    checked_at = data.get("checked_at")
    return cls(
        id=_as_int(data["id"]),
        title=_as_str(data.get("title")),
        site_url=_as_str(data.get("site_url")),
        feed_url=_as_str(data.get("feed_url")),
        category_id=_as_optional_int(data.get("category_id")),
        description=_as_str(data.get("description")),
        parsing_error_message=_as_str(data.get("parsing_error_message")),
        parsing_error_count=_as_int(data.get("parsing_error_count")),
        checked_at=_as_str(checked_at) if checked_at is not None else None,
        disabled=_as_bool(data.get("disabled")),
        username=_as_str(data.get("username")),
        password=_as_str(data.get("password")),
        user_agent=_as_str(data.get("user_agent")),
        proxy_url=_as_str(data.get("proxy_url")),
        ignore_https_errors=_as_bool(data.get("ignore_https_errors")),
        scraper_rules=_as_str(data.get("scraper_rules")),
        rewrite_rules=_as_str(data.get("rewrite_rules")),
        blocklist_rules=_as_str(data.get("blocklist_rules")),
        keeplist_rules=_as_str(data.get("keeplist_rules")),
        hide_globally=_as_bool(data.get("hide_globally")),
        no_media_player=_as_bool(data.get("no_media_player")),
        crawler=_as_bool(data.get("crawler")),
        ignore_http_cache=_as_bool(data.get("ignore_http_cache")),
        fetch_via_proxy=_as_bool(data.get("fetch_via_proxy")),
        check_interval=_as_optional_int(data.get("check_interval")),
    )

Feed Properties

  • id: Unique feed identifier
  • title: Feed title
  • url: Feed URL
  • unread_count: Number of unread entries in this feed

EntryListItem

Internal widget class for rendering entries in the list.

FeedHeaderItem

Internal widget class for rendering feed group headers in grouped mode.

Usage Example

from miniflux_tui.api.models import Entry, Feed

# Create a feed
feed = Feed(id=1, title="My Blog", url="https://example.com/feed")

# Create an entry
entry = Entry(
    id=123, title="My Article", content="<p>Article content</p>", published_at=1699564800, is_read=False, starred=False, feed=feed
)

# Check properties
print(f"Entry: {entry.title}")
print(f"Feed: {entry.feed.title}")
print(f"Status: {entry.status}")
print(f"Is unread: {entry.is_unread}")