This commit is contained in:
FoxMaSk 2022-02-05 21:39:55 +01:00
parent 828811abf1
commit 5edf3d6f7f
12 changed files with 142 additions and 41 deletions

1
.gitignore vendored
View File

@ -112,3 +112,4 @@ venv.bak/
*.sqlite*
static
settings_debug.py

View File

@ -1,6 +1,7 @@
include VERSION.txt
# exclude manage.py shaarpy/.env static tox.ini pytest.ini
exclude shaarpy/settings_debug.py
recursive-include shaarpy *.html *.png *.css *.py *.md env.sample

View File

@ -160,8 +160,8 @@ setup the database
```bash
cd shaarpy
python manage.py createsuperuser
python manage.py migrate
python manage.py createsuperuser
python manage.py loaddata shaarpy/fixtures/my_shaarpy_data.json
```

View File

@ -6,4 +6,4 @@ pytest-django
semgrep
pipdeptree
twine
tox
django-debug-toolbar

View File

@ -22,10 +22,17 @@ classifiers=
Topic :: Communications
Topic :: Database
project_urls =
Documentation = https://framagit.org/foxmask/shaarpy/-/wikis/home
Source = https://framagit.org/foxmask/shaarpy/
Tracker = https://framagit.org/foxmask/shaarpy/-/issues
[options]
python_requires=>=3.8
packages=find:
include_package_data=true
zip_safe=false
include_package_data=true
install_requires=
Django==4.0.1
@ -42,6 +49,6 @@ exclude=
tests
[flake8]
max-line-length=120
exclude=.tox,build
max-line-length=119
exclude=.tox,build,.git
ignore = E402, F401

View File

@ -5,7 +5,6 @@
from django.contrib.auth.models import User
from django.utils.translation import gettext_lazy as _
from django.forms import ModelForm, TextInput, Textarea, CheckboxInput, EmailInput, HiddenInput
from shaarpy.models import Links
from shaarpy.tools import url_cleaning
@ -48,8 +47,13 @@ class LinksForm(ModelForm):
"""
remove extra space
"""
unwanted_chars = '?./:;!#&@{}[]|`\\^~*+=-_'
data = self.cleaned_data['tags']
if data:
if any(s in unwanted_chars for s in data):
msg = _(f"characters {unwanted_chars} not allowed.")
self.add_error('tags', msg)
if data.endswith(','):
data = data[:-1]
return data.replace(' ', '')

View File

