PK!L@g66vidl/__init__.pyfrom vidl import app def main(): return app.main()PK! /BBvidl/__main__.pyif __name__ == '__main__': from vidl import app app.main()PK!E?v[[ vidl/app.pyimport sys from colorboy import green, cyan, red, magenta, yellow, bright def log(*args, error=False, quiet=False, **named_args): vidl_text = cyan('[vidl]') if error: print(vidl_text, red('error:'), *args, **named_args) quit() elif quiet == False: print(vidl_text, *args, **named_args) script_filename = sys.argv[0] def vidl_help(): print( '') print(green( 'Usage:')) print( ' '+cyan(script_filename)+' [format] [options] ') print( '') print(green( 'Options:')) print(cyan( ' format ')+'mp3, mp4, wav or m4a. Default mp3.') print(cyan( ' --no-md ')+'Don\'t add metadata to downloaded files.') print(cyan( ' --no-smart-md ')+'Don\'t extract artist and song name from title.') print(cyan( ' -v, --verbose ')+'Display all logs.') print(cyan( ' -h, --help ')+'Display this help message.') print( '') print(green( 'Configuration:')) print( ' '+cyan(script_filename)+' config [new_value]') print( ' ') print(green( 'Available Configs:')) print(cyan( ' download_folder ')+'The folder that vidl downloads to.') print(cyan( ' output_template ')+'youtube-dl output template.') print( '') quit() def main(): if len(sys.argv) <= 1: vidl_help() elif sys.argv[1] == 'config': from vidl import config config.main() else: from vidl import dl dl.main() if __name__ == '__main__': main()PK!(wwwvidl/config.json{ "download_folder": "~/Downloads", "output_template": "%(uploader)s - %(title)s.%(ext)s", "add_metadata": true }PK!0vidl/config.pyimport sys, json, os from colorboy import green from vidl.app import vidl_help, log from pprint import pformat def path(*args, **options): DIR = os.path.dirname(os.path.abspath(__file__)) return os.path.join(DIR, *args, **options) configs = json.loads(open(path('config.json')).read()) def save(): file = open(path('config.json'), "w+") file.write(json.dumps(configs, indent=2)) file.close() def set_default_downloads_path(): if sys.platform == 'darwin': set('downloads_path', '~/Downloads') elif sys.platform == 'win32': import os os.path.join(os.getenv('USERPROFILE'), 'Downloads') def load(value): if value == 'downloads_path' and configs[value] == None: set_default_downloads_path() return configs[value] def set(key, value): if not key in configs: log('Config does not exist:', green(key), error=True) configs[key] = value save() def main(): if len(sys.argv) not in [3, 4]: vidl_help() if len(sys.argv) == 3: key = sys.argv[2] value = load(key) log('Config', key+':', green(pformat(value))) if len(sys.argv) == 4: key = sys.argv[2] value = sys.argv[3] set(key, value) save() log(key, 'was set to:', green(pformat(value)))PK!E:GG vidl/dl.pyimport sys, os import pprint; pprint = pprint.PrettyPrinter(indent=4).pprint import youtube_dl from colorboy import cyan, green from deep_filter import deep_filter from vidl import app, config from vidl.app import log class Dicty(dict): __getattr__ = dict.__getitem__ __setattr__ = dict.__setitem__ def is_int(number): try: int(number) return True except ValueError: return False def main(): options = { 'url': '', 'file_format': 'mp3', 'audio_only': True, 'no_md': False, 'no_smart_md': False, 'verbose': False, 'download_folder': config.load('download_folder'), 'output_template': config.load('output_template'), 'add_metadata': config.load('add_metadata'), } if options['download_folder'] == None: log('download_folder config has not been set. To set it, run '+green(app.script_filename+' config download_folder '), error=True) video_formats = ['mp4'] audio_formats = ['mp3', 'wav', 'm4a'] id3_metadata_formats = ['mp3'] ytdl_output_template = os.path.join(options['download_folder'], options['output_template']) # parse arguments for arg in sys.argv[1:]: if arg in audio_formats: options['audio_only'] = True options['file_format'] = arg elif arg in video_formats: options['audio_only'] = False options['file_format'] = arg elif arg in ['--no-md']: options['no_md'] = True elif arg in ['--no-smart-md']: options['no_smart_md'] = True elif arg in ['-v', '--verbose']: options['verbose'] = True elif arg in ['-h', '--help']: app.vidl_help() elif '.' in arg: options['url'] = arg else: log('Unknown argument:', arg, error=True) if len(sys.argv) <= 1: # no arguments provided app.vidl_help() if options['url'] == '': log('No URL provided', error=True) # get info log('Fetching URL info') ytdl_get_info_options = { 'outtmpl': ytdl_output_template, 'quiet': False if options['verbose'] else True, } with youtube_dl.YoutubeDL(ytdl_get_info_options) as ytdl: try: info_result = ytdl.extract_info(options['url'], download=False) except: quit() if options['verbose']: pprint(info_result) # delete None properties/indexes def callback(value): return value != None cleaned_info_result = deep_filter(info_result.copy(), callback) # restructure if 'entries' in cleaned_info_result: videos = cleaned_info_result['entries'] playlist_info = cleaned_info_result.copy() del playlist_info['entries'] else: videos = [cleaned_info_result] playlist_info = {} # generate ytdl arguments ytdl_args = [] if options['audio_only']: ytdl_args += ['-x'] ytdl_args += ['-f', 'best'] ytdl_args += ['--audio-format', options['file_format']] else: ytdl_args += ['-f', 'bestvideo+bestaudio'] ytdl_args += ['--recode-video', options['file_format']] ytdl_args += ['--audio-quality', '0'] ytdl_args += ['-o', ytdl_output_template] if options['file_format'] in ['mp3', 'm4a', 'mp4']: ytdl_args += ['--embed-thumbnail'] if not options['verbose']: ytdl_args += ['--quiet'] # ytdl_args += [options['url']] video_index = -1 for video in videos: video_index += 0 try: filename = ytdl.prepare_filename(video) except: quit() filename_split = filename.split('.') filename_split[len(filename_split)-1] = options['file_format'] filename = '.'.join(filename_split) log('Downloading') try: youtube_dl.main(ytdl_args+[video['webpage_url']]) except: pass log('Saved as', filename) if options['file_format'] in id3_metadata_formats and not options['no_md']: log('Adding metadata to file') # get artist/title from title parsed_title = {} if 'title' in video and video['title'].count(' - ') == 1: if not options['no_smart_md']: split_title = video['title'].split(' - ') parsed_title['artist'] = split_title[0] parsed_title['title'] = split_title[1] md = Dicty() playlist = True if len(videos) > 1 else False # title if 'track' in video: md.title = video['track'] elif 'title' in parsed_title: md.title = parsed_title['title'] elif 'title' in video: md.title = video['title'] # artist if 'artist' in video: md.artist = video['artist'] if 'artist' in parsed_title: md.artist = parsed_title['artist'] elif 'uploader' in video: md.artist = video['uploader'] if playlist: #album if 'title' in playlist_info: md.album = playlist_info['title'] elif 'playlist_title' in video: md.album = video['playlist_title'] elif 'playlist' in video and type(video['playlist']) == str: md.album = video['playlist'] #album_artist if 'uploader' in playlist_info: md.album_artist = playlist_info['uploader'] elif 'playlist_uploader' in video: md.album_artist = video['playlist_uploader'] # track_number if 'playlist_index' in video: md.track_number = video['playlist_index'] else: md.track_number = video_index+1 # track_count if 'n_entries' in video: md.track_count = video['n_entries'] else: md.track_count = len(videos) # year if 'release_date' in video and is_int(video['release_date'][:4]): md.year = video['release_date'][:4] elif 'publish_date' in video and is_int(video['publish_date'][:4]): md.year = video['publish_date'][:4] elif 'upload_date' in video and is_int(video['upload_date'][:4]): md.year = video['upload_date'][:4] from vidl import md as md_module md_module.add_metadata(filename, md) log('Done') PK!}8ff vidl/md.pyfrom mutagen.id3 import ID3, TIT2, TPE1, TALB, TPE2, TRCK, TCON, TDRC # http://id3.org/id3v2.4.0-frames - COMM comment, USLT lyrics, TCOM composer from pprint import pformat from vidl.app import log def add_metadata(filename, md): tags = ID3(filename) if 'title' in md: tags["TIT2"] = TIT2(encoding=3, text=md.title) if 'artist' in md: tags["TPE1"] = TPE1(encoding=3, text=md.artist) if 'album' in md: tags["TALB"] = TALB(encoding=3, text=md.album) if 'album_artist' in md: tags["TPE2"] = TPE2(encoding=3, text=md.album_artist) if 'track_number' in md: track_number = str(md.track_number) if 'track_count' in md: track_number += '/'+str(md.track_count) tags["TRCK"] = TRCK(encoding=3, text=track_number) if 'genre' in md: tags["TCON"] = TCON(encoding=3, text=md.genre) if 'year' in md: tags["TDRC"] = TDRC(encoding=3, text=md.year) for key, value in md.items(): whitespace = ' ' * (10 - len(key)) log(' '+key+':'+whitespace+pformat(value)) tags.save(filename)PK!H;A%&%vidl-3.0.2.dist-info/entry_points.txtN+I/N.,()*LɱzVy\\PK!HW"TTvidl-3.0.2.dist-info/WHEEL A н#J."jm)Afb~ ڡ5 G7hiޅF4+-3ڦ/̖?XPK!H+@ Mvidl-3.0.2.dist-info/METADATAXms6_85#QWqq퉓x,';'DPBL<,Rk~8$bwx]aj[^[ȼL^f5b+7׊٩cN\/UyN˄&&,[J7g+ݸf"Pz+1 Fv4::S,޾ݯob&VIZX9MNxfFErH0aӌS]%7⟍4ŽFA?:LӒ[+ )U%Ռ]q5k>uʧ_⛯^Wn3i݈Mu{A}h/E|z['zE/ҽ\zP\88BkPދw= Oxp nW5g7HI4c2:VΔ [YFWRg!»v-e;9%j"rܼ& PdU}89CMR%yΪQ:H1Y0[VF) JGb9wp96 BycY8jj1ur!Uv p ecG6Y`$4} NAg1keWkm,ZH[p\5\Q 霕Z?XV3ge?Qp {v޳#q A6H͟Hp 2Lٙ(xFoS2tsVoXݳ[J[딄 6L# ,$jYi!PZ%Vd$Cy= ["tcIN | +ct?E( w~k6e#y}^lߝ!?&lnzM@#"-Q :bSKwՠtK6 T8>v[Jk{` BC ?Z ;GR`|\ C\ A;V:ֹ4Tc٩5x, *ŻN_'y]TN`tcV,G%)۫ QiɥoYʌ `u]Aڇ-5mME.,,E.=JJMKMϳ+91h3 (IapKw7{$(ZmQp׾ mZGX @vR=|K}# {r#JuI'kh܁XrG!>煮wZyQz>vM“NNc5r2ʬ:{ _3TfLC̘:~rB+k c⅝ QsZz͇J URtY]mߢЃ |#"/G1B1&mA 1hzqv-2R/6<XBVγv"%->e'FȵTv#fMn/*ndxE0QiT>eHkD]^dEi &azJ-kxߔ9UOL%(P2y:{n3ÐiL>Uk-Yk pJQe 3ՎaY~f&TRV&ۘX;#Tf3j2 ߈C~Psׇ}GFB +4H)ZF5bS'o4"^R)DKagb%i-@){!Op &4jgGa EŹaA_gâ:ukJ=( \#73M@GLӇ-gnGfCRh-!ӫKߴEEU+?U|u4&9M݈kmά\ 0խ?y-]C\W }ɢ"Voُa@ c_kپ/>c~{<mn[[Ta ?{¢\"v~DO'uP:r$PK!Hvidl-3.0.2.dist-info/RECORDmn@}aD,lCec6 |9t8#qkxތ\{MYysYm<V k1@s=*/Lvl$ABuL*7Z$6} 9Ey0I@ɵXejJp(A{oãoyWLxEPFJy *+m"ks:)4Ρ_y?(9M: DBGϺ3h}釩QrLF~MWȨgFiXEnb*u0(Q7>U:zYQ_; D\ ܲv&sapKncP\vԻ n?9zIAdH*ctMc'X3:oT8=ϧ]ZC7I.OsܙT;`1!'r8*( 'As-9PK!L@g66vidl/__init__.pyPK! /BBdvidl/__main__.pyPK!E?v[[ vidl/app.pyPK!(wwwXvidl/config.jsonPK!0vidl/config.pyPK!E:GG ? vidl/dl.pyPK!}8ff 'vidl/md.pyPK!H;A%&%<,vidl-3.0.2.dist-info/entry_points.txtPK!HW"TT,vidl-3.0.2.dist-info/WHEELPK!H+@ M0-vidl-3.0.2.dist-info/METADATAPK!Hz7vidl-3.0.2.dist-info/RECORDPK 9