diff --git a/discord_rss_bot/feeds.py b/discord_rss_bot/feeds.py
index d796e0b..a25e84e 100644
--- a/discord_rss_bot/feeds.py
+++ b/discord_rss_bot/feeds.py
@@ -63,3 +63,5 @@ def send_to_discord(feed=None) -> None:
response: Response = webhook.execute()
if not response.ok:
reader.set_entry_read(entry, False)
+
+ reader.update_search()
diff --git a/discord_rss_bot/main.py b/discord_rss_bot/main.py
index 57a1c3c..dab4e67 100644
--- a/discord_rss_bot/main.py
+++ b/discord_rss_bot/main.py
@@ -37,7 +37,7 @@ from fastapi import FastAPI, Form, HTTPException, Request
from fastapi.responses import FileResponse, HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
-from reader import Entry, EntryCounts, Feed, FeedCounts
+from reader import Entry, EntryCounts, EntrySearchResult, Feed, FeedCounts, HighlightedString
from starlette.templating import _TemplateResponse
from tomlkit.toml_document import TOMLDocument
@@ -100,6 +100,8 @@ async def create_feed(feed_url: str = Form(), webhook_dropdown: str = Form()) ->
reader.set_tag(feed_url, "webhook", webhook_url)
reader.get_tag(feed_url, "webhook")
+ reader.update_search()
+
# TODO: Go to the feed page.
return {"feed_url": str(feed_url), "status": "added"}
@@ -224,11 +226,70 @@ async def remove_feed(request: Request, feed_url: str = Form()):
"""
reader.delete_feed(feed_url)
+ reader.update_search()
context = make_context_index(request)
return templates.TemplateResponse("index.html", context)
+@app.get("/search", response_class=HTMLResponse)
+async def search(request: Request, query: str) -> _TemplateResponse:
+ """
+ Get entries matching a full-text search query.
+
+ Args:
+ request: The request.
+ query: The query to search for.
+
+ Returns:
+ HTMLResponse: The HTML response.
+ """
+ reader.update_search()
+ search_results = reader.search_entries(query)
+ search_amount = reader.search_entry_counts(query)
+
+ def add_span_with_slice(highlighted_string: HighlightedString):
+ """Add a span with the highlighted string."""
+
+ for txt_slice in highlighted_string.highlights:
+ first = f"{highlighted_string.value[: txt_slice.start]}"
+ second = f"{highlighted_string.value[txt_slice.start: txt_slice.stop]}"
+ third = f"{highlighted_string.value[txt_slice.stop:]}"
+ return f"{first}{second}{third}"
+
+ def create_html_for_search_results(search_results: Iterable[EntrySearchResult]) -> str:
+ """Create HTML for the search results.
+
+ Args:
+ search_results: The search results.
+
+ Returns:
+ str: The HTML.
+ """
+ html = ""
+ for result in search_results:
+ if ".summary" in result.content:
+ result_summary = add_span_with_slice(result.content[".summary"])
+ feed = reader.get_feed(result.feed_url)
+ feed_url = encode_url(feed.url)
+
+ html += f"""
+
+ {result.metadata[".title"]}
+
+
+ {result_summary} ++