Skip to content

Commit 752fe04

Browse files
committed
Add script to clean up database entries
to fix collections - see jellyfin/jellyfin#1278 and jellyfin/jellyfin#1338
1 parent fe95ecc commit 752fe04

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

jellyfin-collection-fix.py

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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

Comments
 (0)