aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Dockerfile2
-rwxr-xr-xserve.py49
-rw-r--r--tagrss.py28
-rw-r--r--views/manage_feed.tpl17
4 files changed, 47 insertions, 49 deletions
diff --git a/Dockerfile b/Dockerfile
index 80159e5..186123c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -9,4 +9,4 @@ EXPOSE 8000
STOPSIGNAL SIGINT
-CMD ["./serve.py", "--host", "0.0.0.0", "--storage-path", "/tagrss_data/tagrss_data.db"]
+CMD ["python3", "-O", "serve.py", "--host", "0.0.0.0", "--storage-path", "/tagrss_data/tagrss_data.db"]
diff --git a/serve.py b/serve.py
index cec578d..f53acbb 100755
--- a/serve.py
+++ b/serve.py
@@ -216,47 +216,52 @@ def manage_feed_view():
feed_id: int = int(feed_id_raw)
except ValueError:
raise bottle.HTTPError(400, f'"{feed_id_raw}" is not a valid feed ID.')
- feed: dict[str, typing.Any] = {}
- feed["id"] = feed_id
try:
- feed["source"] = core.get_feed_source(feed_id)
- feed["title"] = core.get_feed_title(feed_id)
+ feed = tagrss.Feed(
+ id=feed_id,
+ source=core.get_feed_source(feed_id),
+ title=core.get_feed_title(feed_id),
+ )
except tagrss.FeedDoesNotExistError:
raise bottle.HTTPError(404, f"No feed has ID {feed_id}.")
- feed["tags"] = core.get_feed_tags(feed_id)
- feed["serialised_tags"] = serialise_tags(feed["tags"])
- return bottle.template("manage_feed", feed=feed)
+ feed.tags = core.get_feed_tags(feed_id)
+ serialised_tags = serialise_tags(feed.tags)
+ return bottle.template("manage_feed", feed=feed, serialised_tags=serialised_tags)
@bottle.post("/manage_feed")
def manage_feed_effect():
- feed: dict[str, typing.Any] = {}
- feed["id"] = int(bottle.request.forms["id"]) # type: ignore
- feed["source"] = bottle.request.forms["source"] # type: ignore
- feed["title"] = bottle.request.forms["title"] # type: ignore
- feed["tags"] = parse_space_separated_tags(bottle.request.forms["tags"]) # type: ignore
- feed["serialised_tags"] = bottle.request.forms["tags"] # type: ignore
- if len(feed["tags"]) > MAX_TAGS:
+ serialised_tags = bottle.request.forms["tags"] # type: ignore
+ feed = tagrss.Feed(
+ id=int(bottle.request.forms["id"]), # type: ignore
+ source=bottle.request.forms["source"], # type: ignore
+ title=bottle.request.forms["title"], # type: ignore
+ tags=parse_space_separated_tags(serialised_tags),
+ )
+ assert feed.tags
+ if len(feed.tags) > MAX_TAGS:
raise bottle.HTTPError(400, f"A feed cannot have more than {MAX_TAGS} tags.")
try:
- core.set_feed_source(feed["id"], feed["source"])
+ core.set_feed_source(feed.id, feed.source)
except tagrss.FeedSourceAlreadyExistsError:
raise bottle.HTTPError(
400,
- f"Cannot change source to {feed['source']} as there is already a feed with"
+ f"Cannot change source to {feed.source} as there is already a feed with"
" that source.",
)
try:
- core.set_feed_title(feed["id"], feed["title"])
+ core.set_feed_title(feed.id, feed.title)
except tagrss.FeedTitleAlreadyInUseError:
raise bottle.HTTPError(
400,
- f"Cannot change title to {feed['title']} as there is already a feed with"
+ f"Cannot change title to {feed.title} as there is already a feed with"
" that title.",
)
- core.set_feed_tags(feed["id"], feed["tags"])
- logging.info(f"Edited details of feed {feed['id']}.")
- return bottle.template("manage_feed", feed=feed, after_update=True)
+ core.set_feed_tags(feed.id, feed.tags)
+ logging.info(f"Edited details of feed {feed.id}.")
+ return bottle.template(
+ "manage_feed", feed=feed, serialised_tags=serialised_tags, after_update=True
+ )
@bottle.post("/delete_feed")
@@ -281,7 +286,7 @@ def update_feeds(run_event: threading.Event):
feeds = core.get_feeds(limit=limit, offset=limit * i)
for feed in feeds:
try:
- core.update_feed(feed.id) # type: ignore
+ core.update_feed(feed.id)
except tagrss.FeedFetchError as e:
logging.error(
f"Failed to update feed {feed.id} with source {feed.source} "
diff --git a/tagrss.py b/tagrss.py
index e5a5708..9179035 100644
--- a/tagrss.py
+++ b/tagrss.py
@@ -65,10 +65,10 @@ ParsedFeed = feedparser.FeedParserDict
@dataclasses.dataclass(kw_only=True)
-class PartialFeed:
- id: typing.Optional[FeedId] = None
- source: typing.Optional[str] = None
- title: typing.Optional[str] = None
+class Feed:
+ id: FeedId
+ source: str
+ title: str
tags: typing.Optional[list[str]] = None
@@ -161,7 +161,7 @@ class SqliteStorageProvider(StorageProvider):
included_feeds: typing.Optional[list[FeedId]] = None,
included_tags: typing.Optional[list[str]] = None,
get_tags: bool = False,
- ) -> list[PartialFeed]:
+ ) -> list[Feed]:
where_clause = "WHERE 1"
if included_feeds:
where_clause += f" AND id IN ({','.join('?' * len(included_feeds))})"
@@ -181,11 +181,13 @@ class SqliteStorageProvider(StorageProvider):
offset,
),
).fetchall()
- feeds_dict: dict[FeedId, PartialFeed] = {}
+ feeds_dict: dict[FeedId, Feed] = {}
for row in resp:
- feeds_dict[row[0]] = PartialFeed(source=row[1], title=row[2])
+ feeds_dict[row[0]] = Feed(id=row[0], source=row[1], title=row[2])
if get_tags:
feed_ids = feeds_dict.keys()
+ for feed_id in feed_ids:
+ feeds_dict[feed_id].tags = []
placeholder_str = ",".join("?" * len(feed_ids))
with self.__get_connection() as conn:
resp = conn.execute(
@@ -198,15 +200,7 @@ class SqliteStorageProvider(StorageProvider):
feeds_dict[row[0]].tags.append(row[1]) # type: ignore
except AttributeError:
feeds_dict[row[0]].tags = [row[1]]
- result: list[PartialFeed] = []
- for item in feeds_dict.items():
- feed = PartialFeed(id=item[0], source=item[1].source, title=item[1].title)
- if get_tags:
- feed.tags = item[1].tags
- if not feed.tags:
- feed.tags = []
- result.append(feed)
- return result
+ return list(feeds_dict.values())
def get_feed_count(
self,
@@ -485,7 +479,7 @@ class TagRss:
included_feeds: typing.Optional[list[int]] = None,
included_tags: typing.Optional[list[str]] = None,
get_tags: bool = False,
- ) -> list[PartialFeed]:
+ ) -> list[Feed]:
return self.__storage.get_feeds(
limit=limit,
offset=offset,
diff --git a/views/manage_feed.tpl b/views/manage_feed.tpl
index a26c6bc..cdeaf98 100644
--- a/views/manage_feed.tpl
+++ b/views/manage_feed.tpl
@@ -15,17 +15,16 @@
<table>
<tr>
<th>Title</th>
- <td>{{feed["title"]}}</td>
+ <td>{{feed.title}}</td>
</tr>
<tr>
<th>Source</th>
- <td><a href="{{feed['source']}}" class="no-visited-indication">{{feed["source"]}}</a></td>
+ <td><a href="{{feed.source}}" class="no-visited-indication">{{feed.source}}</a></td>
</tr>
<tr>
<th>Tags</th>
<td>
- % tags = feed["tags"]
- % for i, tag in enumerate(tags):
+ % for i, tag in enumerate(feed.tags):
% if i > 0:
{{", "}}
% end
@@ -35,21 +34,21 @@
</tr>
</table>
<form method="post">
- <input type="hidden" name="id" value="{{feed['id']}}">
+ <input type="hidden" name="id" value="{{feed.id}}">
<div>
<label for="title-input">Title:</label>
- <input type="text" name="title" value="{{feed['title']}}" id="title-input">
+ <input type="text" name="title" value="{{feed.title}}" id="title-input">
</div>
<div>
<label for="source-input">Source:</label>
- <input type="text" name="source" value="{{feed['source']}}" id="source-input">
+ <input type="text" name="source" value="{{feed.source}}" id="source-input">
</div>
- % include("tag_input.tpl", input_name="tags", input_value=feed["serialised_tags"])
+ % include("tag_input.tpl", input_name="tags", input_value=serialised_tags)
<input type="submit" value="Update" name="update_feed">
</form>
<hr>
<form method="post" action="/delete_feed">
- <input type="number" name="id" value="{{feed['id']}}" style="display: none;">
+ <input type="number" name="id" value="{{feed.id}}" style="display: none;">
<input type="submit" value="Delete" name="delete_feed">
</form>
% include("footer.tpl")