diff --git a/bazarr/app/database.py b/bazarr/app/database.py index b931c5f0f..09297ac96 100644 --- a/bazarr/app/database.py +++ b/bazarr/app/database.py @@ -136,6 +136,7 @@ class TableEpisodes(Base): audio_codec = mapped_column(Text) audio_language = mapped_column(Text) + created_at_timestamp = mapped_column(DateTime) episode = mapped_column(Integer, nullable=False) episode_file_id = mapped_column(Integer) failedAttempts = mapped_column(Text) @@ -152,6 +153,7 @@ class TableEpisodes(Base): sonarrSeriesId = mapped_column(Integer, ForeignKey('table_shows.sonarrSeriesId', ondelete='CASCADE')) subtitles = mapped_column(Text) title = mapped_column(Text, nullable=False) + updated_at_timestamp = mapped_column(DateTime) video_codec = mapped_column(Text) @@ -213,6 +215,7 @@ class TableMovies(Base): alternativeTitles = mapped_column(Text) audio_codec = mapped_column(Text) audio_language = mapped_column(Text) + created_at_timestamp = mapped_column(DateTime) failedAttempts = mapped_column(Text) fanart = mapped_column(Text) ffprobe_cache = mapped_column(LargeBinary) @@ -234,6 +237,7 @@ class TableMovies(Base): tags = mapped_column(Text) title = mapped_column(Text, nullable=False) tmdbId = mapped_column(Text, nullable=False, unique=True) + updated_at_timestamp = mapped_column(DateTime) video_codec = mapped_column(Text) year = mapped_column(Text) @@ -271,6 +275,7 @@ class TableShows(Base): tvdbId = mapped_column(Integer) alternativeTitles = mapped_column(Text) audio_language = mapped_column(Text) + created_at_timestamp = mapped_column(DateTime) fanart = mapped_column(Text) imdbId = mapped_column(Text) monitored = mapped_column(Text) @@ -283,6 +288,7 @@ class TableShows(Base): sortTitle = mapped_column(Text) tags = mapped_column(Text) title = mapped_column(Text, nullable=False) + updated_at_timestamp = mapped_column(DateTime) year = mapped_column(Text) diff --git a/bazarr/radarr/sync/movies.py b/bazarr/radarr/sync/movies.py index a5ecf0416..4114ba2c9 100644 --- a/bazarr/radarr/sync/movies.py +++ b/bazarr/radarr/sync/movies.py @@ -5,6 +5,7 @@ from constants import MINIMUM_VIDEO_SIZE from sqlalchemy.exc import IntegrityError +from datetime import datetime from app.config import settings from utilities.path_mappings import path_mappings @@ -49,6 +50,7 @@ def get_movie_file_size_from_db(movie_path): # Update movies in DB def update_movie(updated_movie, send_event): try: + updated_movie['updated_at_timestamp'] = datetime.now() database.execute( update(TableMovies).values(updated_movie) .where(TableMovies.tmdbId == updated_movie['tmdbId'])) @@ -75,6 +77,7 @@ def get_movie_monitored_status(movie_id): # Insert new movies in DB def add_movie(added_movie, send_event): try: + added_movie['created_at_timestamp'] = datetime.now() database.execute( insert(TableMovies) .values(added_movie)) @@ -296,6 +299,7 @@ def update_one_movie(movie_id, action, defer_search=False): # Update existing movie in DB elif movie and existing_movie: try: + movie['updated_at_timestamp'] = datetime.now() database.execute( update(TableMovies) .values(movie) @@ -312,6 +316,7 @@ def update_one_movie(movie_id, action, defer_search=False): # Insert new movie in DB elif movie and not existing_movie: try: + movie['created_at_timestamp'] = datetime.now() database.execute( insert(TableMovies) .values(movie)) diff --git a/bazarr/sonarr/sync/episodes.py b/bazarr/sonarr/sync/episodes.py index b6979ad30..e2623ce71 100644 --- a/bazarr/sonarr/sync/episodes.py +++ b/bazarr/sonarr/sync/episodes.py @@ -5,6 +5,7 @@ from constants import MINIMUM_VIDEO_SIZE from sqlalchemy.exc import IntegrityError +from datetime import datetime from app.database import database, TableShows, TableEpisodes, delete, update, insert, select from app.config import settings @@ -149,9 +150,11 @@ def sync_episodes(series_id, send_event=True): if len(episodes_to_add): for added_episode in episodes_to_add: try: + added_episode['created_at_timestamp'] = datetime.now() database.execute(insert(TableEpisodes).values(added_episode)) except IntegrityError as e: logging.error(f"BAZARR cannot insert episodes because of {e}. We'll try to update it instead.") + del added_episode['created_at_timestamp'] episodes_to_update.append(added_episode) else: store_subtitles(added_episode['path'], path_mappings.path_replace(added_episode['path'])) @@ -163,6 +166,7 @@ def sync_episodes(series_id, send_event=True): if len(episodes_to_update): for updated_episode in episodes_to_update: try: + updated_episode['updated_at_timestamp'] = datetime.now() database.execute(update(TableEpisodes) .values(updated_episode) .where(TableEpisodes.sonarrEpisodeId == updated_episode['sonarrEpisodeId'])) @@ -226,6 +230,7 @@ def sync_one_episode(episode_id, defer_search=False): # Update existing episodes in DB elif episode and existing_episode: try: + episode['updated_at_timestamp'] = datetime.now() database.execute( update(TableEpisodes) .values(episode) @@ -241,6 +246,7 @@ def sync_one_episode(episode_id, defer_search=False): # Insert new episodes in DB elif episode and not existing_episode: try: + episode['created_at_timestamp'] = datetime.now() database.execute( insert(TableEpisodes) .values(episode)) diff --git a/bazarr/sonarr/sync/series.py b/bazarr/sonarr/sync/series.py index f8bd84990..e6eec6c22 100644 --- a/bazarr/sonarr/sync/series.py +++ b/bazarr/sonarr/sync/series.py @@ -3,6 +3,7 @@ import logging from sqlalchemy.exc import IntegrityError +from datetime import datetime from app.config import settings from subtitles.indexer.series import list_missing_subtitles @@ -127,6 +128,7 @@ def update_series(send_event=True): .first(): try: trace(f"Updating {show['title']}") + updated_series['updated_at_timestamp'] = datetime.now() database.execute( update(TableShows) .values(updated_series) @@ -145,6 +147,7 @@ def update_series(send_event=True): try: trace(f"Inserting {show['title']}") + added_series['created_at_timestamp'] = datetime.now() database.execute( insert(TableShows) .values(added_series)) @@ -238,6 +241,7 @@ def update_one_series(series_id, action): # Update existing series in DB if action == 'updated' and existing_series: try: + series['updated_at_timestamp'] = datetime.now() database.execute( update(TableShows) .values(series) @@ -252,6 +256,7 @@ def update_one_series(series_id, action): # Insert new series in DB elif action == 'updated' and not existing_series: try: + series['created_at_timestamp'] = datetime.now() database.execute( insert(TableShows) .values(series)) diff --git a/migrations/versions/8baf97427327_.py b/migrations/versions/8baf97427327_.py new file mode 100644 index 000000000..bb6c7274a --- /dev/null +++ b/migrations/versions/8baf97427327_.py @@ -0,0 +1,34 @@ +"""empty message + +Revision ID: 8baf97427327 +Revises: 1e38aa77a491 +Create Date: 2024-10-18 12:57:13.831596 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '8baf97427327' +down_revision = '1e38aa77a491' +branch_labels = None +depends_on = None + + +def upgrade(): + with op.batch_alter_table('table_episodes', schema=None) as batch_op: + batch_op.add_column(sa.Column('created_at_timestamp', sa.DateTime(), nullable=True)) + batch_op.add_column(sa.Column('updated_at_timestamp', sa.DateTime(), nullable=True)) + + with op.batch_alter_table('table_movies', schema=None) as batch_op: + batch_op.add_column(sa.Column('created_at_timestamp', sa.DateTime(), nullable=True)) + batch_op.add_column(sa.Column('updated_at_timestamp', sa.DateTime(), nullable=True)) + + with op.batch_alter_table('table_shows', schema=None) as batch_op: + batch_op.add_column(sa.Column('created_at_timestamp', sa.DateTime(), nullable=True)) + batch_op.add_column(sa.Column('updated_at_timestamp', sa.DateTime(), nullable=True)) + + +def downgrade(): + pass