Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add database access library #315

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions plex_trakt_sync/commands/inspect.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import click
from plexapi.server import PlexServer
from plex_trakt_sync.config import CONFIG
from plex_trakt_sync.database import PlexDatabase, Database
from plex_trakt_sync.media import MediaFactory
from plex_trakt_sync.plex_api import PlexApi
from plex_trakt_sync.trakt_api import TraktApi
from plex_trakt_sync.version import git_version_info
Expand All @@ -21,6 +23,7 @@ def inspect(input):
server = PlexServer(url, token)
plex = PlexApi(server)
trakt = TraktApi()
mf = MediaFactory(plex=plex, trakt=trakt)

if input.isnumeric():
input = int(input)
Expand All @@ -47,3 +50,10 @@ def inspect(input):
print(f"Trakt match: {tm}")
except Exception as e:
print(f"Error: {e}")

mi = mf.resolve(m)
print(f"Trakt watched at: {mi.trakt_last_watched_at}")

if input == 6114:
db = PlexDatabase(Database('com.plexapp.plugins.library.db'))
db.mark_watched(mi, mi.trakt_last_watched_at)
141 changes: 141 additions & 0 deletions plex_trakt_sync/database.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import sqlite3
from datetime import datetime
from typing import Union

from plexapi.server import PlexServer
from plexapi.video import Movie, Episode

from plex_trakt_sync.logging import logger
from plex_trakt_sync.media import Media


class Database(object):
_uncommited = False

def __init__(self, database_path: str):
try:
self.filename = database_path
self._connection = sqlite3.connect(database_path)
self._cursor = self._connection.cursor()
self._cursor.execute('ANALYZE')

except sqlite3.OperationalError as e:
logger.error(e)
raise e

except sqlite3.DatabaseError as e:
logger.error(e)
raise e

@property
def cursor(self):
return self._cursor

def __enter__(self):
return self

def __exit__(self, exc_type, exc_val, exc_tb):
if self._uncommited:
self.commit()

self._connection.close()

def execute(self, query, *args):
self._uncommited = True
return self.cursor.execute(query, *args)

def commit(self):
self._connection.commit()
self._uncommited = False

def rollback(self):
self._connection.rollback()
self._uncommited = False

def has_uncommited(self):
return self._uncommited

def format_time(self, time: datetime):
"""
Format datetime for sqlite, Plex dates are in localtime.
"""
return time.astimezone().replace(tzinfo=None).isoformat(' ', timespec='seconds')


class PlexDatabase:
_insert_watched = """
INSERT INTO metadata_item_views (
account_id,
guid,
metadata_type,
library_section_id,
grandparent_title,
parent_index,
parent_title,
"index",
title,
thumb_url,
viewed_at,
grandparent_guid,
originally_available_at,
device_id
) VALUES (
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
)
"""

_update_metadata_item_settings = """
UPDATE metadata_item_settings
SET
view_count = view_count+1,
last_viewed_at = ?
WHERE
guid = ?
"""

def __init__(self, db: Database):
self.db = db

def mark_watched(self, media: Media, time: datetime):
plex: PlexServer = media.plex_api.plex
pm: Union[Movie, Episode] = media.plex.item

account = plex.systemAccount(0)
device = plex.systemDevice(1)

account_id = account.id
device_id = device.id
metadata_type = 1
library_section_id = pm.librarySectionID
grandparent_title = None
parent_index = -1
parent_title = None
index = 1
title = pm.title
thumb_url = None
grandparent_guid = None

with self.db as db:
originally_available_at = db.format_time(pm.originallyAvailableAt)
viewed_at = db.format_time(time)
db.execute(self._insert_watched, (
account_id,
media.plex.guid,
metadata_type,
library_section_id,
grandparent_title,
parent_index,
parent_title,
index,
title,
thumb_url,
viewed_at,
grandparent_guid,
originally_available_at,
device_id
))
# TODO: if uypdate fails, must insert
db.execute(self._update_metadata_item_settings, (
viewed_at,
media.plex.guid,
))
6 changes: 6 additions & 0 deletions plex_trakt_sync/media.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from requests import RequestException, ReadTimeout
from trakt.errors import TraktException

from plex_trakt_sync.decorators import memoize
from plex_trakt_sync.logging import logger
from plex_trakt_sync.plex_api import PlexLibraryItem, PlexApi
from plex_trakt_sync.trakt_api import TraktApi
Expand Down Expand Up @@ -68,6 +69,11 @@ def mark_watched_trakt(self):
def mark_watched_plex(self):
self.plex_api.mark_watched(self.plex.item)

@property
@memoize
def trakt_last_watched_at(self):
return self.trakt_api.last_watched_at(self.trakt)

@property
def trakt_rating(self):
return self.trakt_api.rating(self.trakt)
Expand Down
14 changes: 14 additions & 0 deletions plex_trakt_sync/trakt_api.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from typing import Union
from datetime import datetime, timezone

import trakt

from plex_trakt_sync import pytrakt_extensions
Expand Down Expand Up @@ -167,6 +169,18 @@ def scrobbler(self, media: Union[Movie, TVEpisode]) -> ScrobblerProxy:
def mark_watched(self, m, time):
m.mark_as_seen(time)

@memoize
def last_watched_at(self, m: Union[Movie, TVEpisode]):
match = [x for x in self.me.watched_movies if x.trakt == m.trakt]
if not match:
return None
watched_at = match[0].last_watched_at

date = datetime.strptime(watched_at, '%Y-%m-%dT%H:%M:%S.000Z')
utcdate = date.replace(tzinfo=timezone.utc)

return utcdate

def add_to_collection(self, m, pm: PlexLibraryItem):
if m.media_type == "movies":
item = dict(
Expand Down