diff --git a/main/migrations/0003_mainhomepage_twitter_usernames_and_more.py b/main/migrations/0003_mainhomepage_twitter_usernames_and_more.py new file mode 100644 index 0000000000000000000000000000000000000000..acc5d0026ea4d3e7608ecbf7d713aaddd5c0bb7e --- /dev/null +++ b/main/migrations/0003_mainhomepage_twitter_usernames_and_more.py @@ -0,0 +1,60 @@ +# Generated by Django 4.0.7 on 2022-08-19 10:56 + +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("main", "0002_mainarticlepage_remove_mainhomepage_footer_and_more"), + ] + + operations = [ + migrations.AddField( + model_name="mainhomepage", + name="twitter_usernames", + field=wagtail.fields.StreamField( + [("username", wagtail.blocks.CharBlock())], + blank=True, + use_json_field=None, + verbose_name="Uživatelská jména pro synchronizované twitter účty", + ), + ), + migrations.AlterField( + model_name="mainprogrampage", + name="program", + field=wagtail.fields.StreamField( + [ + ( + "program_group", + wagtail.blocks.StructBlock( + [ + ("title", wagtail.blocks.CharBlock()), + ( + "point_list", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "icon", + wagtail.images.blocks.ImageChooserBlock(), + ), + ("title", wagtail.blocks.CharBlock()), + ("text", wagtail.blocks.TextBlock()), + ] + ) + ), + ), + ] + ), + ) + ], + blank=True, + use_json_field=None, + verbose_name="Program", + ), + ), + ] diff --git a/main/models.py b/main/models.py index 3783213616ff1b3dd2642c90844f6104b0733731..a159f2eef9e207db6d740be5b9f68fcf975d527f 100644 --- a/main/models.py +++ b/main/models.py @@ -6,7 +6,7 @@ from modelcluster.fields import ParentalKey from taggit.models import TaggedItemBase from wagtail.admin.edit_handlers import FieldPanel, ObjectList, TabbedInterface from wagtail.contrib.routable_page.models import RoutablePageMixin, route -from wagtail.core.blocks import PageChooserBlock +from wagtail.core.blocks import CharBlock, PageChooserBlock from wagtail.core.fields import RichTextField, StreamField from wagtail.core.models import Page from wagtailmetadata.models import MetadataPageMixin @@ -82,9 +82,26 @@ class MainHomePage(MenuMixin, ExtendedMetadataHomePageMixin, MetadataPageMixin, max_num=6, ) - content_panels = Page.content_panels + [] + twitter_usernames = StreamField( + [("username", CharBlock())], + verbose_name="Uživatelská jména pro synchronizované twitter účty", + blank=True, + max_num=6, + ) - settings_panels = [FieldPanel("matomo_id")] + content_panels = Page.content_panels + [ + FieldPanel("content"), + FieldPanel("footer_social_links"), + FieldPanel("footer_other_links"), + FieldPanel("footer_person_list"), + ] + + settings_panels = [ + FieldPanel("contact_newcomers"), + FieldPanel("donation_page"), + FieldPanel("matomo_id"), + FieldPanel("twitter_usernames"), + ] ### EDIT HANDLERS diff --git a/twitter_utils/management/commands/update_tweets.py b/twitter_utils/management/commands/update_tweets.py index cdefb21b8da1be97b05bffeba194d52f76378f40..65d7be28cf4404512ed8787dbaad4ce919b5ca92 100644 --- a/twitter_utils/management/commands/update_tweets.py +++ b/twitter_utils/management/commands/update_tweets.py @@ -21,4 +21,4 @@ class Command(BaseCommand): ) tds.perform_update() - self.stdout.write("\nUpdating tweets finished!") + self.stdout.write("\nUpdate of tweets finished!") diff --git a/twitter_utils/services.py b/twitter_utils/services.py index 61cf6b72357944e4586a252a68a080f92f0e7c68..adf44b29aec691fa0719417bce31e76c8479633b 100644 --- a/twitter_utils/services.py +++ b/twitter_utils/services.py @@ -1,12 +1,29 @@ +import logging from datetime import timedelta +from typing import TYPE_CHECKING from django.utils import timezone from tweepy import Client +from tweepy.errors import BadRequest + +from main.models import MainHomePage from .models import Tweet +if TYPE_CHECKING: + from tweepy import Tweet as TweetResponse + from tweepy import User + + +logger = logging.getLogger() + class TweetDownloadService: + """ + Service class starající se o update tweetů z Twitter API, v současné chvíli + bere tweety z účtu nastavených v (první) MainHomePage stránce (HP pirati.cz). + """ + client: Client days_back: int @@ -25,7 +42,7 @@ class TweetDownloadService: """ return Tweet.objects.values_list("twitter_id", flat=True) - def get_tweets_response(self, user_id) -> list: + def get_tweets_response(self, user_id) -> list["TweetResponse"]: """ Vrací list tweetů (objektů) pro daného Twitter uživatele. """ @@ -40,13 +57,27 @@ class TweetDownloadService: return tweets_response.data - def get_user_response(self) -> dict: + def get_user_list_data(self) -> list["User"]: + twitter_usernames_block = MainHomePage.objects.first().twitter_usernames + user_data_list = [] + + for username_data in twitter_usernames_block.raw_data: + try: + user_data_list.append(self.get_user_response(username_data["value"])) + except BadRequest: + logger.error( + "Cannot download tweets for the username", + extra={"username": username_data["value"]}, + ) + + return user_data_list + + def get_user_response(self, username) -> "User": """ - Vrací informace o uživateli "PiratskaStrana" - Tento call není až tak potřeba, pokud bychom zahardcodili ID 49022430 + Vrací informace o daném uživateli. """ user_response = self.client.get_user( - username="PiratskaStrana", + username=username, user_fields=["profile_image_url"], # id, name, username enabled by default ) @@ -56,22 +87,22 @@ class TweetDownloadService: """ Obaluje celý proces downloadu Tweetů z API do DB. """ - user_data_dict = self.get_user_response() - downloaded_tweets_list = self.get_tweets_response(user_id=user_data_dict["id"]) + user_data_list = self.get_user_list_data() existing_tweet_id_list = self.get_latest_saved_tweet_id() tweets_to_save = [] - for tweet in downloaded_tweets_list: - if str(tweet.id) not in existing_tweet_id_list: - tweets_to_save.append( - Tweet( - author_img_url=user_data_dict["profile_image_url"], - author_name=user_data_dict["name"], - author_username=user_data_dict["username"], - text=tweet.text, - twitter_id=tweet.id, + for user_data in user_data_list: + for tweet in self.get_tweets_response(user_id=user_data.id): + if str(tweet.id) not in existing_tweet_id_list: + tweets_to_save.append( + Tweet( + author_img_url=user_data.profile_image_url, + author_name=user_data.name, + author_username=user_data.username, + text=tweet.text, + twitter_id=tweet.id, + ) ) - ) # zatím nechávám author fieldy jako default @PiratskaStrana return Tweet.objects.bulk_create(tweets_to_save)