Compare commits

...

13 Commits
v0.2 ... master

13 changed files with 62 additions and 35 deletions

View File

@ -28,7 +28,7 @@ HRSS is an application that allows you to transform any website into a RSS feed.
[Because we all love demos.](https://hrss.hipstercat.fr)
# Installation
# Installation (native)
1. Make sure you have Python3 installed and virtualenv.
2. Clone this repo for unstable branch, or download [latest release](https://hipstercat.fr/gogs/hipstercat/hrss/releases).
@ -36,4 +36,7 @@ HRSS is an application that allows you to transform any website into a RSS feed.
4. `bin/activate && pip3 install -r requirements.txt` to install dependencies.
5. `python3 manage.py migrate` to apply latest DB migrations (and create the H2 database file).
6. `python3 manage.py runserver` to run the integrated webserver (not suitable for production use - even though you should not use HRSS in a production environnement at all until it is considered stable anyway). Use uWSGI to run it in a production environnement.
# Installation (Docker)
Use https://github.com/kmlucy/docker-hrss nicely made by [kmlucy](https://github.com/kmlucy).

View File

@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/2.0/ref/settings/
"""
import os
import urllib.parse
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@ -27,6 +28,9 @@ DEBUG = True
ALLOWED_HOSTS = []
# Set up your website base URL here, WITHOUT A TRAILING SLASH.
BASE_URL = "http://localhost:8000"
# Application definition
@ -119,7 +123,7 @@ USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/
STATIC_URL = '/static/'
STATIC_URL = '/'+urllib.parse.urlparse(BASE_URL).path[1:]+'/static/' if urllib.parse.urlparse(BASE_URL).path[1:] else '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
USE_X_FORWARDED_HOST = True
@ -156,4 +160,6 @@ LOGGING = {
'level': 'ERROR',
}
}
}
}
X_FRAME_OPTIONS = 'SAMEORIGIN'

View File

@ -16,8 +16,12 @@ Including another URLconf
from django.contrib import admin
from django.urls import path
from django.conf.urls import include, url
from django.conf import settings
import urllib.parse
base_path = urllib.parse.urlparse(settings.BASE_URL).path[1:]
urlpatterns = [
path('admin/', admin.site.urls),
url(r'', include('web.urls')),
path(base_path+'/admin/' if base_path else 'admin/', admin.site.urls),
url(base_path+'/' if base_path else '', include('web.urls')),
]

View File

@ -1,3 +1,4 @@
from django.contrib import admin
from .models import Feed
# Register your models here.
admin.site.register(Feed)

View File

@ -1,11 +1,9 @@
from django.conf import settings
import urllib.parse
def BASE_URL(request):
"""
Return a BASE_URL template context for the current request.
"""
if request.is_secure():
scheme = 'https://'
else:
scheme = 'http://'
fullhost = request.get_host()
base = fullhost.split(":")[0]
return {'BASE_URL': scheme + base, }
parse = urllib.parse.urlparse(settings.BASE_URL)
return {'BASE_URL': parse.scheme+"://"+parse.netloc, }

View File

@ -10,7 +10,7 @@ def random_url():
class Feed(models.Model):
url = models.URLField(max_length=255)
element = models.CharField(max_length=255)
element = models.CharField(max_length=1000)
title = models.CharField(max_length=255)
content = models.CharField(max_length=255)
date = models.CharField(max_length=255)
@ -18,4 +18,4 @@ class Feed(models.Model):
link = models.CharField(max_length=255)
creation_date = models.DateTimeField(auto_now=True)
uurl = models.CharField(max_length=18, default=random_url, unique=True)
uurl = models.CharField(max_length=18, default=random_url, unique=True)

View File

@ -19,7 +19,7 @@
<div id="collapse{{ feed.id }}" class="collapse" aria-labelledby="heading{{ feed.id }}" data-parent="#accordionExample">
<div class="card-body">
<code>{{ BASE_URL }}/{{ feed.uurl }}.rss</code>
<code>{{ BASE_URL }}{% url 'rss' uurl=feed.uurl %}</code>
<p><a class="btn btn-danger" href="{% url 'feed_delete' feed.id %}">Delete</a></p>
</div>
</div>

View File

@ -5,7 +5,7 @@
<div class="col-lg-12 text-center">
<h1 class="mt-5">Generate RSS out of any website</h1>
{% if error %}<div class="alert alert-danger" role="alert">{{ error }}</div>{% endif %}
<form action="/" method="post">
<form action="{% url 'homepage' %}" method="post">
{% csrf_token %}
<div class="form-group">
<input type="text" class="form-control" name="url" id="url" placeholder="http://" {% if url %}value="{{ url }}"{% endif %}>

View File

@ -29,7 +29,7 @@
<code style="display:block" id="link-selector"></code>
</li>
<li>
<form action="/newfeed" method="post">
<form action="{% url 'newfeed' %}" method="post">
{% csrf_token %}
<input type="hidden" id="url" name="url" value="{{ url }}">
<input type="hidden" id="element" name="element" value="">
@ -44,7 +44,7 @@
</ul>
</div>
<!-- /#sidebar-wrapper -->
<iframe id="preview" style="width:100%" src="/iframe/{{ url }}"></iframe>
<iframe id="preview" style="width:100%" src="{% url 'iframe' encodedurl=encodedurl %}"></iframe>
<script>
$(function() {
function handleResize() {

View File

@ -26,14 +26,14 @@
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark static-top">
<div class="container">
<a class="navbar-brand" href="/">HRSS</a>
<a class="navbar-brand" href="{% url 'homepage' %}">HRSS</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" href="/">New
<a class="nav-link" href="{% url 'homepage' %}">New
<span class="sr-only">(current)</span>
</a>
</li>

View File

@ -3,8 +3,8 @@ from . import views
urlpatterns = [
url(r'^$', views.homepage, name='homepage'),
url(r'^iframe/(?P<url>.+)$', views.iframe, name='iframe'),
url(r'^setup/(?P<url>.+)$', views.setup, name='setup'),
url(r'^iframe/(?P<encodedurl>.+)$', views.iframe, name='iframe'),
url(r'^setup/(?P<encodedurl>.+)$', views.setup, name='setup'),
url(r'^newfeed$', views.newfeed, name='newfeed'),
url(r'^feeds$', views.feeds, name='feeds'),
url(r'^feeds/delete/(?P<id>[0-9]+)$', views.feed_delete, name='feed_delete'),

View File

@ -67,6 +67,12 @@ def fetch_feed(feed, limit=10):
author = False
try:
link = element.select(feed.link)[0]["href"]
if link and len(link) > 2 and link[0] == "/" and link[1] != "/":
# fixes issue #5 with relative link
# prepend base url
base_scheme = feed.url.split("://")[0]
base_url = feed.url.split("//")[-1].split("/")[0].split('?')[0]
link = base_scheme + "://" + base_url + link
except Exception:
link = False
items.append({"title": title, "content": content, "pubDate": date, "author": author, "link": link})

View File

@ -5,12 +5,17 @@ from .models import Feed
from django.db.models import ObjectDoesNotExist
from bs4 import BeautifulSoup
import logging
from urllib.parse import quote_plus, unquote_plus
import traceback
import sys
# Create your views here.
logger = logging.getLogger(__name__)
def iframe(request, url):
def iframe(request, encodedurl):
sys.setrecursionlimit(10000)
try:
url = unquote_plus(encodedurl)
req = get_url(url)
html = req.content
bs = False
@ -56,28 +61,32 @@ def iframe(request, url):
html = final_html
except Exception as e:
logger.debug(e)
traceback.print_exc()
return HttpResponse("An error has occured", content_type=500)
return HttpResponse(html, content_type=content_type)
def dummy(request):
return HttpResponse("toto")
def homepage(request):
if request.method == 'POST':
if "url" in request.POST and request.POST["url"]:
url = request.POST["url"]
if is_valid_url(url):
return redirect("/setup/"+url)
return redirect("setup", encodedurl=quote_plus(url))
else:
return render(request, 'homepage.html', {"url": url, "error": url+" is not a valid URL."})
return render(request, 'homepage.html')
def setup(request, url):
if is_valid_url(url):
return render(request, 'setup.html', {"url": url})
def setup(request, encodedurl):
decoded_url = unquote_plus(encodedurl)
if is_valid_url(decoded_url):
return render(request, 'setup.html', {"encodedurl": encodedurl, "url": decoded_url})
else:
return redirect("/")
return redirect("homepage")
def newfeed(request):
@ -110,9 +119,9 @@ def newfeed(request):
feed = Feed(url=url, element=element, title=title, content=content, date=date, author=author, link=link)
feed.save()
return redirect("/feeds")
return redirect("feeds")
else:
return redirect("/")
return redirect("homepage")
def feeds(request):
feeds = Feed.objects.all()
@ -124,11 +133,11 @@ def feed_delete(request, id):
if not request.get_host() == "hrss.hipstercat.fr:443":
Feed.objects.get(pk=id).delete()
logger.info("Removed feed ID "+id)
return redirect("/feeds")
return redirect("feeds")
else:
return HttpResponse("Deleting is disabled on demo website.", status=403)
except ObjectDoesNotExist:
return redirect("/feeds")
return redirect("feeds")
def rss(request, uurl):
try: