This commit is contained in:
parent
9cc7018698
commit
6641053beb
73
personal_data/fetchers/jellyfin_watch_history.py
Normal file
73
personal_data/fetchers/jellyfin_watch_history.py
Normal file
|
@ -0,0 +1,73 @@
|
|||
import dataclasses
|
||||
import datetime
|
||||
import logging
|
||||
import re
|
||||
import bs4
|
||||
from typing import Any
|
||||
from collections.abc import Iterator
|
||||
from jellyfin_apiclient_python import JellyfinClient
|
||||
|
||||
from ..data import DeduplicateMode, Scraper
|
||||
from .. import secrets, parse_util, html_util, _version
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
URL_SITE_ROOT = 'https://steamcommunity.com/'
|
||||
|
||||
URL_GAME_ACHIVEMENTS = URL_SITE_ROOT+'id/{username}/stats/appid/{appid}'
|
||||
|
||||
FORMAT_DATE_HEADER = '%d/%m/%YYYY'
|
||||
|
||||
def iterate_series(client):
|
||||
result = client.jellyfin.user_items(params = {
|
||||
'includeItemTypes': 'Series',
|
||||
'parentId': 'a656b907eb3a73532e40e44b968d0225',
|
||||
'userId': 'dd95c1085c1b4e83ba8e8853fbc644ab',
|
||||
})
|
||||
yield from result['Items']
|
||||
|
||||
def iterate_watched_episodes_of_series(client, series_id: str):
|
||||
result = client.jellyfin.user_items(params = {
|
||||
'filters': 'IsPlayed',
|
||||
'recursive': True,
|
||||
'includeItemTypes': 'Episode',
|
||||
'parentId': series_id,
|
||||
'userId': 'dd95c1085c1b4e83ba8e8853fbc644ab',
|
||||
'fields': 'AirTime',
|
||||
})
|
||||
yield from result['Items']
|
||||
|
||||
@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()
|
||||
|
||||
client.config.app('personal_data', _version.__version__,
|
||||
'test_machine', 'unique_id_1')
|
||||
|
||||
client.config.data["auth.ssl"] = False
|
||||
client.auth.connect_to_address(secrets.JELLYFIN_URL)
|
||||
client.auth.login(secrets.JELLYFIN_URL, secrets.JELLYFIN_USERNAME, secrets.JELLYFIN_PASSWORD)
|
||||
|
||||
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
|
||||
|
|
@ -124,7 +124,7 @@ def main(
|
|||
OUTPUT_PATH / f'{scraper.dataset_name}.csv',
|
||||
result_rows,
|
||||
deduplicate_mode=scraper.deduplicate_mode,
|
||||
deduplicate_ignore_columns=scraper.deduplicate_ignore_columns,
|
||||
deduplicate_ignore_columns=scraper.deduplicate_ignore_columns(),
|
||||
)
|
||||
logger.info('Scraper done: %s', scraper.dataset_name)
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ KUCOIN_KEY = load_secret('KUCOIN_KEY')
|
|||
KUCOIN_SECRET = load_secret('KUCOIN_SECRET')
|
||||
KUCOIN_PASS = load_secret('KUCOIN_PASS')
|
||||
|
||||
# KRAKEN
|
||||
# Kraken
|
||||
KRAKEN_KEY = load_secret('KRAKEN_KEY')
|
||||
KRAKEN_SECRET = load_secret('KRAKEN_SECRET')
|
||||
|
||||
|
@ -35,3 +35,8 @@ HOME_ASSISTANT_LLAK = load_secret('HOME_ASSISTANT_LLAK')
|
|||
MAILGUN_API_KEY = load_secret('MAILGUN_API_KEY')
|
||||
MAILGUN_DOMAIN = load_secret('MAILGUN_DOMAIN')
|
||||
MAILGUN_RECIPIENT = load_secret('MAILGUN_RECIPIENT')
|
||||
|
||||
# Jellyfin
|
||||
JELLYFIN_URL = load_secret('JELLYFIN_URL')
|
||||
JELLYFIN_USERNAME = load_secret('JELLYFIN_USERNAME')
|
||||
JELLYFIN_PASSWORD = load_secret('JELLYFIN_PASSWORD')
|
||||
|
|
|
@ -89,6 +89,7 @@ def deduplicate_by_ignoring_certain_fields(
|
|||
|
||||
Output order is stable.
|
||||
"""
|
||||
|
||||
to_remove = set()
|
||||
for idx1, first in enumerate(dicts):
|
||||
for idx2, second in enumerate(dicts[idx1 + 1 :], idx1 + 1):
|
||||
|
@ -163,7 +164,7 @@ def load_csv_file(csv_file: Path) -> list[frozendict]:
|
|||
|
||||
def extend_csv_file(
|
||||
csv_file: Path,
|
||||
new_dicts: list[dict],
|
||||
new_dicts: list[dict[str,typing.Any]],
|
||||
deduplicate_mode: data.DeduplicateMode,
|
||||
deduplicate_ignore_columns: list[str],
|
||||
) -> dict:
|
||||
|
|
Loading…
Reference in New Issue
Block a user