@ -2,15 +2,16 @@
"""
ShaarPy :: Exporting in markdown
"""
import os.path
from django.core.management.base import BaseCommand
import logging
import os.path
from rich.console import Console
from shaarpy.models import Links
from shaarpy.tools import create_md_file
from slugify import slugify
console = Console()
logger = logging.getLogger("command")
__author__ = 'FoxMaSk'
@ -27,7 +28,9 @@ class Command(BaseCommand):
if os.path.exists(options['folder']):
for link in links:
file_name = slugify(link.title) + '.md'
console.print(f"Shaarpy :: Exporting md file {options['folder']}/{file_name}", style="green")
log = f"Shaarpy :: Exporting md file {options['folder']}/{file_name}"
console.print(log, style="green")
logger.info(log)
create_md_file(options['folder'],
link.title,
link.url,

View File

@ -10,10 +10,10 @@ https://docs.djangoproject.com/en/4.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.0/ref/settings/
"""
from pathlib import Path
from django.urls import reverse_lazy
import environ
import os
from pathlib import Path
env = environ.Env()
@ -117,6 +117,67 @@ AUTH_PASSWORD_VALIDATORS = [
},
]
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format':
'%(asctime)s %(levelname)s %(module)s %(process)d %(message)s'
},
'simple': {
'format': '%(levelname)s %(message)s'
},
},
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse'
}
},
'handlers': {
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
},
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'simple'
},
'file': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': BASE_DIR / 'shaarpy.log',
'maxBytes': 61280,
'backupCount': 3,
'formatter': 'verbose',
},
},
'loggers':
{
'django.request': {
'handlers': ['mail_admins', 'file'],
'level': 'ERROR',
'propagate': True,
},
'shaarpy.views': {
'handlers': ['console', 'file'],
'level': 'INFO',
},
'shaarpy.command': {
'handlers': ['console', 'file'],
'level': 'INFO',
},
'shaarpy.tools': {
'handlers': ['console', 'file'],
'level': 'INFO',
},
}
}
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
@ -148,7 +209,8 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
CSRF_TRUSTED_ORIGINS = env.list('CSRF_TRUSTED_ORIGINS')
LOGOUT_REDIRECT_URL = '/'
LOGIN_REDIRECT_URL = reverse_lazy('base')
LOGOUT_REDIRECT_URL = reverse_lazy('base')
SHAARPY_AUTHOR = env.str('SHAARPY_AUTHOR', default="FoxMaSk")
SHAARPY_NAME = env.str('SHAARPY_NAME', default=f"ShaarPy - {SHAARPY_AUTHOR} Links")

View File

@ -23,54 +23,60 @@
{% endif %}
<div class="mb-3">
<label class="form-label" for="id_url"> URL</label>
<div>{{ form.url }}</div>
{% if form.url.errors %}
<div class="col-sm-offset-2 col-sm-8 alert alert-danger" role="alert">{{ form.url.errors }}</div>
{% endif %}
{{ form.url }}
</div>
{% if form.url.errors %}
<div class="alert alert-danger" role="alert">{{ form.url.errors }}</div>
{% endif %}
<div class="mb-3">
<label class="form-label" for="id_title"> {% trans 'Title' %}</label>
<div>{{ form.title }}</div>
{% if form.title.errors %}
<div class="col-sm-offset-2 col-sm-8 alert alert-danger">{{ form.title.errors }}</div>
{% endif %}
{{ form.title }}
</div>
{% if form.title.errors %}
<div class="alert alert-danger" role="alert">{{ form.title.errors }}</div>
{% endif %}
{% if edit_link %}
<div class="mb-3">
<label class="form-label" for="id_image"> {% trans 'Image' %}</label>
<div>{{ form.image }}</div>
{% if form.image.errors %}
<div class="col-sm-offset-2 col-sm-8 alert alert-danger">{{ form.image.errors }}</div>
{% endif %}
{{ form.image }}
</div>
{% if form.image.errors %}
<div class="alert alert-danger" role="alert">{{ form.image.errors }}</div>
{% endif %}
{% endif %}
<div class="mb-3">
<label class="form-label" for="id_text"> {% trans 'Text' %}</label>
<div class="">{{ form.text }}</div>
{% if form.text.errors %}
<div class="col-sm-offset-2 col-sm-8 alert alert-danger">{{ form.text.errors }}</div>
{% endif %}
{{ form.text }}
</div>
{% if form.text.errors %}
<div class="alert alert-danger" role="alert">{{ form.text.errors }}</div>
{% endif %}
<div class="input-group input-group-sm mb-3">
<span class="input-group-text" id="basic-addon1"><i class="fas fa-tags"></i></span>{{ form.tags }}
{% if form.tags.errors %}
<div class="col-sm-offset-2 col-sm-8 alert alert-danger">{{ form.tags.errors }}</div>
{% endif %}
</div>
{% if form.tags.errors %}
<div class="alert alert-danger" role="alert">
{{ form.tags.errors }}
</div>
{% endif %}
<div class="mb-3">
<label class="form-label" for="id_private"><i class="fas fa-user-secret"></i> {% trans 'Private' %}</label>
<div>{{ form.private }}</div>
{% if form.private.errors %}
<div class="col-sm-offset-2 col-sm-8 alert alert-danger">{{ form.private.errors }}</div>
{% endif %}
{{ form.private }}
</div>
{% if form.private.errors %}
<div class="alert alert-danger" role="alert">
{{ form.private.errors }}
</div>
{% endif %}
<div class="mb-3">
<label class="form-label" for="id_sticky"><i class="fas fa-thumbtack"></i> {% trans 'Sticky' %}</label>
<div>{{ form.sticky }}</div>
{% if form.sticky.errors %}
<div class="col-sm-offset-2 col-sm-8 alert alert-danger">{{ form.sticky.errors }}</div>
{% endif %}
{{ form.sticky }}
</div>
{% if form.sticky.errors %}
<div class="alert alert-danger" role="alert">
{{ form.sticky.errors }}
</div>
{% endif %}
{% if edit_link %}
<a href="{% url 'link_detail' object.url_hashed %}" class="btn btn-success"><i class="fas fa-long-arrow-alt-left"></i> {% trans "Back" %}</a>
<button class="btn btn-primary">{% trans "Update link" %}</button>

View File

@ -14,6 +14,7 @@ from django.utils import timezone
from django.utils.text import Truncator
import html
from jinja2 import Environment, PackageLoader
import logging
from newspaper import Article
import os
@ -29,7 +30,7 @@ from slugify import slugify
from urllib.parse import urlparse
console = Console()
logger = logging.getLogger('tools')
"""
URL
"""
@ -200,6 +201,7 @@ def import_shaarli(the_file, reload_article_from_url): # noqa: C901
private = 0
with open(the_file, 'r') as f:
data = f.read()
logger.debug(f"ShaarPy :: importing {the_file}")
if data.startswith('<!DOCTYPE NETSCAPE-Bookmark-file-1>'):
i = 0
@ -275,6 +277,7 @@ def import_shaarli(the_file, reload_article_from_url): # noqa: C901
obj.image = link['image']
obj.video = link['video']
obj.url_hashed = small_hash(link['date_created'].strftime("%Y%m%d_%H%M%S"))
logger.debug(f"ShaarPy :: updating {obj.url}")
obj.save()
except Links.DoesNotExist:
new_values = {'url': link['url'],
@ -289,5 +292,6 @@ def import_shaarli(the_file, reload_article_from_url): # noqa: C901
}
obj = Links(**new_values)
obj.save()
logger.debug(f"ShaarPy :: creating {obj.url}")
console.print(table)

View File

@ -47,6 +47,13 @@ urlpatterns = [
path('admin/', admin.site.urls),
]
"""
if settings.DEBUG:
urlpatterns += [
path('__debug__/', include('debug_toolbar.urls')),
]
"""
handler403 = 'shaarpy.views.error_403'
handler404 = 'shaarpy.views.error_404'
handler500 = 'shaarpy.views.error_500'

View File

@ -16,6 +16,7 @@ from django.urls import reverse, reverse_lazy
from django.utils import timezone
from django.views.generic import ListView, CreateView, UpdateView, DetailView
from django.views.generic.base import TemplateView
import logging
import pypandoc
from shaarpy.forms import LinksForm, LinksFormEdit, MeForm
from shaarpy.models import Links
@ -26,6 +27,8 @@ from simple_search import search_form_factory
# call the cache
shaarpy_cache = caches['default']
logger = logging.getLogger("views")
@login_required
def link_delete(request, pk):
@ -33,6 +36,7 @@ def link_delete(request, pk):
if 'page' in request.GET:
page = request.GET.get('page')
link = Links.objects.get(pk=pk)
logger.info(f'ShaarPy :: delete ShaarPy {pk}')
if link.title is not None and settings.SHAARPY_LOCALSTORAGE_MD:
rm_md_file(link.title)
link.delete()
@ -54,6 +58,7 @@ class SuccessMixin:
# clear the cache when creating/updating a note/link
# otherwise, the update would have to wait the time of `CACHE_MIDDLEWARE_SECONDS`
# to be available
logger.debug('ShaarPy :: clear application cache')
shaarpy_cache.clear()
# then go back to ...
return reverse('link_detail', kwargs={'slug': self.object.url_hashed})
@ -178,6 +183,7 @@ class LinksCreate(SettingsMixin, SuccessMixin, LoginRequiredMixin, CreateView):
try:
# check if url already exist and then redirect to it
links = Links.objects.get(url=url)
logger.debug(f"ShaarPy :: link already exists {url}")
return redirect('link_detail', **{'slug': links.url_hashed})
except Links.DoesNotExist:
pass
@ -194,7 +200,7 @@ class LinksCreate(SettingsMixin, SuccessMixin, LoginRequiredMixin, CreateView):
self.object.url_hashed = small_hash(self.object.date_created.strftime("%Y%m%d_%H%M%S"))
self.object = form.save()
logger.debug(f"ShaarPy :: create {self.object.url} {self.object.title} {self.object.tags}")
if settings.SHAARPY_LOCALSTORAGE_MD:
create_md_file(settings.SHAARPY_LOCALSTORAGE_MD,
self.object.title, self.object.url, self.object.text, self.object.tags,