ytarchiver

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

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:
Achannel.py | 144+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Arequirements.txt | 5+++++
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