Skip to content
Snippets Groups Projects
Commit 33588d91 authored by Tomáš Valenta's avatar Tomáš Valenta
Browse files

finish instagram post model sync

parent 5eae29a5
No related branches found
No related tags found
3 merge requests!787Release,!743Add Redmine datasets to charts, Instagram feed to homepage,!742Add Instagram feed to homepage
Pipeline #12225 passed
# Generated by Django 4.1.6 on 2023-04-05 17:16
from django.db import migrations, models
import instagram_utils.models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='InstagramPost',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('author_name', models.CharField(max_length=64, verbose_name='Jméno autora')),
('author_username', models.CharField(max_length=64, verbose_name='Username autora')),
('timestamp', models.DateTimeField(default=instagram_utils.models.get_current_datetime, verbose_name='Datum a čas vytvoření')),
('caption', models.TextField(blank=True, null=True, verbose_name='Popis')),
('image', models.ImageField(upload_to='instagram', verbose_name='Obrázek')),
('url', models.URLField(blank=True, null=True, verbose_name='Odkaz')),
],
options={
'ordering': ('timestamp',),
},
),
]
# Generated by Django 4.1.6 on 2023-04-05 17:18
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('instagram_utils', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='instagrampost',
name='remote_id',
field=models.CharField(default='', max_length=64, verbose_name='ID Postu'),
preserve_default=False,
),
]
# Generated by Django 4.1.6 on 2023-04-05 17:19
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('instagram_utils', '0002_instagrampost_remote_id'),
]
operations = [
migrations.AlterField(
model_name='instagrampost',
name='remote_id',
field=models.CharField(max_length=64, unique=True, verbose_name='ID Postu'),
),
]
import datetime
from django.db import models
def get_current_datetime() -> datetime.datetime:
return datetime.datetime.now(tz=datetime.timezone.utc)
class InstagramPost(models.Model):
"""
Model representing an Instgram post obtained from its API through the
update_instagram management command.
"""
remote_id = models.CharField(
verbose_name="ID Postu",
max_length=64,
unique=True,
)
timestamp = models.DateTimeField(
verbose_name="Datum a čas vytvoření",
default=get_current_datetime
)
author_name = models.CharField(
verbose_name="Jméno autora",
max_length=64,
)
author_username = models.CharField(
verbose_name="Username autora",
max_length=64,
)
caption = models.TextField(
verbose_name="Popis",
blank=True,
null=True,
)
image = models.ImageField(
verbose_name="Obrázek",
upload_to="instagram",
)
url = models.URLField(
verbose_name="Odkaz",
blank=True,
null=True,
)
def __str__(self) -> str:
return f"@{self.author_username} - {self.caption}"
class Meta:
ordering = ("timestamp",)
import datetime
import logging
import io
import os
import requests_cache
from django.core.files import File
from main.models import MainHomePage, MainPersonPage
from .models import InstagramPost
......@@ -28,37 +32,101 @@ class InstagramDownloadService:
return [
(
block["value"]["name"],
block["value"]["user_id"],
block["value"]["access_token"]
)
for block in access_block.raw_data
]
def parse_media_for_user(self, name, user_id, access_token):
def download_remote_image(self, image_url) -> (str, File):
try:
response = self.session.get(image_url)
response.raise_for_status()
except Exception as exc:
logger.warning(
"Error getting Instagram image at %s: %s",
image_url, exc
)
return "", None
return os.path.basename(image_url), File(io.BytesIO(response.content))
def get_user_data(self, access_token: str) -> dict:
user_data = self.session.get(
f"https://graph.instagram.com/v16.0/me?access_token={access_token}"
"&fields=id,username"
)
user_data.raise_for_status()
return user_data.json()
def get_recent_media(self, user_data: dict, access_token: str) -> list[dict]:
with self.session.cache_disabled():
recent_media = self.session.get(
f"https://graph.instagram.com/v16.0/{user_id}/media?access_token="
f"{access_token}&fields=caption,media_type,permalink,media_url,"
"thumbnail_url"
f"https://graph.instagram.com/v16.0/{user_data['id']}/media?access_token="
f"{access_token}&fields=id,timestamp,caption,media_type,permalink,"
"media_url,thumbnail_url"
)
if not recent_media.ok:
logger.warning(
"Error getting media for user %s: %s",
user_id,
user_data["id"],
recent_media.status_code
)
return []
logger.debug("Parsing Instagram feed: %s", recent_media)
return recent_media.json()["data"]
def parse_media_for_user(self, name: str, access_token: str) -> None:
user_data = self.get_user_data(access_token)
recent_media_json = self.get_recent_media(user_data, access_token)
if len(recent_media_json) == 0:
return
recent_media = recent_media.json()
posts = []
for media_data in recent_media_json:
# Don't recreate existing posts'
if InstagramPost.objects.filter(remote_id=media_data["id"]).exists():
logging.info(
"Skipping Instagram post ID %s, already exists",
media_data["id"]
)
continue
post = InstagramPost(
remote_id=media_data["id"],
author_name=name,
author_username=user_data["username"],
timestamp=datetime.datetime.strptime(
media_data["timestamp"],
"%Y-%m-%dT%H:%M:%S%z",
),
caption=media_data["caption"],
url=media_data["permalink"],
)
print(recent_media)
post.image.save(
*self.download_remote_image(media_data["media_url"]),
False, # Don't save yet
)
post.save()
logger.info(
"Saved Instagram post ID %s",
post.remote_id,
)
def perform_update(self) -> None:
user_info_list = self.get_user_info_list()
media = []
media_list = []
for user_info in user_info_list:
media.append(self.parse_media_for_user(*user_info))
self.parse_media_for_user(*user_info)
......@@ -374,7 +374,6 @@ class CardLinkWithHeadlineBlock(CardLinkWithHeadlineBlockMixin):
class InstagramAccessBlock(StructBlock):
name = CharBlock(label="Zobrazované jméno")
user_id = CharBlock(label="Uživatelské ID")
access_token = CharBlock(label="Přístupový token")
class Meta:
......
# Generated by Django 4.1.6 on 2023-04-05 16:45
from django.db import migrations
import wagtail.blocks
import wagtail.fields
class Migration(migrations.Migration):
dependencies = [
('main', '0049_alter_mainhomepage_instagram_access'),
]
operations = [
migrations.AlterField(
model_name='mainhomepage',
name='instagram_access',
field=wagtail.fields.StreamField([('instagram_access', wagtail.blocks.StructBlock([('name', wagtail.blocks.CharBlock(label='Zobrazované jméno')), ('access_token', wagtail.blocks.CharBlock(label='Přístupový token'))]))], blank=True, use_json_field=True, verbose_name='Uživatelská jména a přístupové tokeny pro synchronizované Instagram účty'),
),
]
File deleted
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment