From 468ed4b3f8d17bd06a6f564723ef8f52588ab495 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Valenta?= <git@imaniti.org>
Date: Tue, 4 Apr 2023 23:35:32 +0200
Subject: [PATCH] instagram sync base

---
 README.md                                     |  1 +
 instagram_utils/__init__.py                   |  0
 instagram_utils/apps.py                       |  5 ++
 instagram_utils/management/__init__.py        |  0
 .../management/commands/__init__.py           |  0
 .../management/commands/update_instagram.py   | 15 ++++++
 instagram_utils/models.py                     |  9 ++++
 instagram_utils/services.py                   | 50 +++++++++++++++++++
 ...inhomepage_instagram_usernames_and_more.py | 35 +++++++++++++
 main/models.py                                | 20 +++++++-
 majak/settings/base.py                        |  4 ++
 requirements/base.txt                         |  6 +--
 {twitter_utils => shared}/storages.py         |  4 +-
 ...uthor_img_url_tweet_author_img_and_more.py |  4 +-
 .../migrations/0003_alter_tweet_author_img.py |  4 +-
 twitter_utils/models.py                       |  2 +-
 16 files changed, 147 insertions(+), 12 deletions(-)
 create mode 100644 instagram_utils/__init__.py
 create mode 100644 instagram_utils/apps.py
 create mode 100644 instagram_utils/management/__init__.py
 create mode 100644 instagram_utils/management/commands/__init__.py
 create mode 100644 instagram_utils/management/commands/update_instagram.py
 create mode 100644 instagram_utils/models.py
 create mode 100644 instagram_utils/services.py
 create mode 100644 main/migrations/0046_mainhomepage_instagram_usernames_and_more.py
 rename {twitter_utils => shared}/storages.py (96%)

diff --git a/README.md b/README.md
index 0b4ba971..ff48c297 100644
--- a/README.md
+++ b/README.md
@@ -176,6 +176,7 @@ Přes CRON je třeba na pozadí spouštět Django `manage.py` commandy:
 * `update_main_timeline_articles` - aktualizuje články na `pirati.cz` z `https://piratipracuji.cz/api/`
 * `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`.
 
 ### Fulltextové vyhledávání v češtině
 
diff --git a/instagram_utils/__init__.py b/instagram_utils/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/instagram_utils/apps.py b/instagram_utils/apps.py
new file mode 100644
index 00000000..d054dc44
--- /dev/null
+++ b/instagram_utils/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class InstagramUtilsConfig(AppConfig):
+    name = "instagram_utils"
diff --git a/instagram_utils/management/__init__.py b/instagram_utils/management/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/instagram_utils/management/commands/__init__.py b/instagram_utils/management/commands/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/instagram_utils/management/commands/update_instagram.py b/instagram_utils/management/commands/update_instagram.py
new file mode 100644
index 00000000..11c2c130
--- /dev/null
+++ b/instagram_utils/management/commands/update_instagram.py
@@ -0,0 +1,15 @@
+from django.conf import settings
+from django.core.management.base import BaseCommand
+
+from ...services import InstagramDownloadService
+
+
+class Command(BaseCommand):
+    def handle(self, *args, **options):
+        service = InstagramDownloadService(
+            app_id=settings.INSTAGRAM_APP_ID,
+            app_secret=settings.INSTAGRAM_APP_SECRET,
+        )
+        service.perform_update()
+
+        self.stdout.write("\nInstagram post update finished.")
diff --git a/instagram_utils/models.py b/instagram_utils/models.py
new file mode 100644
index 00000000..47c408ae
--- /dev/null
+++ b/instagram_utils/models.py
@@ -0,0 +1,9 @@
+from django.db import models
+
+
+class InstagramPost(models.Model):
+    """
+    Model representing an Instgram post obtained from its API through the
+    update_instagram management command.
+    """
+
diff --git a/instagram_utils/services.py b/instagram_utils/services.py
new file mode 100644
index 00000000..6c4349e4
--- /dev/null
+++ b/instagram_utils/services.py
@@ -0,0 +1,50 @@
+import logging
+import requests
+
+from main.models import MainHomePage, MainPersonPage
+
+from .models import InstagramPost
+
+
+logger = logging.getLogger()
+
+
+class InstagramDownloadService:
+    """
+    TODO
+    """
+
+    def __init__(self, app_id: int, app_secret: str):
+        self.app_id = app_id
+        self.app_secret = app_secret
+
+        # https://www.instagram.com/web/search/topsearch/?context=user&count=1&query=that_snowden
+        # Useful Instagram username search API
+
+    def get_username_list(self) -> list[str]:
+        instagram_usernames_block = MainHomePage.objects.first().instagram_usernames
+
+        person_username_list = (
+            MainPersonPage.objects.filter(instagram_username__isnull=False)
+            .values_list("instagram_username", flat=True)
+            .distinct()
+        )
+        homepage_username_list = [
+            username_data["value"] for username_data in instagram_usernames_block.raw_data
+        ]
+
+        # kvůli duplicitám udělám(e) list/set/list konverzi
+        return list({*person_username_list, *homepage_username_list})
+
+    def convert_usernames_to_ids(self, username_list) -> list[str]:
+        user_ids = []
+
+        for username in username_list:
+            print(username)
+
+        return user_ids
+
+    def perform_update(self) -> None:
+        username_list = self.get_username_list()
+
+        user_ids = self.convert_usernames_to_ids(username_list)
diff --git a/main/migrations/0046_mainhomepage_instagram_usernames_and_more.py b/main/migrations/0046_mainhomepage_instagram_usernames_and_more.py
new file mode 100644
index 00000000..8345a6a7
--- /dev/null
+++ b/main/migrations/0046_mainhomepage_instagram_usernames_and_more.py
@@ -0,0 +1,35 @@
+# Generated by Django 4.1.7 on 2023-04-04 21:34
+
+from django.db import migrations, models
+import wagtail.blocks
+import wagtail.fields
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('main', '0045_alter_mainprogrampage_program'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='mainhomepage',
+            name='instagram_usernames',
+            field=wagtail.fields.StreamField([('username', wagtail.blocks.CharBlock(label='Instagram uživatelské jméno'))], blank=True, use_json_field=True, verbose_name='Uživatelská jména pro synchronizované Instagram účty'),
+        ),
+        migrations.AddField(
+            model_name='mainpersonpage',
+            name='instagram_username',
+            field=models.CharField(blank=True, help_text='Uživatelské jméno zadejte bez @ na začátku', max_length=32, null=True, verbose_name='Uživatelské jméno na Instagramu pro získání příspěvků'),
+        ),
+        migrations.AlterField(
+            model_name='mainhomepage',
+            name='twitter_usernames',
+            field=wagtail.fields.StreamField([('username', wagtail.blocks.CharBlock(label='Twitter uživatelské jméno'))], blank=True, use_json_field=True, verbose_name='Uživatelská jména pro synchronizované Twitter účty'),
+        ),
+        migrations.AlterField(
+            model_name='mainpersonpage',
+            name='twitter_username',
+            field=models.CharField(blank=True, help_text='Uživatelské jméno zadejte bez @ na začátku', max_length=32, null=True, verbose_name='Uživatelské jméno na Twitteru pro získání příspěvků'),
+        ),
+    ]
diff --git a/main/models.py b/main/models.py
index c5ab4ffc..7a330821 100644
--- a/main/models.py
+++ b/main/models.py
@@ -136,7 +136,15 @@ class MainHomePage(
 
     twitter_usernames = StreamField(
         [("username", CharBlock(label="Twitter uživatelské jméno"))],
-        verbose_name="Uživatelská jména pro synchronizované twitter účty",
+        verbose_name="Uživatelská jména pro synchronizované Twitter účty",
+        blank=True,
+        max_num=64,
+        use_json_field=True,
+    )
+
+    instagram_usernames = StreamField(
+        [("username", CharBlock(label="Instagram uživatelské jméno"))],
+        verbose_name="Uživatelská jména pro synchronizované Instagram účty",
         blank=True,
         max_num=64,
         use_json_field=True,
@@ -159,6 +167,7 @@ class MainHomePage(
         FieldPanel("social_links"),
         FieldPanel("matomo_id"),
         FieldPanel("twitter_usernames"),
+        FieldPanel("instagram_usernames"),
     ]
 
     ### EDIT HANDLERS
@@ -683,7 +692,14 @@ class MainPersonPage(ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin,
     text = RichTextField()
 
     twitter_username = models.CharField(
-        "Uživatelské jméno twitter pro získání příspěvků",
+        "Uživatelské jméno na Twitteru pro získání příspěvků",
+        blank=True,
+        null=True,
+        max_length=32,
+        help_text="Uživatelské jméno zadejte bez @ na začátku",
+    )
+    instagram_username = models.CharField(
+        "Uživatelské jméno na Instagramu pro získání příspěvků",
         blank=True,
         null=True,
         max_length=32,
diff --git a/majak/settings/base.py b/majak/settings/base.py
index 80b8a324..0dc9913f 100644
--- a/majak/settings/base.py
+++ b/majak/settings/base.py
@@ -48,6 +48,7 @@ INSTALLED_APPS = [
     "maps_utils",
     "redmine_utils",
     "twitter_utils",
+    "instagram_utils",
     "users",
     "pirates",
     "tuning",
@@ -311,3 +312,6 @@ MAPS_UTILS_MAPPROXY_URL = env.str(
 )
 
 TWITTER_BEARER_TOKEN = env.str("TWITTER_BEARER_TOKEN", default="")
+
+INSTAGRAM_APP_ID = env.str("INSTAGRAM_APP_ID", default="")
+INSTAGRAM_APP_SECRET = env.str("INSTAGRAM_APP_SECRET", default="")
diff --git a/requirements/base.txt b/requirements/base.txt
index acf77e06..55415830 100644
--- a/requirements/base.txt
+++ b/requirements/base.txt
@@ -1,6 +1,6 @@
 #
-# This file is autogenerated by pip-compile with python 3.10
-# To update, run:
+# This file is autogenerated by pip-compile with Python 3.10
+# by the following command:
 #
 #    pip-compile base.in
 #
@@ -8,8 +8,6 @@ amqp==5.1.1
     # via kombu
 anyascii==0.3.1
     # via wagtail
-appnope==0.1.3
-    # via ipython
 arrow==1.2.3
     # via
     #   -r base.in
diff --git a/twitter_utils/storages.py b/shared/storages.py
similarity index 96%
rename from twitter_utils/storages.py
rename to shared/storages.py
index 04ffc57c..8c73ea2f 100644
--- a/twitter_utils/storages.py
+++ b/shared/storages.py
@@ -13,7 +13,9 @@ class OverwriteStorage(get_storage_class()):
 
         Found at https://djangosnippets.org/snippets/976/
         """
+
         # If the filename already exists, remove it as if it was a true file system
         if self.exists(name):
             os.remove(os.path.join(settings.MEDIA_ROOT, name))
-        return name
+
+        return name 
diff --git a/twitter_utils/migrations/0002_remove_tweet_author_img_url_tweet_author_img_and_more.py b/twitter_utils/migrations/0002_remove_tweet_author_img_url_tweet_author_img_and_more.py
index bab86107..4fb0167f 100644
--- a/twitter_utils/migrations/0002_remove_tweet_author_img_url_tweet_author_img_and_more.py
+++ b/twitter_utils/migrations/0002_remove_tweet_author_img_url_tweet_author_img_and_more.py
@@ -2,7 +2,7 @@
 
 from django.db import migrations, models
 
-import twitter_utils.storages
+import shared.storages
 
 
 class Migration(migrations.Migration):
@@ -20,7 +20,7 @@ class Migration(migrations.Migration):
             name="author_img",
             field=models.ImageField(
                 null=True,
-                storage=twitter_utils.storages.OverwriteStorage,
+                storage=shared.storages.OverwriteStorage,
                 upload_to="twitter_accounts",
             ),
         ),
diff --git a/twitter_utils/migrations/0003_alter_tweet_author_img.py b/twitter_utils/migrations/0003_alter_tweet_author_img.py
index bd08e389..2a71f9a0 100644
--- a/twitter_utils/migrations/0003_alter_tweet_author_img.py
+++ b/twitter_utils/migrations/0003_alter_tweet_author_img.py
@@ -2,7 +2,7 @@
 
 from django.db import migrations, models
 
-import twitter_utils.storages
+import shared.storages
 
 
 class Migration(migrations.Migration):
@@ -15,7 +15,7 @@ class Migration(migrations.Migration):
             model_name="tweet",
             name="author_img",
             field=models.ImageField(
-                storage=twitter_utils.storages.OverwriteStorage,
+                storage=shared.storages.OverwriteStorage,
                 upload_to="twitter_accounts",
             ),
         ),
diff --git a/twitter_utils/models.py b/twitter_utils/models.py
index b15e9eb8..d32203e3 100644
--- a/twitter_utils/models.py
+++ b/twitter_utils/models.py
@@ -1,6 +1,6 @@
 from django.db import models
 
-from twitter_utils.storages import OverwriteStorage
+from shared.storages import OverwriteStorage
 
 
 class TweetQueryset(models.QuerySet):
-- 
GitLab