...
 
Commits (3)
_subscriptions.txt
.archive
* install `youtube-dl`
* clone this into `/usr/local/scripts/youtube`
* setup cronjob. for example: `*/15 * * * * flock --no-fork --exclusive --nonblock /var/lock/plex-youtube.lock -c '/usr/local/scripts/youtube/download.sh > /var/log/plex-youtube.log'`
* setup subscriptions webinterface:
* `cp subscriptions-web.service /etc/systemd/system/`
* `systemctl daemon-reload`
* `systemctl enable --now subscriptions-web`
this script downloads to `/storage/plex/media/youtube/` and deletes old files after 14 days. this can be configured in `download.sh` and `youtube-dl.sh`
you may need to change the path to `youtube-dl` in `youtube-dl.sh`
Subscription URLs can be Youtube Channel URLs or any other URL that is supported by `youtube-dl`
#!/bin/bash
days=14
path=/storage/plex/media/youtube/
if [[ ! -d ${path} ]]; then
echo $path not found
exit 1
fi
cd ${path}
while read line; do
link=$(echo ${line} | cut -d ';' -f 2)
channel=$(echo ${line} | cut -d ';' -f 1)
mkdir -p ${channel}/_new
pushd ${channel}/_new
/usr/local/scripts/youtube/youtube-dl.sh ${link} 2>&1 | tee /tmp/youtube-dl.log
popd
rm -r ${channel}/_new
#grep -B 2 --no-group-separator "upload date is not in range" /tmp/youtube-dl.log | grep -v "upload date is not in range" | grep "\[youtube\]" | cut -d ":" -f 1 | tr -d '[]' | uniq >> /usr/local/scripts/youtube/.archive
done < /usr/local/scripts/youtube/_subscriptions.txt
touch .plexignore
find ${path} -mtime +${days} -type f -delete
rmdir ${path}* 2> /dev/null
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<movie>
<title>--title--</title>
<premiered>--date--</premiered>
<plot>--description--</plot>
</movie>
#!/bin/bash
infofile=${1%.*}.info.json
outputfilename=${1}
mkdir -p "../${outputfilename%.*}"
mkvpropedit --edit info --set "title=$(jq -r .title "${infofile}" | tr '/\\"' ' ')" "${1}"
sed -e "s#--title--#$(jq -r .title "${infofile}" | tr -d '#')#" -e "s/--date--/$(jq -r .upload_date "${infofile}")/" -e "s#--description--#$(jq -r .description "${infofile}" | tr '\n' ' ' | tr -d '#')#g" /usr/local/scripts/youtube/info.xml > "../${outputfilename%.*}/${outputfilename%.*}.nfo"
ls -l
mv -f "${1%.*}.jpg" "../${outputfilename%.*}/poster.jpg"
if [[ -f "${1%.*}.description" ]]; then
mv -f "${1%.*}.description" "../${outputfilename%.*}/description.txt"
fi
mv -f "${1%.*}".*.vtt "../${outputfilename%.*}/" 2>&1
mv -f "${1%.*}".*.ssa "../${outputfilename%.*}/" 2>&1
mv -f "${1%.*}".*.ass "../${outputfilename%.*}/" 2>&1
mv -f "${1%.*}".*.smi "../${outputfilename%.*}/" 2>&1
mv -f "${1%.*}".*.srt "../${outputfilename%.*}/" 2>&1
mv -f "${1%.*}".*.json "../${outputfilename%.*}/" 2>&1
mv -f "${1}" "../${outputfilename%.*}/${outputfilename}"
#!/usr/bin/env python3
import sys
from http.server import BaseHTTPRequestHandler, HTTPServer
from cgi import parse_header
from urllib.parse import parse_qs
class Server(BaseHTTPRequestHandler):
def do_GET(self):
body = '<form action="" method="POST"><table><tr><th>Name</th><th>URL</th><th><th></tr>'
body += '<tr><td><input type="text" name="name" placeholder="name"></td><td><input type="text" name="url" placeholder="url"></td><td><button type="submit" name="action" value="add">+</button></td></tr>'
for name, url in subscriptions.items():
body += '<tr><td>' + name + '</td><td>' + url + '</td><td><button type="submit" name="action" value="del_' + name + '">&times;</button><td></tr>'
body += '</table></form>'
self._sendResponse(200, bytes(body, 'utf-8'), contenttype='text/html')
def do_POST(self):
ctype, pdict = parse_header(self.headers['content-type'])
if ctype != 'application/x-www-form-urlencoded':
self._sendResponse(400, b'Bad Request')
return
length = int(self.headers['content-length'])
qs = self.rfile.read(length).decode()
postvars = parse_qs(qs, keep_blank_values=1)
if not 'action' in postvars:
self._sendResponse(400, b'Bad Request')
return
action = postvars['action'][0]
print('action: %s' % (action))
if action.startswith('del_'):
name = action[4:]
print('name: %s' % (name))
del subscriptions[name]
elif action == 'add':
name = postvars['name'][0]
url = postvars['url'][0]
print('name: %s' % (name))
print('url: %s' % (url))
if len(name) == 0 or len(url) == 0:
self._sendResponse(400, b'Bad Request')
return
subscriptions[name] = url
else:
self._sendResponse(400, b'Bad Request')
return
saveSubscriptions()
self.send_response(302)
self.send_header('Location', '.')
self.end_headers()
def _sendResponse(self, code, body, contenttype = 'text/plain'):
self.send_response(code)
self.send_header('Content-type', contenttype)
self.end_headers()
self.wfile.write(body)
def saveSubscriptions():
global subscriptions
print('saving subscriptions...')
subscriptions = {k: subscriptions[k] for k in sorted(subscriptions)}
with open('_subscriptions.txt', mode='w') as f:
for name, url in subscriptions.items():
f.write(name + ';' + url + '\n')
subscriptions = {}
def run(server_class=HTTPServer, handler_class=Server, port=80):
print('loading subscriptions...');
with open('_subscriptions.txt') as f:
content = f.readlines()
for line in content:
name, url = line.strip().split(';')
subscriptions[name] = url
print('Starting httpd...')
server_address = ('', port)
httpd = server_class(server_address, handler_class)
httpd.serve_forever()
if __name__ == "__main__":
try:
if len(sys.argv) == 2:
run(port=int(sys.argv[1]))
else:
run()
except KeyboardInterrupt as e:
print(e)
[Unit]
Description=subscriptions web interface
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 -u /usr/local/scripts/youtube/subscriptions-web.py 8080
WorkingDirectory=/usr/local/scripts/youtube/
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
#!/bin/bash
days=14
/usr/local/bin/youtube-dl \
--all-subs \
--write-info-json \
--write-thumbnail \
--output '%(uploader)s - %(title)s - %(id)s.%(ext)s' \
--dateafter $(date +%Y%m%d -d "${days} days ago") \
--playlist-items 1-20 \
--format 'bestvideo[height<=1080][height>=720][vcodec^=avc]+bestaudio/bestvideo[height<=1080][height>=720]+bestaudio/best[height<=1080][height>=720]' \
--download-archive /usr/local/scripts/youtube/.archive \
--cache-dir /tmp/youtube-dl/cache/ \
--write-description \
--no-overwrites \
--continue \
--ignore-errors \
--recode-video mkv \
--merge-output-format mkv \
--exec /usr/local/scripts/youtube/postprocess.sh \
"${1}" 2>&1 | tee /tmp/youtube-dl.log