Skip to content
Snippets Groups Projects
Verified Commit cfb76c72 authored by jindra12's avatar jindra12
Browse files

Create BE support for mastodon updatable feed

parent 8a0527e5
Branches
No related tags found
1 merge request!759Create mastodon block for senate, uniweb and district
......@@ -174,6 +174,7 @@ Přes CRON je třeba na pozadí spouštět Django `manage.py` commandy:
* `publish_scheduled_pages` - publikuje naplánované stránky (každou hodinu)
* `update_callendars` - stáhne a aktualizuje kalendáře (několikrát denně)
* `update_main_timeline_articles` - aktualizuje články na `pirati.cz` z `https://piratipracuji.cz/api/`
* `update_mastodon_feed` - aktualizuje tooty podle nastavení na různých aplikacích
* `update_redmine_issues` - aktualizuje programované body MS a KS stránek napojených na Redmine (několikrát denně)
* `update_tweets` - aktualizuje tweety podle nastavení na Homepage pirati.cz - vyžaduje mít v .env TWITTER_BEARER_TOKEN, parametr --days určuje stáří tweetů (default 1)
* `update_instagram` - aktualizuje Instagramové posty na Homepage pirati.cz - vyžaduje mít v .env `INSTAGRAM_APP_ID` a `INSTAGRAM_APP_SECRET`.
......
from django.core.management.base import BaseCommand
from shared.services import MastodonFeedDownloadService
class Command(BaseCommand):
def handle(self, *args, **options):
ads = MastodonFeedDownloadService()
ads.perform_update()
self.stdout.write("\nUpdate of mastodon finished!")
import hashlib
import logging
from time import time
from attr import dataclass
from django.core.files.temp import NamedTemporaryFile
......@@ -15,15 +15,12 @@ from wagtail.models import Page
from shared.blocks import (
DEFAULT_CONTENT_BLOCKS,
FooterLinksBlock,
ImageCreatorMixin,
MenuItemBlock,
MenuParentBlock,
)
logger = logging.getLogger(__name__)
FIVE_MINUTES_IN_SECONDS = 300
@dataclass
class MastodonImage:
......@@ -66,12 +63,26 @@ class MastodonUser:
preferredUsername: str
class Mastodon(ImageCreatorMixin, models.Model):
class MastodonImageMixin(models.Model):
image = models.ImageField(null=True, blank=True, upload_to="mastodon/")
def download_image(self, url, name):
response = request("GET", url, stream=True)
response.raw.decode_content = True
# Taken from: https://gist.github.com/anderser/2172888
temporary_stored_image = NamedTemporaryFile(delete=True)
temporary_stored_image.write(response.content)
temporary_stored_image.flush()
self.image.save(name, temporary_stored_image)
class Meta:
abstract = True
class Mastodon(MastodonImageMixin, models.Model):
url = models.URLField()
toots = models.JSONField(encoder=DjangoJSONEncoder, null=True)
summary = models.TextField(null=True, blank=True)
user_image = models.ImageField(null=True, blank=True, upload_to="mastodon_users/")
timestamp = models.FloatField()
def download_toots(self):
"""
......@@ -89,31 +100,41 @@ class Mastodon(ImageCreatorMixin, models.Model):
full_url = self.url + ".json"
return request("GET", full_url).json()
def parse_url(self, now: float):
def parse_url(self):
toots: MastodonToots = self.download_toots()
user: MastodonUser = self.download_user()
# Taken from: https://gist.github.com/anderser/2172888
temporary_stored_image = NamedTemporaryFile(delete=True)
temporary_stored_image.write(user.icon.url)
temporary_stored_image.flush()
self.user_image.save(f"{user.preferredUsername}.jpg", temporary_stored_image)
self.download_image(f"{user.preferredUsername}.jpg", user["icon"]["url"])
for toot in toots["orderedItems"]:
if toot["attachment"] != None:
for attachment in toot["attachment"]:
mastodon_attachment: MastodonAttachment = (
MastodonAttachment.objects.create(mastodon=self)
)
mastodon_attachment.download_image(
attachment["url"],
hashlib.md5(attachment["url"].encode("ascii")).hexdigest(),
)
attachment["url"] = mastodon_attachment.image.url
self.toots = toots.orderedItems
self.summary = user.summary
self.timestamp = now
def refresh_toots(self):
now = time()
if self.timestamp != None and now - self.timestamp < FIVE_MINUTES_IN_SECONDS:
return
try:
self.parse_url(now)
self.parse_url()
self.save()
except:
logger.error("Mastodon refresh failed for %s", self.url, exc_info=True)
class MastodonAttachment(MastodonImageMixin, models.Model):
mastodon = models.ForeignKey(
Mastodon, null=True, blank=True, on_delete=models.PROTECT
)
class MastodonFeedMixin(models.Model):
mastodon_feed = models.URLField(
verbose_name="Mastodon feed",
......@@ -132,7 +153,7 @@ class MastodonFeedMixin(models.Model):
if self.mastodon is not None
else Mastodon.objects.create(url=self.calendar_url)
)
mastodon.parse_url(time())
mastodon.parse_url()
except:
raise ValidationError("Update mastodonu se nepovedl")
......
import logging
from typing import TYPE_CHECKING
from shared.models import Mastodon
if TYPE_CHECKING:
pass
logger = logging.getLogger()
class MastodonFeedDownloadService:
def perform_update(self):
for mastodon in Mastodon.objects.all():
mastodon.refresh_toots()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment