Added series status and last air date

This commit is contained in:
morpheus65535 2024-12-17 21:14:01 -05:00 committed by GitHub
parent f81780fac5
commit c8e2894b2b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 103 additions and 28 deletions

View file

@ -34,9 +34,11 @@ class Series(Resource):
'alternativeTitles': fields.List(fields.String), 'alternativeTitles': fields.List(fields.String),
'audio_language': fields.Nested(get_audio_language_model), 'audio_language': fields.Nested(get_audio_language_model),
'episodeFileCount': fields.Integer(default=0), 'episodeFileCount': fields.Integer(default=0),
'ended': fields.Boolean(),
'episodeMissingCount': fields.Integer(default=0), 'episodeMissingCount': fields.Integer(default=0),
'fanart': fields.String(), 'fanart': fields.String(),
'imdbId': fields.String(), 'imdbId': fields.String(),
'lastAired': fields.String(),
'monitored': fields.Boolean(), 'monitored': fields.Boolean(),
'overview': fields.String(), 'overview': fields.String(),
'path': fields.String(), 'path': fields.String(),
@ -100,6 +102,8 @@ class Series(Resource):
TableShows.tags, TableShows.tags,
TableShows.title, TableShows.title,
TableShows.year, TableShows.year,
TableShows.ended,
TableShows.lastAired,
episodeFileCount.c.episodeFileCount, episodeFileCount.c.episodeFileCount,
episodeMissingCount.c.episodeMissingCount) \ episodeMissingCount.c.episodeMissingCount) \
.select_from(TableShows) \ .select_from(TableShows) \
@ -128,6 +132,8 @@ class Series(Resource):
'tags': x.tags, 'tags': x.tags,
'title': x.title, 'title': x.title,
'year': x.year, 'year': x.year,
'ended': x.ended,
'lastAired': x.lastAired,
'episodeFileCount': x.episodeFileCount, 'episodeFileCount': x.episodeFileCount,
'episodeMissingCount': x.episodeMissingCount, 'episodeMissingCount': x.episodeMissingCount,
}) for x in database.execute(stmt).all()] }) for x in database.execute(stmt).all()]

View file

@ -276,8 +276,10 @@ class TableShows(Base):
alternativeTitles = mapped_column(Text) alternativeTitles = mapped_column(Text)
audio_language = mapped_column(Text) audio_language = mapped_column(Text)
created_at_timestamp = mapped_column(DateTime) created_at_timestamp = mapped_column(DateTime)
ended = mapped_column(Text)
fanart = mapped_column(Text) fanart = mapped_column(Text)
imdbId = mapped_column(Text) imdbId = mapped_column(Text)
lastAired = mapped_column(Text)
monitored = mapped_column(Text) monitored = mapped_column(Text)
overview = mapped_column(Text) overview = mapped_column(Text)
path = mapped_column(Text, nullable=False, unique=True) path = mapped_column(Text, nullable=False, unique=True)

View file

