Compare commits
9 commits
119a8b7094
...
b112b69f52
| Author | SHA1 | Date | |
|---|---|---|---|
|
b112b69f52 |
|||
|
232f1b7f66 |
|||
|
dfcb8975b8 |
|||
|
827f94bce3 |
|||
|
8def159a72 |
|||
|
649689eada |
|||
|
0bf0888324 |
|||
|
f9505da731 |
|||
|
63a9b8f301 |
7 changed files with 154 additions and 52 deletions
31
.env.example
Normal file
31
.env.example
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Django Configuration
|
||||||
|
# Set to False in production
|
||||||
|
DEBUG=True
|
||||||
|
|
||||||
|
# Django Secret Key
|
||||||
|
# Generate a new secret key for production: python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'
|
||||||
|
DJANGO_SECRET_KEY=your-secret-key-here
|
||||||
|
|
||||||
|
# Email Configuration
|
||||||
|
# SMTP Host (examples below)
|
||||||
|
EMAIL_HOST=smtp.gmail.com
|
||||||
|
|
||||||
|
# SMTP Port (common ports: 587 for TLS, 465 for SSL, 25 for unencrypted)
|
||||||
|
EMAIL_PORT=587
|
||||||
|
|
||||||
|
# Email credentials
|
||||||
|
EMAIL_HOST_USER=your-email@gmail.com
|
||||||
|
EMAIL_HOST_PASSWORD=your-app-password-here
|
||||||
|
|
||||||
|
# Connection security
|
||||||
|
# Use TLS (True for most providers like Gmail, Outlook)
|
||||||
|
EMAIL_USE_TLS=True
|
||||||
|
# Use SSL (False for most providers, True for some older configurations)
|
||||||
|
EMAIL_USE_SSL=False
|
||||||
|
|
||||||
|
# Connection timeout in seconds
|
||||||
|
EMAIL_TIMEOUT=10
|
||||||
|
|
||||||
|
# Redis Configuration
|
||||||
|
REDIS_URL_CACHE=unix:///var/run/redis/redis.sock?db=2
|
||||||
|
REDIS_URL_CELERY=unix:///var/run/redis/redis.sock?db=3
|
||||||
16
.vscode/launch.json
vendored
Normal file
16
.vscode/launch.json
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Python Debugger: Django",
|
||||||
|
"type": "debugpy",
|
||||||
|
"request": "launch",
|
||||||
|
"args": [
|
||||||
|
"runserver"
|
||||||
|
],
|
||||||
|
"django": true,
|
||||||
|
"autoStartBrowser": false,
|
||||||
|
"program": "${workspaceFolder}/manage.py"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
88
README.md
88
README.md
|
|
@ -2,40 +2,66 @@
|
||||||
|
|
||||||
_A seed vault for your feeds._
|
_A seed vault for your feeds._
|
||||||
|
|
||||||
[FeedVault](https://feedvault.se/) is an open-source web application that allows users to archive and search their favorite RSS, Atom, and JSON feeds. With FeedVault, users can effortlessly add their favorite feeds, ensuring they have a centralized location for accessing and preserving valuable content.
|
[FeedVault](https://feedvault.se/) is an free and open-source archive of RSS/Atom feeds.
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
_Note: Some features are currently in development._
|
|
||||||
|
|
||||||
- **Unified Feed Archiving**: Archive RSS (0.90 to 2.0), Atom (0.3, 1.0), JSON (1.0, 1.1), Dublin Core, and ITunes feeds seamlessly in one centralized location.
|
|
||||||
- **Content Search**: Easily search your archive for specific content.
|
|
||||||
- **Export Options**: Export your archive to various formats, including JSON, CSV, HTML, ODS, RST, TSV, XLS, XLSX, or YAML.
|
|
||||||
- **API**: Access your archive programmatically through a API.
|
|
||||||
- **Self-Hosting**: Host FeedVault on your own server for complete control over your data.
|
|
||||||
- **Privacy-Focused**: FeedVault respects user privacy by not tracking or collecting any personal data. It is an ad-free platform that prioritizes user security.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
- [Visit the FeedVault website](https://feedvault.se/).
|
|
||||||
- Sign up for an account or log in if you already have one.
|
|
||||||
- Add your favorite feeds to start archiving content.
|
|
||||||
- Explore, manage, and enjoy your centralized feed archive.
|
|
||||||
|
|
||||||
### CLI
|
|
||||||
|
|
||||||
There is a CLI available for FeedVault. You can run the CLI with the following command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python -m cli
|
|
||||||
```
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Feel free to contribute to the project. If you have any questions, please open an issue.
|
Feel free to contribute with anything. If you have any questions, please open an issue or reach out to me directly.
|
||||||
|
|
||||||
## Contact
|
I can be reached at [tlovinator@gmail.com](mailto:tlovinator@gmail.com) or on Discord: `TheLovinator#9276`
|
||||||
|
|
||||||
If you have any questions, please open an issue.
|
## Deployment
|
||||||
|
|
||||||
I can also be reached at [hello@panso.se](mailto:hello@panso.se) or on Discord: `TheLovinator#9276`
|
```bash
|
||||||
|
sudo pacman -S postgresql
|
||||||
|
sudo -u postgres initdb -D /var/lib/postgres/data
|
||||||
|
sudo systemctl enable --now postgresql
|
||||||
|
```
|
||||||
|
|
||||||
|
Create a local role and database:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -u postgres createuser -P feedvault
|
||||||
|
sudo -u postgres createdb -O feedvault feedvault
|
||||||
|
```
|
||||||
|
|
||||||
|
Point Django at the unix socket used by Arch (`/run/postgresql`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
POSTGRES_USER=feedvault
|
||||||
|
POSTGRES_PASSWORD=your_password
|
||||||
|
POSTGRES_DB=feedvault
|
||||||
|
POSTGRES_HOST=/run/postgresql
|
||||||
|
POSTGRES_PORT=5432
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo useradd --create-home --home-dir /home/feedvault --shell /bin/fish feedvault
|
||||||
|
sudo passwd feedvault
|
||||||
|
# sudo usermod -aG wheel feedvault
|
||||||
|
su - feedvault
|
||||||
|
git clone https://git.lovinator.space/TheLovinator/feedvault.se.git feedvault
|
||||||
|
cd feedvault
|
||||||
|
uv sync --no-dev
|
||||||
|
|
||||||
|
# Modify .env with the correct database credentials and other settings, then run migrations:
|
||||||
|
uv run python manage.py migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
Install the systemd service from the repo:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo install -m 0644 tools/systemd/feedvault.socket /etc/systemd/system/feedvault.socket
|
||||||
|
sudo install -m 0644 tools/systemd/feedvault.service /etc/systemd/system/feedvault.service
|
||||||
|
```
|
||||||
|
|
||||||
|
Enable and start the service:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable --now feedvault.socket
|
||||||
|
sudo systemctl enable --now feedvault.service
|
||||||
|
|
||||||
|
# Add to Nginx config and test with:
|
||||||
|
curl --unix-socket /run/feedvault/feedvault.sock https://feedvault.se
|
||||||
|
```
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,43 @@
|
||||||
import os
|
import os
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from celery import Celery
|
from celery import Celery
|
||||||
|
from celery import Signature
|
||||||
|
from celery.app.task import Task
|
||||||
|
from celery.contrib.abortable import AbortableAsyncResult
|
||||||
|
from celery.contrib.abortable import AbortableTask
|
||||||
|
from celery.contrib.django.task import DjangoTask
|
||||||
|
from celery.local import class_property
|
||||||
|
from celery.result import AsyncResult
|
||||||
|
from celery.utils.objects import FallbackContext
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from config.settings import Any
|
||||||
|
|
||||||
|
|
||||||
|
classes = [
|
||||||
|
Celery,
|
||||||
|
Task,
|
||||||
|
DjangoTask,
|
||||||
|
AbortableTask,
|
||||||
|
AsyncResult,
|
||||||
|
AbortableAsyncResult,
|
||||||
|
Signature,
|
||||||
|
FallbackContext,
|
||||||
|
class_property,
|
||||||
|
]
|
||||||
|
|
||||||
|
for cls in classes:
|
||||||
|
setattr( # noqa: B010
|
||||||
|
cls,
|
||||||
|
"__class_getitem__",
|
||||||
|
classmethod(lambda cls, *args, **kwargs: cls), # noqa: ARG005
|
||||||
|
)
|
||||||
|
|
||||||
# Set the default Django settings module for the 'celery' program.
|
# Set the default Django settings module for the 'celery' program.
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
|
||||||
|
|
||||||
app = Celery("config")
|
app: Celery[Task[Any, Any]] = Celery("config")
|
||||||
|
|
||||||
# Using a string here means the worker doesn't have to serialize
|
# Using a string here means the worker doesn't have to serialize
|
||||||
# the configuration object to child processes.
|
# the configuration object to child processes.
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,24 @@
|
||||||
"""URL configuration for config project.
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
from django.conf import settings
|
||||||
https://docs.djangoproject.com/en/6.0/topics/http/urls/
|
from django.conf.urls.static import static
|
||||||
|
from django.urls import include
|
||||||
Examples:
|
|
||||||
Function views
|
|
||||||
1. Add an import: from my_app import views
|
|
||||||
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
|
||||||
Class-based views
|
|
||||||
1. Add an import: from other_app.views import Home
|
|
||||||
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
|
||||||
Including another URLconf
|
|
||||||
1. Import the include() function: from django.urls import include, path
|
|
||||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
|
||||||
"""
|
|
||||||
|
|
||||||
from django.contrib import admin
|
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
urlpatterns = [
|
if TYPE_CHECKING:
|
||||||
path("admin/", admin.site.urls),
|
from django.urls import URLPattern
|
||||||
|
from django.urls.resolvers import URLResolver
|
||||||
|
|
||||||
|
urlpatterns: list[URLPattern | URLResolver] = [
|
||||||
|
path(route="silk/", view=include("silk.urls", namespace="silk")),
|
||||||
]
|
]
|
||||||
|
if settings.DEBUG:
|
||||||
|
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
|
|
||||||
|
if not settings.TESTING:
|
||||||
|
from debug_toolbar.toolbar import ( # pyright: ignore[reportMissingTypeStubs]
|
||||||
|
debug_toolbar_urls,
|
||||||
|
)
|
||||||
|
|
||||||
|
urlpatterns += [path("silk/", include("silk.urls", namespace="silk"))]
|
||||||
|
urlpatterns = [*urlpatterns, *debug_toolbar_urls()]
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,11 @@
|
||||||
"""WSGI config for config project.
|
|
||||||
|
|
||||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
|
||||||
|
|
||||||
For more information on this file, see
|
|
||||||
https://docs.djangoproject.com/en/6.0/howto/deployment/wsgi/
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from django.core.wsgi import get_wsgi_application
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from django.core.handlers.wsgi import WSGIHandler
|
||||||
|
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
|
||||||
|
|
||||||
application = get_wsgi_application()
|
application: WSGIHandler = get_wsgi_application()
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ dependencies = [
|
||||||
"django-celery-beat",
|
"django-celery-beat",
|
||||||
"django-celery-results",
|
"django-celery-results",
|
||||||
"django-debug-toolbar",
|
"django-debug-toolbar",
|
||||||
"django-silk",
|
"django-silk[formatting]",
|
||||||
"django",
|
"django",
|
||||||
"flower",
|
"flower",
|
||||||
"gunicorn",
|
"gunicorn",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue