commit 7b05607e38d897d5abba95b5e332232e6d0d790d
parent 7d36ec96cc4cc69910a9439aa850a0a75e3a4687
Author: lash <dev@holbrook.no>
Date: Wed, 12 Aug 2026 14:47:02 -0600
Use custom ytdl-nfo through git source in requirements
Diffstat:
2 files changed, 149 insertions(+), 0 deletions(-)
diff --git a/channel.py b/channel.py
@@ -0,0 +1,144 @@
+import mimetypes
+import sys
+import logging
+import os
+import urllib.request
+import json
+import re
+
+import lxml.etree
+
+logging.basicConfig(level=logging.DEBUG)
+logg = logging.getLogger()
+
+
+class YTChannelMeta:
+
+ def __init__(self, tree=None, remote=None):
+ self.o = lxml.etree.fromstring('<?xml version="1.0" ?><tvshow></tvshow>')
+ self.fp = None
+ self.wd = None
+ self.base = None
+ self.remote = remote
+
+
+ def load_nfo(self, fp):
+ s = os.path.basename(fp)
+ self.wd = os.path.dirname(fp)
+ v = os.path.splitext(s)
+ self.base = v[0]
+ self.o = lxml.etree.fromstring('<?xml version="1.0" ?><tvshow></tvshow>')
+ self.fp = fp
+
+
+ def load_json(self, fp):
+ if self.o == None:
+ raise AttributeError('no nfo tree')
+ f = open(fp, 'r')
+ o = json.load(f)
+ f.close()
+ self.process(o)
+
+
+ def process(self, o):
+ v = lxml.etree.Element('title')
+ v.text = o['title']
+ self.o.append(v)
+
+ v = lxml.etree.Element('originaltitle')
+ v.text = o['channel']
+ self.o.append(v)
+
+ v = lxml.etree.Element('plot')
+ v.text = o['description']
+ self.o.append(v)
+
+ v = lxml.etree.Element('uniqueid')
+ v.set('type', 'youtube')
+ v.set('default', 'true')
+ v.text = o['channel_id']
+ self.o.append(v)
+
+
+ v = lxml.etree.Element('seasons')
+ v.text = '1'
+ self.o.append(v)
+
+ self.process_thumb(o)
+ self.process_tags(o)
+
+
+ def process_thumb(self, o):
+ c = None
+ s = None
+ for v in o['thumbnails']:
+ try:
+ pri = v['preference']
+ except KeyError:
+ continue
+ if c == None or pri > c:
+ c = pri
+ s = v['url']
+
+ if s == None:
+ raise AttributeError('thumbnail missing')
+
+ with urllib.request.urlopen(s) as response:
+ t = response.info().get_content_type()
+ b = response.read()
+ #fp = '{}-poster{}'.format(self.base, ext)
+ fp = 'poster' + mimetypes.guess_extension(t)
+ fp = os.path.join(self.wd, fp)
+ f = open(fp, 'wb')
+ f.write(b)
+ f.close()
+
+
+ def process_tags(self, o):
+ for v in o['tags']:
+ logg.info('add tag {}'.format(v))
+ element = lxml.etree.Element('tag')
+ element.text = v
+ self.o.append(element)
+
+
+ def save(self, w=None):
+ close = False
+ if w == None:
+# if self.fp == None:
+# raise AttributeError('missing file path')
+# w = open(self.fp, 'w')
+ fp = os.path.join(self.wd, 'tvshow.nfo')
+ w = open(fp, 'w')
+ close = True
+ w.write(str(self))
+ if close:
+ w.close()
+
+
+ def __str__(self):
+ return lxml.etree.tostring(self.o).decode('utf-8')
+
+
+def main():
+ #ofp = os.path.realpath(sys.argv[1])
+ #d = os.path.dirname(ofp)
+ #try:
+ # ifp = os.path.realpath(sys.argv[2])
+ #except IndexError:
+ # ifp = os.path.splitext(ofp)[0] + '.info.json'
+ ifp = os.path.realpath(sys.argv[1])
+ d = os.path.dirname(ifp)
+ ofp = os.path.splitext(ifp)[0]
+ ofp = os.path.splitext(ofp)[0] + '.nfo'
+
+ o = YTChannelMeta()
+ logg.debug('json {}, nfo {}'.format(ifp, ofp))
+
+ o.load_nfo(ofp)
+ o.load_json(ifp)
+ o.save()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/requirements.txt b/requirements.txt
@@ -0,0 +1,5 @@
+lxml==6.1.1
+PyYAML==6.0.3
+setuptools==80.10.2
+#ytdl-nfo==0.3.0
+git+git://git.casanodo/ytdl-nfo.git@lash/external-config-path