@ -2,6 +2,8 @@
import os import os
from dateutil import parser
from app.config import settings from app.config import settings
from app.database import TableShows, database, select from app.database import TableShows, database, select
from constants import MINIMUM_VIDEO_SIZE from constants import MINIMUM_VIDEO_SIZE
@ -45,6 +47,10 @@ def seriesParser(show, action, tags_dict, language_profiles, serie_default_profi
imdbId = show['imdbId'] if 'imdbId' in show else None imdbId = show['imdbId'] if 'imdbId' in show else None
ended = 'True' if 'ended' in show and show['ended'] else 'False'
lastAired = parser.parse(show['lastAired']).strftime("%Y-%m-%d") if 'lastAired' in show and show['lastAired'] else None
audio_language = [] audio_language = []
if not settings.general.parse_embedded_audio_track: if not settings.general.parse_embedded_audio_track:
if get_sonarr_info.is_legacy(): if get_sonarr_info.is_legacy():
@ -56,22 +62,24 @@ def seriesParser(show, action, tags_dict, language_profiles, serie_default_profi
audio_language = [] audio_language = []
parsed_series = { parsed_series = {
'title': show["title"], 'title': show["title"],
'path': show["path"], 'path': show["path"],
'tvdbId': int(show["tvdbId"]), 'tvdbId': int(show["tvdbId"]),
'sonarrSeriesId': int(show["id"]), 'sonarrSeriesId': int(show["id"]),
'overview': overview, 'overview': overview,
'poster': poster, 'poster': poster,
'fanart': fanart, 'fanart': fanart,
'audio_language': str(audio_language), 'audio_language': str(audio_language),
'sortTitle': show['sortTitle'], 'sortTitle': show['sortTitle'],
'year': str(show['year']), 'year': str(show['year']),
'alternativeTitles': str(alternate_titles), 'alternativeTitles': str(alternate_titles),
'tags': str(tags), 'tags': str(tags),
'seriesType': show['seriesType'], 'seriesType': show['seriesType'],
'imdbId': imdbId, 'imdbId': imdbId,
'monitored': str(bool(show['monitored'])) 'monitored': str(bool(show['monitored'])),
} 'ended': ended,
'lastAired': lastAired,
}
if action == 'insert': if action == 'insert':
parsed_series['profileId'] = serie_default_profile parsed_series['profileId'] = serie_default_profile

View file

@ -13,11 +13,14 @@ import { showNotification } from "@mantine/notifications";
import { import {
faAdjust, faAdjust,
faBriefcase, faBriefcase,
faCalendar,
faCircleChevronDown, faCircleChevronDown,
faCircleChevronRight, faCircleChevronRight,
faCloudUploadAlt, faCloudUploadAlt,
faHdd, faHdd,
faPlay,
faSearch, faSearch,
faStop,
faSync, faSync,
faTriangleExclamation, faTriangleExclamation,
faWrench, faWrench,
@ -67,6 +70,14 @@ const SeriesEpisodesView: FunctionComponent = () => {
icon: faTriangleExclamation, icon: faTriangleExclamation,
text: `${series?.episodeMissingCount} missing subtitles`, text: `${series?.episodeMissingCount} missing subtitles`,
}, },
{
icon: series?.ended ? faStop : faPlay,
text: series?.ended ? "Ended" : "Continuing",
},
{
icon: faCalendar,
text: `Last ${series?.ended ? "aired on" : "known airdate"}: ${series?.lastAired}`,
},
{ {
icon: faAdjust, icon: faAdjust,
text: series?.seriesType ?? "", text: series?.seriesType ?? "",

View file

@ -1,9 +1,14 @@
import { FunctionComponent, useMemo } from "react"; import { FunctionComponent, useMemo } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { Anchor, Container, Progress } from "@mantine/core"; import { Anchor, Container, Group, Progress } from "@mantine/core";
import { useDocumentTitle } from "@mantine/hooks"; import { useDocumentTitle } from "@mantine/hooks";
import { faBookmark as farBookmark } from "@fortawesome/free-regular-svg-icons"; import { faBookmark as farBookmark } from "@fortawesome/free-regular-svg-icons";
import { faBookmark, faWrench } from "@fortawesome/free-solid-svg-icons"; import {
faBookmark,
faPlay,
faStop,
faWrench,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { ColumnDef } from "@tanstack/react-table"; import { ColumnDef } from "@tanstack/react-table";
import { useSeriesModification, useSeriesPagination } from "@/apis/hooks"; import { useSeriesModification, useSeriesPagination } from "@/apis/hooks";
@ -23,16 +28,19 @@ const SeriesView: FunctionComponent = () => {
const columns = useMemo<ColumnDef<Item.Series>[]>( const columns = useMemo<ColumnDef<Item.Series>[]>(
() => [ () => [
{ {
id: "monitored", id: "status",
cell: ({ cell: ({ row: { original } }) => (
row: { <Group gap="xs" wrap="nowrap">
original: { monitored }, <FontAwesomeIcon
}, title={original.monitored ? "monitored" : "unmonitored"}
}) => ( icon={original.monitored ? faBookmark : farBookmark}
<FontAwesomeIcon ></FontAwesomeIcon>
title={monitored ? "monitored" : "unmonitored"}
icon={monitored ? faBookmark : farBookmark} <FontAwesomeIcon
></FontAwesomeIcon> title={original.ended ? "Ended" : "Continuing"}
icon={original.ended ? faStop : faPlay}
></FontAwesomeIcon>
</Group>
), ),
}, },
{ {

View file

@ -151,6 +151,8 @@ declare namespace Item {
SeriesIdType & { SeriesIdType & {
episodeFileCount: number; episodeFileCount: number;
episodeMissingCount: number; episodeMissingCount: number;
ended: boolean;
lastAired: string;
seriesType: SonarrSeriesType; seriesType: SonarrSeriesType;
tvdbId: number; tvdbId: number;
}; };

View file

@ -0,0 +1,38 @@
"""empty message
Revision ID: 4274a5dfc4ad
Revises: 8baf97427327
Create Date: 2024-12-15 21:19:19.406290
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '4274a5dfc4ad'
down_revision = '8baf97427327'
branch_labels = None
depends_on = None
bind = op.get_context().bind
insp = sa.inspect(bind)
def column_exists(table_name, column_name):
columns = insp.get_columns(table_name)
return any(c["name"] == column_name for c in columns)
def upgrade():
if not column_exists('table_shows', 'ended'):
with op.batch_alter_table('table_shows', schema=None) as batch_op:
batch_op.add_column(sa.Column('ended', sa.TEXT(), nullable=True))
if not column_exists('table_shows', 'lastAired'):
with op.batch_alter_table('table_shows', schema=None) as batch_op:
batch_op.add_column(sa.Column('lastAired', sa.TEXT(), nullable=True))
def downgrade():
pass