2024-09-08 18:20:09 +00:00
|
|
|
import dataclasses
|
|
|
|
import logging
|
|
|
|
from collections.abc import Iterator
|
2024-10-03 21:24:12 +00:00
|
|
|
from typing import Any
|
|
|
|
|
2024-09-08 18:20:09 +00:00
|
|
|
from jellyfin_apiclient_python import JellyfinClient
|
|
|
|
|
2024-10-03 21:24:12 +00:00
|
|
|
from .. import _version, secrets
|
2024-09-08 18:20:09 +00:00
|
|
|
from ..data import DeduplicateMode, Scraper
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
URL_SITE_ROOT = 'https://steamcommunity.com/'
|
|
|
|
|
2024-10-03 21:24:12 +00:00
|
|
|
URL_GAME_ACHIVEMENTS = URL_SITE_ROOT + 'id/{username}/stats/appid/{appid}'
|
2024-09-08 18:20:09 +00:00
|
|
|
|
|
|
|
FORMAT_DATE_HEADER = '%d/%m/%YYYY'
|
|
|
|
|
2024-10-03 21:24:12 +00:00
|
|
|
|
2024-09-08 18:20:09 +00:00
|
|
|
def iterate_series(client):
|
2024-10-03 21:24:12 +00:00
|
|
|
result = client.jellyfin.user_items(
|
|
|
|
params={
|
|
|
|
'includeItemTypes': 'Series',
|
|
|
|
'parentId': 'a656b907eb3a73532e40e44b968d0225',
|
|
|
|
'userId': 'dd95c1085c1b4e83ba8e8853fbc644ab',
|
|
|
|
},
|
|
|
|
)
|
2024-09-08 18:20:09 +00:00
|
|
|
yield from result['Items']
|
|
|
|
|
2024-10-03 21:24:12 +00:00
|
|
|
|
2024-09-08 18:20:09 +00:00
|
|
|
def iterate_watched_episodes_of_series(client, series_id: str):
|
2024-10-03 21:24:12 +00:00
|
|
|
result = client.jellyfin.user_items(
|
|
|
|
params={
|
|
|
|
'filters': 'IsPlayed',
|
|
|
|
'recursive': True,
|
|
|
|
'includeItemTypes': 'Episode',
|
|
|
|
'parentId': series_id,
|
|
|
|
'userId': 'dd95c1085c1b4e83ba8e8853fbc644ab',
|
|
|
|
'fields': 'AirTime',
|
|
|
|
},
|
|
|
|
)
|
2024-09-08 18:20:09 +00:00
|
|
|
yield from result['Items']
|
|
|
|
|
2024-10-03 21:24:12 +00:00
|
|
|
|
2024-09-08 18:20:09 +00:00
|
|
|
@dataclasses.dataclass(frozen=True)
|
|
|
|
class JellyfinWatchHistoryScraper(Scraper):
|
|
|
|
dataset_name = 'show_episodes_watched'
|
|
|
|
deduplicate_mode = DeduplicateMode.BY_ALL_COLUMNS
|
|
|
|
|
|
|
|
def scrape(self) -> Iterator[dict[str, Any]]:
|
|
|
|
client = JellyfinClient()
|
|
|
|
|
2024-10-03 21:24:12 +00:00
|
|
|
client.config.app(
|
2024-10-10 22:54:01 +00:00
|
|
|
'personal_data',
|
|
|
|
_version.__version__,
|
|
|
|
'test_machine',
|
|
|
|
'unique_id_1',
|
2024-10-03 21:24:12 +00:00
|
|
|
)
|
2024-09-08 18:20:09 +00:00
|
|
|
|
2024-10-03 21:24:12 +00:00
|
|
|
client.config.data['auth.ssl'] = False
|
2024-09-08 18:20:09 +00:00
|
|
|
client.auth.connect_to_address(secrets.JELLYFIN_URL)
|
2024-10-03 21:24:12 +00:00
|
|
|
client.auth.login(
|
2024-10-10 22:54:01 +00:00
|
|
|
secrets.JELLYFIN_URL,
|
|
|
|
secrets.JELLYFIN_USERNAME,
|
|
|
|
secrets.JELLYFIN_PASSWORD,
|
2024-10-03 21:24:12 +00:00
|
|
|
)
|
2024-09-08 18:20:09 +00:00
|
|
|
|
|
|
|
for series_data in iterate_series(client):
|
|
|
|
series_id = series_data['Id']
|
|
|
|
for episode_data in iterate_watched_episodes_of_series(client, series_id):
|
|
|
|
episode_index = episode_data.get('IndexNumber')
|
|
|
|
if episode_index is None:
|
|
|
|
continue
|
|
|
|
yield {
|
|
|
|
'series.name': episode_data['SeriesName'],
|
|
|
|
'season.name': episode_data['SeasonName'],
|
|
|
|
'episode.index': int(episode_index),
|
|
|
|
'episode.name': episode_data['Name'],
|
|
|
|
'me.last_played_time': episode_data['UserData']['LastPlayedDate'],
|
|
|
|
'episode.duration_seconds': episode_data['RunTimeTicks'] / 10000000,
|
|
|
|
'episode.premiere_date': episode_data.get('PremiereDate'),
|
|
|
|
}
|
|
|
|
|
|
|
|
del episode_data
|
|
|
|
del series_data, series_id
|