gawa/gawa/start/models.py
2023-10-10 12:29:43 +02:00

105 lines
3.6 KiB
Python

import random
import favicon
import requests
from django.db import models
from django.db.models.options import override
from django.utils.translation import gettext as _
from django.core.files import File
from django.conf import settings
import logging
logger = logging.getLogger(__name__)
class Keyword(models.Model):
"""
this is the model that should contain searchable keywords
"""
slug = models.SlugField(unique=True)
text_de = models.CharField(max_length=40)
text_en = models.CharField(max_length=40)
def __str__(self):
return f"{{<{self.__class__.__name__}>\"{self.slug}\"}}"
class Meta:
verbose_name = _("Keyword")
verbose_name_plural = _("keywords")
class Link(models.Model):
"""
contains all my interesting links
"""
FAVICON_DIR: str = "img/links/favicons"
# the actual link
url = models.URLField(unique=True, null=False, primary_key=True)
favicon = models.ImageField(blank=True, upload_to=FAVICON_DIR, null=True)
personal = models.BooleanField(default=False)
title_de = models.CharField(max_length=50, default="Nicht übersetzt")
title_en = models.CharField(max_length=50, default="Not translated")
desc_de = models.TextField(
blank=True, max_length=250, unique=False, default="Keine Beschreibung")
desc_en = models.TextField(
blank=True, max_length=250, unique=False, default="no description")
keywords = models.ManyToManyField(Keyword, blank=True)
public = models.BooleanField(default=False)
def __str__(self):
return f"{{<{self.__class__.__name__}>\"{self.title_en}\"}}"
def regenerate(self):
"""
regenerate a object
Implements the abstract method of Searchable
Searches for a favicon in the urr, if one is found, it will be stored in MEDIA_ROOT
TODO filepathings here suck and are too error prone
"""
logger.info(f"regenerating {self.__class__.__name__} object: {self}")
self.suburl = f"/links#{self.title_en}"
logger.info(f"getting favicon for link object {self}: '{self.url}'")
try:
icons = favicon.get(self.url, timeout=2)
except (ConnectionError) as ce:
# just keep whatever was stored if we cant get a new favicon
logger.warn(
f"unable to download favicon for {self}: {ce.with_traceback(None)}")
self.status = False
except Exception as e:
logger.warn(
f"Unexpected Exception while downloading {self}: {e.with_traceback(None)}")
self.status = False
else:
response = requests.get(icons[0].url, stream=True)
filename: str = f"favicon-{random.randint(0x1000, 0xffff)}.{icons[0].format}"
try:
with open(f"/tmp/{filename}", 'wb') as image:
for chunk in response.iter_content(1024):
image.write(chunk)
logger.debug(image)
with open(f"/tmp/{filename}", 'rb') as image:
self.favicon.save(filename, File(image))
logger.info(f"downloaded favicon for {self}")
self.status = True
except FileNotFoundError as fe:
logger.error(f"cant write favicon to file for {self}: {fe}")
self.favicon = None
except Exception as e:
logger.warn(
f"Unexpected Exception while downloading {self}: {e.with_traceback(None)}")
self.favicon = None
self.save()
class Meta:
verbose_name = _("Link")
verbose_name_plural = _("Links")