Select Git revision
services.py
services.py 3.46 KiB
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
def __init__(self, bearer_token, days_back=1):
if not bearer_token:
raise RuntimeError("Twitter bearer token not set, cannot update tweets")
self.client = Client(bearer_token=bearer_token)
self.days_back = days_back
@staticmethod
def get_latest_saved_tweet_id() -> list[int]:
"""
Vrací IDs už uložených Tweetů - možná by stálo za to brát jen z určitého
časového období...
"""
return Tweet.objects.values_list("twitter_id", flat=True)
def get_tweets_response(self, user_id) -> list["TweetResponse"]:
"""
Vrací list tweetů (objektů) pro daného Twitter uživatele.
"""
tweets_response = self.client.get_users_tweets(
user_id,
expansions=["author_id", "entities.mentions.username"],
max_results=100,
start_time=timezone.now() - timedelta(days=self.days_back),
tweet_fields=["author_id", "created_at"],
user_fields=["name", "username"],
) # 49022430
return tweets_response.data
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 daném uživateli.
"""
user_response = self.client.get_user(
username=username,
user_fields=["profile_image_url"], # id, name, username enabled by default
)
return user_response.data
def perform_update(self) -> int:
"""
Obaluje celý proces downloadu Tweetů z API do DB.
"""
user_data_list = self.get_user_list_data()
existing_tweet_id_list = self.get_latest_saved_tweet_id()
tweets_to_save = []
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,
)
)
return Tweet.objects.bulk_create(tweets_to_save)