Update HTML
This commit is contained in:
parent
efc4a26340
commit
6f544db209
8 changed files with 137 additions and 41 deletions
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
|
|
@ -4,6 +4,7 @@
|
|||
"feedburner",
|
||||
"feedparser",
|
||||
"feedvault",
|
||||
"leftright",
|
||||
"PGHOST",
|
||||
"PGPORT",
|
||||
"PGUSER",
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
from django.urls import path
|
||||
|
||||
from feeds.views import FeedsView, IndexView
|
||||
from feeds.views import APIView, FeedsView, IndexView, add_feeds
|
||||
|
||||
app_name = "feeds"
|
||||
|
||||
|
|
@ -11,4 +11,8 @@ urlpatterns = [
|
|||
path("", IndexView.as_view(), name="index"),
|
||||
# /feeds
|
||||
path("feeds", FeedsView.as_view(), name="feeds"),
|
||||
# /add
|
||||
path("add", add_feeds, name="add"),
|
||||
# /api
|
||||
path("api", APIView.as_view(), name="api"),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -8,12 +8,17 @@ from __future__ import annotations
|
|||
|
||||
import typing
|
||||
|
||||
from django.contrib import messages
|
||||
from django.db import connection
|
||||
from django.shortcuts import redirect
|
||||
from django.views.generic.base import TemplateView
|
||||
from django.views.generic.list import ListView
|
||||
|
||||
from feeds.models import Feed
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from django.http import HttpRequest, HttpResponseRedirect
|
||||
|
||||
|
||||
def get_database_size() -> int:
|
||||
"""Get the size of a database.
|
||||
|
|
@ -65,3 +70,45 @@ class FeedsView(ListView):
|
|||
context["feed_count"] = Feed.objects.count()
|
||||
context["database_size"] = get_database_size()
|
||||
return context
|
||||
|
||||
|
||||
def add_feeds(request: HttpRequest) -> HttpResponseRedirect:
|
||||
"""Add feeds to the database.
|
||||
|
||||
Args:
|
||||
request: The request object.
|
||||
|
||||
Returns:
|
||||
A redirect to the index page.
|
||||
"""
|
||||
if request.method == "POST":
|
||||
urls = request.POST.get("urls")
|
||||
if not urls:
|
||||
messages.error(request, "No URLs provided")
|
||||
return redirect("feeds:index", permanent=False)
|
||||
|
||||
if urls == "Test":
|
||||
messages.error(request, "Hello, world!")
|
||||
return redirect("feeds:index", permanent=False)
|
||||
|
||||
for url in urls.splitlines():
|
||||
print(f"Adding {url} to the database...") # noqa: T201
|
||||
|
||||
return redirect("feeds:feeds", permanent=False)
|
||||
|
||||
msg: str = f"You must use a POST request. You used a {request.method} request. You can find out how to use this endpoint here: <a href=''>http://127.0.0.1:8000/</a>. If you think this is a mistake, please contact the administrator." # noqa: E501
|
||||
messages.error(request, msg)
|
||||
return redirect("feeds:index", permanent=False)
|
||||
|
||||
|
||||
class APIView(TemplateView):
|
||||
"""Index page."""
|
||||
|
||||
template_name = "api.html"
|
||||
|
||||
def get_context_data(self: APIView, **kwargs: dict) -> dict:
|
||||
"""Add feed count and database size to context data."""
|
||||
context: dict = super().get_context_data(**kwargs)
|
||||
context["feed_count"] = Feed.objects.count()
|
||||
context["database_size"] = get_database_size()
|
||||
return context
|
||||
|
|
|
|||
1
static/Feed.svg
Normal file
1
static/Feed.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 256 256" cursor="default"><defs><linearGradient x1=".085" y1=".085" x2=".915" y2=".915" id="prefix__a"><stop offset="0" stop-color="#E3702D"/><stop offset=".107" stop-color="#EA7D31"/><stop offset=".35" stop-color="#F69537"/><stop offset=".5" stop-color="#FB9E3A"/><stop offset=".702" stop-color="#EA7C31"/><stop offset=".887" stop-color="#DE642B"/><stop offset="1" stop-color="#D95B29"/></linearGradient></defs><rect width="256" height="256" rx="55" ry="55" fill="#CC5D15"/><rect width="246" height="246" rx="50" ry="50" x="5" y="5" fill="#F49C52"/><rect width="236" height="236" rx="47" ry="47" x="10" y="10" fill="url(#prefix__a)"/><circle cx="68" cy="189" r="24" fill="#FFF"/><path d="M160 213h-34a82 82 0 00-82-82V97a116 116 0 01116 116z" fill="#FFF"/><path d="M184 213A140 140 0 0044 73V38a175 175 0 01175 175z" fill="#FFF"/></svg>
|
||||
|
After Width: | Height: | Size: 916 B |
|
|
@ -1,25 +1,19 @@
|
|||
html {
|
||||
max-width: 70ch;
|
||||
/* larger spacing on larger screens, very small spacing on tiny screens */
|
||||
padding: calc(1vmin + 0.5rem);
|
||||
/* shorthand for margin-left/margin-right */
|
||||
margin-inline: auto;
|
||||
/* fluid sizing: https://frontaid.io/blog/fluid-typography-2d-css-locks-clamp/ */
|
||||
font-size: clamp(1em, 0.909em + 0.45vmin, 1.25em);
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
|
||||
Arial, sans-serif;
|
||||
/* use dark mode if user prefers it */
|
||||
color-scheme: light dark;
|
||||
}
|
||||
|
||||
/* h1 */
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 600;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* FeedVault logo */
|
||||
.title {
|
||||
text-align: center;
|
||||
}
|
||||
|
|
@ -27,21 +21,15 @@ h1 {
|
|||
.search {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
/* Spacing between search bar and nav bar */
|
||||
margin-top: 1rem;
|
||||
|
||||
/* Center the search bar */
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
/* Links at the top and bottom of the page */
|
||||
.leftright {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Align the links to the left and right */
|
||||
.left {
|
||||
margin-right: auto;
|
||||
}
|
||||
|
|
@ -50,9 +38,16 @@ h1 {
|
|||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* Add feeds box */
|
||||
textarea {
|
||||
width: 100%;
|
||||
height: 10rem;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.messages {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
|
|
|||
8
templates/api.html
Normal file
8
templates/api.html
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{% extends "base.html" %}
|
||||
{% block title %}<title>Feeds</title>{% endblock %}
|
||||
{% block description %}FeedVault - A feed archive{% endblock %}
|
||||
{% block keywords %}RSS, Atom, Feed, Archive{% endblock %}
|
||||
{% block content %}
|
||||
<h2>API documentation</h2>
|
||||
<p>Here be dragons.</p>
|
||||
{% endblock %}
|
||||
|
|
@ -13,20 +13,39 @@
|
|||
{% if canonical_url %}<link rel="canonical" href="{{ canonical_url }}">{% endif %}
|
||||
</head>
|
||||
<body>
|
||||
{% if messages %}
|
||||
<ul class="messages">
|
||||
{% for message in messages %}
|
||||
<li {% if message.tags %}class="{{ message.tags }}"{% endif %}>{{ message|safe }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<hr>
|
||||
{% endif %}
|
||||
<span class="title">
|
||||
<a href="{% url 'feeds:index' %}">
|
||||
<h1>FeedVault</h1>
|
||||
</a>
|
||||
<h1>
|
||||
<a href="{% url 'feeds:index' %}">FeedVault</a>
|
||||
</h1>
|
||||
</span>
|
||||
<small>An archive of <a href="https://en.wikipedia.org/wiki/Web_feed">web feeds</a>. Currently archiving {{ feed_count }} feeds. ~{{ database_size|floatformat:2 }} MB of data.</small>
|
||||
<div class="leftright">
|
||||
<div class="left">
|
||||
<small>Archive of <a href="https://en.wikipedia.org/wiki/Web_feed">web feeds</a>. {{ feed_count }} feeds. ~{{ database_size|floatformat:2 }} MB.</small>
|
||||
</div>
|
||||
<div class="right">
|
||||
<!-- Search -->
|
||||
<form action="#" method="get">
|
||||
<input type="text" name="q" placeholder="Search">
|
||||
<button type="submit">Search</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<nav>
|
||||
<small>
|
||||
<div class="leftright">
|
||||
<div class="left">
|
||||
<a href="{% url 'feeds:feeds' %}">Feeds</a> | <a href="">About</a> | <a href="">API</a> | <a href="">Stats</a> | <a href="">GitHub</a> | <a href="">Donate</a>
|
||||
<a href="{% url 'feeds:feeds' %}">Feeds</a> | <a href="{% url 'feeds:api' %}">API</a> | <a href="https://github.com/TheLovinator1/FeedVault">GitHub</a> | <a href="https://github.com/sponsors/TheLovinator1">Donate</a>
|
||||
</div>
|
||||
<div class="right">
|
||||
<a href="">Login</a>
|
||||
<a href="">Register</a> | <a href="">Login</a>
|
||||
</div>
|
||||
</div>
|
||||
</small>
|
||||
|
|
|
|||
|
|
@ -15,46 +15,67 @@
|
|||
<br>
|
||||
<br>
|
||||
<details>
|
||||
<summary>What is RSS and Atom?</summary>
|
||||
<summary>What are web feeds?</summary>
|
||||
<p>
|
||||
RSS and Atom are two different formats for <a href="https://en.wikipedia.org/wiki/Web_feed">web feeds</a>. They are used to publish frequently updated content such as blog posts, news articles, etc.
|
||||
Web feeds are a way for you to "subscribe" to content on a website. When you subscribe to a feed, you will be notified when new content is published. You can then read the content in a feed reader.
|
||||
Feeds are usually available in the RSS or Atom format. You can recognize a feed by the following icon:
|
||||
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgMjU2IDI1NiIgY3Vyc29yPSJkZWZhdWx0Ij48ZGVmcz48bGluZWFyR3JhZGllbnQgeDE9Ii4wODUiIHkxPSIuMDg1IiB4Mj0iLjkxNSIgeTI9Ii45MTUiIGlkPSJwcmVmaXhfX2EiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iI0UzNzAyRCIvPjxzdG9wIG9mZnNldD0iLjEwNyIgc3RvcC1jb2xvcj0iI0VBN0QzMSIvPjxzdG9wIG9mZnNldD0iLjM1IiBzdG9wLWNvbG9yPSIjRjY5NTM3Ii8+PHN0b3Agb2Zmc2V0PSIuNSIgc3RvcC1jb2xvcj0iI0ZCOUUzQSIvPjxzdG9wIG9mZnNldD0iLjcwMiIgc3RvcC1jb2xvcj0iI0VBN0MzMSIvPjxzdG9wIG9mZnNldD0iLjg4NyIgc3RvcC1jb2xvcj0iI0RFNjQyQiIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI0Q5NUIyOSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHdpZHRoPSIyNTYiIGhlaWdodD0iMjU2IiByeD0iNTUiIHJ5PSI1NSIgZmlsbD0iI0NDNUQxNSIvPjxyZWN0IHdpZHRoPSIyNDYiIGhlaWdodD0iMjQ2IiByeD0iNTAiIHJ5PSI1MCIgeD0iNSIgeT0iNSIgZmlsbD0iI0Y0OUM1MiIvPjxyZWN0IHdpZHRoPSIyMzYiIGhlaWdodD0iMjM2IiByeD0iNDciIHJ5PSI0NyIgeD0iMTAiIHk9IjEwIiBmaWxsPSJ1cmwoI3ByZWZpeF9fYSkiLz48Y2lyY2xlIGN4PSI2OCIgY3k9IjE4OSIgcj0iMjQiIGZpbGw9IiNGRkYiLz48cGF0aCBkPSJNMTYwIDIxM2gtMzRhODIgODIgMCAwMC04Mi04MlY5N2ExMTYgMTE2IDAgMDExMTYgMTE2eiIgZmlsbD0iI0ZGRiIvPjxwYXRoIGQ9Ik0xODQgMjEzQTE0MCAxNDAgMCAwMDQ0IDczVjM4YTE3NSAxNzUgMCAwMTE3NSAxNzV6IiBmaWxsPSIjRkZGIi8+PC9zdmc+"
|
||||
alt="Feed icon"
|
||||
width="16"
|
||||
height="16">
|
||||
<br>
|
||||
<br>
|
||||
You can read more about web feeds on <a href="https://en.wikipedia.org/wiki/Web_feed">Wikipedia</a>.
|
||||
</p>
|
||||
<hr>
|
||||
</details>
|
||||
<details>
|
||||
<summary>What is FeedVault?</summary>
|
||||
<p>
|
||||
FeedVault is designed to collect, organize, and store information from RSS feeds. It parses XML data using the <a href="https://github.com/kurtmckee/feedparser">feedparser by Kurt McKee</a> library and stores the relevant information in a PostgreSQL database managed by Django.
|
||||
</p>
|
||||
<hr>
|
||||
</details>
|
||||
<details>
|
||||
<summary>Why archive feeds?</summary>
|
||||
<p>
|
||||
<h3>Preserving Content History</h3>
|
||||
<p>
|
||||
The web is constantly changing. Websites are redesigned, articles are deleted, and content is lost. By archiving feeds, we can preserve the history of the web.
|
||||
</p>
|
||||
<h3>Research and Reference</h3>
|
||||
<p>
|
||||
Researchers, journalists, or individuals conducting studies may find value in archiving RSS feeds to create a reference library. This can aid in analyzing trends, tracking changes in information, or referencing past data for various purposes.
|
||||
</p>
|
||||
<h3>Long-Term Availability</h3>
|
||||
<p>
|
||||
Websites and feeds may change or disappear over time due to various reasons. Archiving ensures that users have a reliable and persistent source for accessing content even if the original sources are no longer available.
|
||||
</p>
|
||||
<h3>Content Analysis and Statistics</h3>
|
||||
<p>
|
||||
Archiving feeds can facilitate content analysis and statistical insights. Users may want to track the frequency of updates, analyze the popularity of certain topics, or gather data for research purposes.
|
||||
</p>
|
||||
The web is constantly changing. Websites are redesigned, content is removed, and links are broken. By archiving feeds, we can preserve the content that is published on the web.
|
||||
</p>
|
||||
<hr>
|
||||
</details>
|
||||
<details>
|
||||
<summary>How does it work?</summary>
|
||||
<p>
|
||||
FeedVault uses <a href="https://github.com/kurtmckee/feedparser">feedparser</a> to parse the feeds. The parsed feeds are then stored in a database. The feeds are updated every 30 minutes.
|
||||
<ul>
|
||||
<li>
|
||||
Parse XML data using the <a href="https://github.com/kurtmckee/feedparser">feedparser</a> library.
|
||||
</li>
|
||||
<li>
|
||||
Before saving the parsed data to the database, HTML content is <a href="https://feedparser.readthedocs.io/en/latest/html-sanitization.html">sanitized</a>.
|
||||
</li>
|
||||
<li>The sanitized data is then stored in a PostgreSQL database using Django's ORM.</li>
|
||||
<li>
|
||||
The data is then made available through the website and the <a href="/api">API</a>.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
<hr>
|
||||
</details>
|
||||
<details>
|
||||
<summary>How can I access the archived feeds?</summary>
|
||||
<p>
|
||||
You can find feeds by using the search bar at the top of the page. You can also use the <a href="/api">API</a> to access the feeds.
|
||||
<ul>
|
||||
<li>You can search for feeds through the search bar at the top of the page.</li>
|
||||
<li>
|
||||
You can access the archived feeds through the <a href="/feeds">website</a>.
|
||||
</li>
|
||||
<li>
|
||||
You can access the archived feeds through the <a href="/api">API</a>.
|
||||
</li>
|
||||
<li>
|
||||
You can download database dumps from <a href="">here</a>.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
<hr>
|
||||
</details>
|
||||
{% endblock %}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue