sdbs-infra/sdbs_infra/dashboard/models.py

56 lines
1.8 KiB
Python

import urllib.request
from enum import Enum
from urllib.error import URLError
from urllib.request import Request
from bs4 import BeautifulSoup
from django.db import models
from django.utils.functional import cached_property
from ordered_model.models import OrderedModel
class ServiceStatus(Enum):
OK = 'ok'
DOWN = 'down'
UNKNOWN = 'unknown'
class Service(OrderedModel):
short_name = models.CharField(null=False, max_length=64)
image = models.ImageField(null=True, blank=True, upload_to='services')
description = models.TextField(null=True, blank=True)
url = models.URLField()
def __str__(self):
return f"{self.short_name} ({self.url})"
@cached_property
def index_request(self):
try:
request = Request(self.url, headers={'User-Agent': 'its just me humble status page'})
return urllib.request.urlopen(request)
except URLError:
return None
def get_status(self):
if self.index_request and self.index_request.getcode() == 200:
return ServiceStatus.OK
else:
return ServiceStatus.DOWN
@cached_property
def image_or_favicon(self):
if self.image:
return self.image.url
if self.index_request:
parsed_html = BeautifulSoup(self.index_request, features="html.parser")
link_tags = parsed_html.find_all('link')
for rel in ['apple-touch-icon', 'shortcut', 'icon']:
for link_tag in link_tags:
if rel in link_tag.attrs['rel']:
result = link_tag.attrs['href']
if self.url not in result:
return self.url + result if result.startswith("/") else f"/{result}"
else:
return result