forked from stokkes/plex_rcs
-
Notifications
You must be signed in to change notification settings - Fork 1
/
plex_rcs.py
executable file
·136 lines (116 loc) · 4.49 KB
/
plex_rcs.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/usr/bin/python3
#
# Helper script
#
import os
import sys
import re
import argparse
import yaml
import time
from datetime import datetime
from multiprocessing import Pool
from subprocess import run
from plexapi.myplex import PlexServer
import tailer
def config(file):
global servers, cfg
with open(file, 'r') as ymlfile:
cfg = yaml.load(ymlfile,Loader=yaml.FullLoader)['plex_rcs']
servers = []
for server in cfg['servers']:
try:
plex = PlexServer(
"http://{0}:{1}".format(server['host'], server['port']), server['token'])
servers.append(plex)
except:
sys.exit("Failed to connect to plex server {0}:{1}.".format(
server['host'], server['port']))
def build_sections():
global paths
# Build our library paths dictionary
for section in servers[0].library.sections():
for l in servers[0].library.section(section.title).locations:
paths.update({l: section.key})
def scan(folder):
directory = os.path.abspath("{0}/{1}".format(cfg['media_root'].rstrip("\\").rstrip("/"), folder))
# Match the new file with a path in our library
# and trigger a scan via a `docker exec` call
found = False
for p in paths:
if p in directory:
found = True
section_id = paths[p]
print("Processing section {0}, folder: {1}".format(section_id, directory))
for server in servers:
try:
# Use run for non-blocking
run(["/usr/bin/docker", "exec", "-it", server['container'], "bash", "-c",
"export LD_LIBRARY_PATH=/usr/lib/plexmediaserver/lib;/usr/lib/plexmediaserver/Plex\ Media\ Scanner" " --scan" " --refresh" " --section {0} --directory '{1}'".format(section_id, directory)])
except:
print("Error executing docker command")
if not found:
print("Scanned directory '{0}' not found in Plex library".format(directory))
def tailf(logfile):
print("Starting to monitor {0} with pattern for rclone {1}".format(
logfile, cfg['backend']))
for line in tailer.follow(open(logfile)):
if re.match(r".*(mkv:|mp4:|mpeg4:|avi:) received cache expiry notification", line):
search = re.search(r'^[0-9]{4}\/[0-9]{2}\/[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} INFO : (.*): received cache expiry notification', line, re.IGNORECASE)
if search is not None:
f = search.group(1)
print("Detected new file: {0}".format(f))
scan(os.path.dirname(f))
def find_log():
if args.logfile:
lf = args.logfile
if not os.path.isfile(lf):
print("Log file '{0}' does not exist.".format(args.logfile))
sys.exit(1)
else:
lf = cfg['log_file']
if not os.path.isfile(lf):
print("Log file {0} does not exist.".format(lf))
sys.exit(1)
return lf
if __name__ == "__main__":
parser = argparse.ArgumentParser(
prog="plex_rcs_helper.py", description="Small helper script to update a Plex library section by scanning a specific directory.")
parser.add_argument("-d", "--directory", dest="directory",
metavar="directory", help="Directory to scan")
parser.add_argument("-l", "--logfile", dest="logfile", metavar="logfile",
help="Log file to monitor (default /var/log/syslog)")
parser.add_argument("-c", "--config", dest="config",
metavar="config", help="config file")
parser.add_argument("--test", action='store_true', help="Test config")
args = parser.parse_args()
# Initialize our paths dict
paths = {}
# Configuration file
if args.config:
cf = args.config
if not os.path.isfile(cf):
print("Configuration file '{0}' does not exist.".format(
args.config))
sys.exit(1)
else:
cf = "{0}/config.yml".format(
os.path.dirname(os.path.realpath(__file__)))
if not os.path.isfile(cf):
print("Configuration file '{0}' does not exist.".format(
os.path.dirname(os.path.realpath(__file__))))
sys.exit(1)
# Main
if args.test:
config(cf)
find_log()
elif args.directory:
config(cf)
find_log()
build_sections()
scan(args.directory)
else:
config(cf)
lf = find_log()
build_sections()
tailf(lf)