|
| 1 | +#!/usr/bin/env python3 |
| 2 | +# Copyright (c) Oddstr13 |
| 3 | +# License: MIT - https://opensource.org/licenses/MIT |
| 4 | +# |
| 5 | +# Based on cvium's SQL statements; https://github.com/jellyfin/jellyfin/pull/1338#issuecomment-488223840 |
| 6 | + |
| 7 | +import os |
| 8 | +import sys |
| 9 | +import sqlite3 |
| 10 | +import pwd |
| 11 | + |
| 12 | +DBFILE = "/var/lib/jellyfin/data/library.db" |
| 13 | + |
| 14 | +def isRunning(): |
| 15 | + return not os.system("ps axwwo comm --no-headers | grep -i '^jellyfin$' > /dev/null") |
| 16 | + |
| 17 | +if __name__ == "__main__": |
| 18 | + # Make sure that Jellyfin is not running. |
| 19 | + if isRunning(): |
| 20 | + print("You should stop jellyfin before running this script.") |
| 21 | + print("$ systemctl stop jellyfin") |
| 22 | + exit(50) |
| 23 | + |
| 24 | + # Make sure we can write to the DB file |
| 25 | + if not os.access(DBFILE, os.W_OK): |
| 26 | + print("ERROR: No write access to {}".format(DBFILE)) |
| 27 | + print("Try running this script as the jellyfin user:") |
| 28 | + print("sudo -u {} {}".format(pwd.getpwuid(os.stat(DBFILE).st_uid).pw_name, ' '.join([sys.executable] + sys.argv))) |
| 29 | + exit(100) |
| 30 | + |
| 31 | + |
| 32 | + with sqlite3.connect(DBFILE) as conn: |
| 33 | + cur = conn.cursor() |
| 34 | + |
| 35 | + # Get a list of incorrect UserDataKeys |
| 36 | + res = cur.execute("SELECT tbi2.UserDataKey, tbi2.type, tbi2.ExtraIds FROM TypedBaseItems tbi1 INNER JOIN TypedBaseItems tbi2 ON tbi2.Path = tbi1.Path and tbi1.Guid <> tbi2.Guid WHERE tbi2.ExtraType is not NULL and tbi1.ExtraType is NULL").fetchall() |
| 37 | + blacklist = [] |
| 38 | + for item in res: |
| 39 | + udk = item[0] |
| 40 | + if item[0] not in blacklist: |
| 41 | + blacklist.append(item[0]) |
| 42 | + |
| 43 | + # Remove the incorrect UserDataKeys from ExtraIds fields |
| 44 | + res = cur.execute("SELECT guid, ExtraIds, Name FROM TypedBaseItems;").fetchall() |
| 45 | + for guid, _eids, name in res: |
| 46 | + if not _eids: continue |
| 47 | + |
| 48 | + eids = _eids.split('|') |
| 49 | + |
| 50 | + new_eids = list(filter(lambda i: i not in blacklist, eids)) |
| 51 | + |
| 52 | + if len(eids) != len(new_eids): |
| 53 | + print(guid, len(eids), len(new_eids)) |
| 54 | + cur.execute("UPDATE TypedBaseItems SET ExtraIds=:eids WHERE guid=:guid", {'eids':'|'.join(new_eids), 'guid': guid}) |
| 55 | + print(name) |
| 56 | + |
| 57 | + # Delete the incorrect items |
| 58 | + res = cur.execute("SELECT tbi2.guid, tbi2.ExtraType, tbi2.Name FROM TypedBaseItems tbi1 INNER JOIN TypedBaseItems tbi2 ON tbi2.Path = tbi1.Path and tbi1.Guid <> tbi2.Guid WHERE tbi2.ExtraType is not NULL and tbi1.ExtraType is NULL").fetchall() |
| 59 | + for guid, etype, name in res: |
| 60 | + print([name, etype]) |
| 61 | + cur.execute("DELETE FROM TypedBaseItems WHERE guid=:guid", {'guid': guid}) |
| 62 | + |
| 63 | + # Clean up empty ExtraIds - Jellyfin will crash and burn if we don't. |
| 64 | + cur.execute("UPDATE TypedBaseItems SET ExtraIds=NULL WHERE ExtraIds='';") |
| 65 | + |
| 66 | + print("Done.") |
0 commit comments