#! /usr/bin/env python # -*- coding: utf-8 -*- import logging import os import re import shutil import tempfile import urllib.request from configparser import ConfigParser from pprint import pp import feedparser import requests from pymkv import MKVFile, MKVTrack logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.DEBUG) config = ConfigParser(interpolation=None) config.read('config.ini') def build_filename(name, titel_dict): if titel_dict == []: return None if titel_dict[0]['episod'].isdigit(): filename = '{name} S{season:>02}E{episod:>02} {titel}'.format( name=name, **titel_dict[0]) else: filename = '{name} S{season:>02}.{episod} {titel}'.format( name=name, **titel_dict[0]) return filename.strip().replace(' ', '.') def make_mkv(data): series_name = data['series'] default_lang = config[series_name]['default_language'] lang_sort = config[series_name]['languages'].split(',') def add_video(lang, path): logging.debug('[MKV] add video (%s, %s)', lang, path) video = MKVTrack(path, track_id=0, language=lang, default_track=True) mkv.add_track(video) def add_audio(lang, path): logging.debug('[MKV] add audio (%s, %s)', lang, path) audio = MKVTrack(path, track_id=1, language=lang, default_track=lang == default_lang) mkv.add_track(audio) mkv = MKVFile() add_video(default_lang, data['lang'][default_lang]) for lang in lang_sort: mp4_file = data['lang'].pop(lang, None) if mp4_file is not None: add_audio(lang, mp4_file) mkv.mux(data['mkvpath']) def parse_feed(series_name): d = feedparser.parse(config[series_name]['rss']) episodes = dict() for item in d['entries']: title = item['title'] link = item['link'] for lang in config[series_name]['languages'].split(','): pattern = config[series_name][lang] groups = [x.groupdict() for x in re.finditer(pattern, title, re.M)] if len(groups) == 1: break filename = build_filename(series_name, groups) if filename is None: logging.warning('skip %s', title) continue if filename not in episodes: episodes[filename] = dict() episodes[filename]['lang'] = dict() episodes[filename]['lang'][lang] = link season = '{season:>02}'.format(**groups[0]) episod = '{episod:>02}'.format(**groups[0]) basepath = os.path.join(config[series_name]['save_path'], series_name, f'Season {season:>02}') mkvpath = os.path.join(basepath, filename + '.mkv') episodes[filename]['season'] = season episodes[filename]['episod'] = episod episodes[filename]['series'] = series_name episodes[filename]['basepath'] = basepath episodes[filename]['mkvpath'] = mkvpath return episodes def download_files(episodes): for episod in sorted(episodes.keys()): item = episodes[episod] if os.path.exists(item['mkvpath']): continue basepath = item['basepath'] os.makedirs(basepath, exist_ok=True) temp = tempfile.TemporaryDirectory(dir=basepath) for lang in item['lang']: link = item['lang'][lang] filepath = os.path.join(temp.name, os.path.basename(link)) logging.info('start downloading...') logging.debug('source: %s', link) logging.debug('destination: %s', filepath) try: response = urllib.request.urlopen(link) with requests.get(link, stream=True) as r: with open(filepath, 'wb') as f: shutil.copyfileobj(r.raw, f) item['lang'][lang] = filepath except: logging.error("download") pass make_mkv(item) temp.cleanup() def run(): logging.info('====== START ======') for series_name in config.sections(): episodes = parse_feed(series_name) download_files(episodes) logging.info('====== END ======') if __name__ == "__main__": run()