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
Branches
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