feat: reader
This commit is contained in:
parent
dc09b4b353
commit
168d40789b
0
later42/libs/__init__.py
Normal file
0
later42/libs/__init__.py
Normal file
21
later42/libs/content.py
Normal file
21
later42/libs/content.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import requests
|
||||||
|
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
|
def sanitize_img_size(html: str):
|
||||||
|
soup = BeautifulSoup(html, 'html.parser')
|
||||||
|
for img in soup.find_all('img'):
|
||||||
|
img['width'] = '100%'
|
||||||
|
img['height'] = 'auto'
|
||||||
|
return str(soup)
|
||||||
|
|
||||||
|
|
||||||
|
def get_content(url: str):
|
||||||
|
url = settings.READABILITY_HOST.rstrip(
|
||||||
|
'/') + '/api/content/v1/parser?url=' + url
|
||||||
|
try:
|
||||||
|
return requests.get(url).json()
|
||||||
|
except KeyError:
|
||||||
|
return None
|
@ -7,12 +7,12 @@
|
|||||||
<div class="post-preview">
|
<div class="post-preview">
|
||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-between">
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<a href="{{ url.url }}">
|
<a href="{% url 'reader' url.id %}">
|
||||||
<h2 class="post-title">{{ url.title }}</h2>
|
<h2 class="post-title">{{ url.title }}</h2>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<a href="/archive/{{ url.id }}"><span class="fa-regular fa-square-check"></span></a>
|
<a href="{% url 'archive_url' url.id %}"><span class="fa-regular fa-square-check"></span></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if url.content %}
|
{% if url.content %}
|
||||||
|
35
later42/templates/reader.html
Normal file
35
later42/templates/reader.html
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="post-preview">
|
||||||
|
<!-- Post preview-->
|
||||||
|
{% if content %}
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<div class="p-2">
|
||||||
|
<h2 class="post-title">{{ content.title }}</h2>
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<div class="p-2">
|
||||||
|
<a href="{% url 'archive_url' url.id %}"><span class="fa-regular fa-square-check"></span> Отметить прочитанным</a>
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<a href="{{ url.url }}">Открыть оригинал статьи</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr class="my-4" />
|
||||||
|
{{ content.rich_content|safe }}
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<div class="p-2">
|
||||||
|
<a href="{% url 'archive_url' url.id %}"><span class="fa-regular fa-square-check"></span> Отметить прочитанным</a>
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<a href="{{ url.url }}">Открыть оригинал статьи</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<h2 class="post-title">Что-то пошло не так.</h2>
|
||||||
|
Открыть <a href="{{ url.url }}">оригинал ссылки</a>.
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
@ -22,7 +22,7 @@ from django.contrib.auth.views import LoginView
|
|||||||
from rest_framework import routers, serializers, viewsets
|
from rest_framework import routers, serializers, viewsets
|
||||||
|
|
||||||
from later42.forms import CustomLoginForm
|
from later42.forms import CustomLoginForm
|
||||||
from later42.views import index, profile, api, api_token, signup, about
|
from later42.views import index, profile, api, api_token, reader, signup, about
|
||||||
|
|
||||||
|
|
||||||
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
@ -53,5 +53,5 @@ urlpatterns = [
|
|||||||
path('about/', about.get, name='about'),
|
path('about/', about.get, name='about'),
|
||||||
path('archive/', index.archive, name='archive'),
|
path('archive/', index.archive, name='archive'),
|
||||||
path('archive/<int:url_id>', index.archive, name='archive_url'),
|
path('archive/<int:url_id>', index.archive, name='archive_url'),
|
||||||
|
path('reader/<int:url_id>', reader.get, name='reader'),
|
||||||
]
|
]
|
||||||
|
@ -1,41 +1,21 @@
|
|||||||
import requests
|
|
||||||
|
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
from bs4 import BeautifulSoup
|
from later42.libs.content import get_content
|
||||||
from later42.models.urls import URL as URLModel
|
from later42.models.urls import URL as URLModel
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
class URL(APIView):
|
class URL(APIView):
|
||||||
def get_title(self, url: str):
|
|
||||||
try:
|
|
||||||
response = requests.get(url)
|
|
||||||
soup = BeautifulSoup(response.text, 'html.parser')
|
|
||||||
title = soup.find('title').text
|
|
||||||
return title
|
|
||||||
except AttributeError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_content(self, url: str):
|
|
||||||
url = settings.READABILITY_HOST.rstrip(
|
|
||||||
'/') + '/api/content/v1/parser?url=' + url
|
|
||||||
try:
|
|
||||||
response = requests.get(url).json()
|
|
||||||
return response['excerpt']
|
|
||||||
except KeyError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def post(self, request, format=None):
|
def post(self, request, format=None):
|
||||||
url = request.GET.get('url')
|
url = request.GET.get('url')
|
||||||
if url:
|
if url:
|
||||||
title = self.get_title(url)
|
page = get_content(url)
|
||||||
if title is None:
|
|
||||||
title = url
|
title = page['title']
|
||||||
|
|
||||||
content = None
|
content = None
|
||||||
if settings.READABILITY_HOST:
|
if settings.READABILITY_HOST:
|
||||||
content = self.get_content(url)
|
content = page['excerpt']
|
||||||
|
|
||||||
url = URLModel(url=url, user=request.user,
|
url = URLModel(url=url, user=request.user,
|
||||||
title=title, content=content)
|
title=title, content=content)
|
||||||
|
17
later42/views/reader.py
Normal file
17
later42/views/reader.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from multiprocessing import context
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.shortcuts import render, redirect
|
||||||
|
from django.core.paginator import Paginator
|
||||||
|
from django.conf import settings
|
||||||
|
from later42.libs.content import get_content, sanitize_img_size
|
||||||
|
from later42.models.urls import URL
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def get(request, url_id=None):
|
||||||
|
url = URL.objects.get(
|
||||||
|
user=request.user, archived=False, id=url_id)
|
||||||
|
content = get_content(url.url)
|
||||||
|
content['rich_content'] = sanitize_img_size(content['rich_content'])
|
||||||
|
context = {'url': url, 'content': content}
|
||||||
|
return render(request, 'reader.html', context)
|
Loading…
Reference in New Issue
Block a user