Advertisement
thituto

Untitled

Feb 28th, 2017
156
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 72.97 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3.  
  4. #### User Configurations ####
  5.  
  6. ## Fill yours - This is again REQUIRED by the LTV website.
  7. ltv_username = xxx
  8. ltv_password = xxx
  9.  
  10. # Folder to scan when no arguments are passed
  11. default_folder = '.'
  12.  
  13. # Ordered, from: pt, br, en
  14. preferred_languages = ['br']
  15. # Rename downloaded subtitles to the same name of the video file, and append language code
  16. rename_subtitle = True
  17. append_language = False
  18. # Download one subtitle file for each of the prefered languages
  19. download_each_lang = False
  20. # Remove old subtitle languages when a prefered becomes available
  21. clean_old_language = True
  22.  
  23. # Append a confidence/quality number to then end of the subtitle file. Allows "upgrading" with the same language
  24. # Most players ignore this last number and correctly identify the srt file. If not, make this False
  25. append_confidence = False
  26.  
  27. # Stop if #-Lang is already present: 1-PT, 2-PT/BR, 3-EN/PT/BR etc
  28. stopSearchWhenExistsLang = 1
  29.  
  30. # Keeps a subtitle with the same name of the video (hard)linking to the best available subtitle.
  31. # Occupies no space, but only useful for some old playeres that don't support language codes in subtitle files
  32. hardlink_without_lang_to_best_sub = False
  33.  
  34. # Set this to 80 or 90 if you just want to download the best languague and subtitle
  35. confidence_threshold = 50
  36.  
  37. # Recursivity also becomes active after a '-r' argument
  38. recursive_folders = True
  39.  
  40. # Append or update IMDB rating at the end of movie folders
  41. # Folders must have the movie name followed by the year inside parenthesis, otherwise they are ignored
  42. # eg: "Milk (2008)" becomes: "Milk (2008) [7.7]"
  43. append_iMDBRating = False
  44.  
  45. # Rename and clean videos and accompanying files from this garbage-tags
  46. fix_ETTV_subfolder = False
  47.  
  48. # Rename and clean videos and accompanying files from this garbage-tags
  49. clean_original_filename = False
  50. clean_name_from = ['VTV','www.torentz.3xforum.ro','MyTV','rarbg','eztv','ettv']
  51.  
  52.  
  53. Debug = 0
  54.  
  55. ####### End of regular user configurations #######
  56.  
  57. ## Set this flag using -f as parameter, to force search and replace all subtitles.
  58. ## This option is implied when only one argument is passed (single file dragged & dropped)
  59. ForceSearch=False
  60. OnlyIMDBRating = False
  61.  
  62. ## LegendasTV timeout and number of threads to use. Increasing them too high may affect the website performance, please be careful
  63. ltv_timeout = 15
  64. thread_count = 5
  65.  
  66. #### Known Arrays
  67.  
  68. # No need to change those, but feel free to add/remove some
  69. valid_subtitle_extensions = ['srt','txt','aas','ssa','sub','smi']
  70. valid_video_extensions = ['avi','mkv','wmv','mov','mpg','mpeg','3gp','flv']
  71. valid_extension_modifiers = ['!ut','part','rar','zip']
  72.  
  73. known_release_groups = ['LOL','killers','ASAP','dimension','ETRG','fum','ift','2HD','FoV','FQM','DONE','vision','fleet'
  74. ,'Yify','MrLss','fever','p0w4','TLA','refill','notv','reward','bia','maxspeed','FiHTV','BATV','SickBeard','sfm']
  75.  
  76. # garbage is ignored from filenames
  77. garbage = ['Unrated', 'DC', 'Dual', 'VTV', 'esubs', 'eng', 'subbed', 'artsubs', 'sample', 'ExtraTorrentRG', 'StyLish', 'Release', 'Internal', '2CH', 'mp4' ]
  78.  
  79. # undesired wordslowers the confidence weight if detected
  80. undesired = ['.HI.', '.Impaired.', '.Comentários.', '.Comentarios.' ]
  81.  
  82. # video_quality, video_size and release_groups should agree between movie file and subtitles, otherwise weight is reduced
  83. video_quality = ['HDTV', 'PDTV', 'XviD', 'DivX', 'x264', 'aac', 'dd51', 'webdl', 'webrip', 'BluRay', 'blueray', 'BRip', 'BRRip', 'BDRip', 'DVDrip', 'DVD', 'AC3', 'DTS', 'TS', 'R5', 'R6', 'DVDScr', 'PROPER', 'REPACK' ]
  84. video_size = ['480', '540', '720', '1080']                              
  85.    
  86.  
  87. ####### Dragons ahead !! #######
  88.  
  89. Done = False
  90.  
  91.  
  92. import os, sys, traceback
  93. import json, re
  94. import shutil, stat, glob, filecmp, tempfile
  95. import signal, platform
  96. import threading, queue, time, random
  97.  
  98. from zipfile import ZipFile
  99.  
  100. if(platform.system().lower().find("windows") > -1):
  101.     if Debug > 2:
  102.         print('Windows system detected')
  103.     import msvcrt
  104.     getch = msvcrt.getch
  105.  
  106.     def winHardLink(source, link_name):
  107.         import ctypes
  108.         ch1 = ctypes.windll.kernel32.CreateHardLinkW
  109.         ch1.argtypes = (ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32)
  110.         ch1.restype = ctypes.c_ubyte
  111.         if not ch1(link_name, source, 0):
  112.             raise ctypes.WinError()
  113.     os.link = winHardLink
  114.    
  115.     def winSymLink(source, link_name):
  116.         import ctypes
  117.         csl = ctypes.windll.kernel32.CreateSymbolicLinkW
  118.         csl.argtypes = (ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32)
  119.         csl.restype = ctypes.c_ubyte
  120.         flags = 0
  121.         if source is not None and os.path.isdir(source):
  122.             flags = 1
  123.         if not csl(link_name, source, flags):
  124.             raise ctypes.WinError()
  125.     os.symlink = winSymLink
  126. else:
  127.     if Debug > 2:
  128.         print('Unix system detected')
  129.     import sys, tty
  130.    
  131.     fd = sys.stdin.fileno()
  132.     tty.setraw(sys.stdin.fileno())
  133.     # getch = sys.stdin.read(1)
  134.  
  135.  
  136. REQUIREMENTS = [ 'requests' , 'beautifulsoup4', 'rarfile' ]
  137.  
  138. try:
  139.     import requests
  140.     from bs4 import BeautifulSoup
  141.     from rarfile import RarFile
  142. except (Exception) as e:
  143.     print('! Missing requirements. '+str(type(e)))
  144.     import os, pip
  145.     pip_args = [ ]
  146.     # pip_args = [ '-vvv' ]
  147.     if 'http_proxy' in os.environ:
  148.         proxy = os.environ['http_proxy']
  149.         if proxy:
  150.             pip_args.append('--proxy')
  151.             pip_args.append(proxy)
  152.     pip_args.append('install')
  153.     for req in REQUIREMENTS:
  154.         pip_args.append( req )
  155.     print('Installing: ' + str(REQUIREMENTS))
  156.     pip.main(pip_args)
  157.     # pip.main(initial_args = pip_args)
  158.  
  159.     # do it again
  160.     try:
  161.         import requests
  162.         from bs4 import BeautifulSoup
  163.         from rarfile import RarFile
  164.         print('Sucessfully installed the required libraries\n')
  165.     except (Exception) as e:
  166.         print('\nPython modules needed: beautifulsoup4, rarfile, requests')
  167.         print('We failled to install them automatically: '+str(type(e)))
  168.         print('! Traceback:')
  169.         traceback.print_exc(file=sys.stdout)
  170.         print()
  171.         print('\nTry running this with Admin Priviliges, or')
  172.         print('Run in a command prompt Admin Priviliges:\n')
  173.         print('pip install requests beautifulsoup4 rarfile')
  174.         print('\nPress any key to exit...')
  175.         if Debug > -1:
  176.             junk = getch()
  177.         sys.exit()
  178.  
  179.  
  180.  
  181. def signal_handler(signal, frame):
  182.     global videosQ, Done
  183.     Done=True
  184.     videosQ.queue.clear()
  185.     print('Cleared List. Terminating in 5s')
  186.     time.sleep(5)
  187.     sys.exit()
  188. signal.signal(signal.SIGINT, signal_handler)
  189.  
  190.  
  191.  
  192. lock = threading.Lock()
  193. local = threading.local()
  194. local.output = ''
  195. local.wanted_languages = []
  196.  
  197.  
  198.  
  199.  
  200. if ltv_username is "USERNAME":
  201.     print('\nPlease edit ltv-downloader.py file and configure with your LTV\'s Username and Password...')
  202.     junk = getch()
  203.     sys.exit()
  204.  
  205.  
  206. def SameFile(file1, file2):
  207.     try:
  208.         return filecmp.cmp(file1, file2)
  209.         # return os.stat(file1) == os.stat(file2)
  210.     except:
  211.         return False
  212. os.path.samefile = SameFile
  213.  
  214. def UpdateFile(src, dst):
  215.     if src == dst:
  216.         return True
  217.     exc = ""
  218.     for x in [1, 2, 3]:
  219.         try:
  220.             if not os.path.isfile(src):
  221.                 return False
  222.            
  223.             if not os.path.isfile(dst):
  224.                 os.rename(src, dst)
  225.                 return True
  226.            
  227.             if os.path.samefile(src, dst):
  228.                 os.remove(src)
  229.                 return True
  230.            
  231.             if os.path.getsize(src) < 1500 and os.path.getsize(dst) >= 1500:
  232.                 os.remove(src)
  233.                 return True
  234.                
  235.             if os.path.getsize(dst) < 1500 and os.path.getsize(src) >= 1500:
  236.                 os.remove(dst)
  237.                 os.rename(src, dst)
  238.                 return True
  239.                
  240.             if os.path.getmtime(src) < os.path.getmtime(dst):
  241.                 os.remove(src)
  242.                 return True
  243.                
  244.             if os.path.getmtime(dst) < os.path.getmtime(src):
  245.                 os.remove(dst)
  246.                 os.rename(src, dst)
  247.                 return True
  248.            
  249.             if os.path.getsize(src) < os.path.getsize(dst):
  250.                 os.remove(src)
  251.                 return True
  252.                
  253.             if os.path.getsize(dst) < os.path.getsize(src):
  254.                 os.remove(dst)
  255.                 os.rename(src, dst)
  256.                 return True
  257.            
  258.             os.remove(dst)
  259.             os.rename(src, dst)
  260.             return True
  261.            
  262.         except (Exception) as e:
  263.             exc = e
  264.             time.sleep(0.5)
  265.             pass
  266.    
  267.     print('\nSomething went wrong renaming files: '+str(type(exc))+'\n'+src+'\nto:\n'+dst)
  268.     return False
  269.  
  270. def stringify(input):
  271.     if isinstance(input, dict):
  272.         return {stringify(key):stringify(value) for key,value in input.items()}
  273.     elif isinstance(input, list):
  274.         return [stringify(element) for element in input]
  275.     elif isinstance(input, str):
  276.         return input.encode('ascii', 'replace').decode('utf8')
  277.     else:
  278.         return input
  279.  
  280.  
  281. ## Takes car of everything related to the Website
  282. class LegendasTV:
  283.    
  284.     def __init__(self, ltv_username, ltv_password, download_dir=None):
  285.         if not download_dir:
  286.             download_dir = tempfile.gettempdir()
  287.  
  288.         self.download_path = os.path.abspath(download_dir)
  289.         self.base_url = 'http://legendas.tv'
  290.         self.username = ltv_username
  291.         self.password = ltv_password
  292.        
  293.         self.login_url = self.base_url+'/login'
  294.         self.logout_url = self.base_url+'/users/logout'
  295.         #self.searh_url = self.base_url+'/busca/'
  296.         self.searh_url = self.base_url+'/util/carrega_legendas_busca/'
  297.         self.download_url = self.base_url+'/downloadarquivo/'
  298.        
  299.         self.session = requests.Session()
  300.         self.session.auth = (ltv_username, ltv_password)
  301.         self.session.headers.update({'User-Agent': 'LegendasTV-Downloader at GitHub'})
  302.         self.session.mount("http://", requests.adapters.HTTPAdapter(max_retries=3))
  303.        
  304.     ## Login in legendas.tv
  305.     def login(self):
  306.        
  307.         login_data= {'data[User][username]':self.username,'data[User][password]':self.password, '_method':'POST'}
  308.        
  309.         try:
  310.             r = self.session.post(self.login_url, data=login_data, timeout=ltv_timeout)
  311.             r.raise_for_status()
  312.         except (Exception) as e:
  313.             if Debug > -1:
  314.                 print('! Error, loging in! '+str(type(e)))
  315.             return False
  316.        
  317.         if "Usuário ou senha inválidos" in r.text:
  318.             if Debug > -1:
  319.                 print('! Error, wrong login user/pass!')
  320.             return False
  321.         return True
  322.  
  323.     ## Logout
  324.     def logout(self):
  325.         try:
  326.             r = self.session.get(self.logout_url, timeout=ltv_timeout)
  327.             r.raise_for_status()
  328.         except (Exception) as e:
  329.             if Debug > -1:
  330.                 print('! Error, loging out! '+str(type(e)))
  331.             return False
  332.         return True
  333.  
  334.     ## Search and select best subtitle
  335.     def search(self, originalShow):
  336.        
  337.         if Debug > 2:
  338.             local.output+='------- Searching -------\n'
  339.         if Debug > 2:
  340.             local.output+='ShowName='+str(originalShow['ShowName'])+'\n'
  341.             local.output+='Year='+str(originalShow['Year'])+'\n'
  342.             local.output+='Season='+str(originalShow['Season'])+'\n'
  343.             local.output+='Episode='+str(originalShow['Episode'])+'\n'
  344.             local.output+='Group='+str(originalShow['Group'])+'\n'
  345.             local.output+='Quality='+str(originalShow['Quality'])+'\n'
  346.             local.output+='Size='+str(originalShow['Size'])+'\n'
  347.             local.output+='Undesired='+str(originalShow['Undesired'])+'\n'
  348.             local.output+='Unknown='+str(originalShow['Unknown'])+'\n'
  349.             local.output+='\n'
  350.        
  351.         list_possibilities = []
  352.  
  353.         for iTry in 1,2,3:
  354.             if len(list_possibilities) > 0:
  355.                 break
  356.             vsearch_array = []
  357.  
  358.             if originalShow['Season'] and originalShow['Episode']:
  359.                 if iTry == 1:
  360.                     if len(originalShow['Episode'])>1:
  361.                         vsearch_array.append(' '.join(originalShow['ShowName'])+' '+"S{:02d}E".format(originalShow['Season'][0]) + "E".join('{:02d}'.format(a) for a in originalShow['Episode']))
  362.                     vsearch_array.append(' '.join(originalShow['ShowName'])+' '+"S{:02d}E{:02d}".format(originalShow['Season'][0], originalShow['Episode'][0]))
  363.                
  364.                 if iTry == 2:
  365.                     if len(originalShow['Episode'])>1:
  366.                         vsearch_array.append(' '.join(originalShow['ShowName'])+' '+"{:0d}x".format(originalShow['Season'][0]) + "x".join('{:02d}'.format(a) for a in originalShow['Episode']))
  367.                     vsearch_array.append(' '.join(originalShow['ShowName'])+' '+"{:0d}x{:02d}".format(originalShow['Season'][0], originalShow['Episode'][0]))
  368.  
  369.                 if iTry == 3:
  370.                     vsearch_array.append(' '.join(originalShow['ShowName'])+' '+"{:0d}{:02d}".format(originalShow['Season'][0], originalShow['Episode'][0]))
  371.                     ##vsearch_array.append(' '.join(originalShow['ShowName'])+' '+"{:0d} {:02d}".format(originalShow['Season'][0], originalShow['Episode'][0]))
  372.                
  373.             else:
  374.                 if iTry == 1:
  375.                     if originalShow['Group'] and originalShow['Year']:
  376.                         vsearch_array.append(' '.join(originalShow['ShowName'])+' '+originalShow['Group'][0]+' '+originalShow['Year'][0])
  377.                    
  378.                 if iTry == 2:
  379.                     if originalShow['Year']:
  380.                         vsearch_array.append(' '.join(originalShow['ShowName'])+' '+originalShow['Year'][0])
  381.                        
  382.                     if originalShow['Group']:
  383.                         vsearch_array.append(' '.join(originalShow['ShowName'])+' '+originalShow['Group'][0])
  384.                    
  385.                 if iTry == 3:
  386.                     vsearch_array.append(' '.join(originalShow['ShowName']))
  387.  
  388.  
  389.             ## Search 6 pages and build a list of possibilities
  390.             for vsearch in vsearch_array:
  391.                
  392.                 # vsearch = urllib.parse.quote(vsearch)
  393.                 for vsearch_prefix in ['/-/-', '/-/-/2', '/-/-/3', '/-/-/4', '/-/-/5', '/-/-/6']:
  394.                     newPossibilities = 0
  395.                    
  396.                     if Debug < 2:
  397.                         local.output+='. '
  398.                     else:
  399.                         local.output+="\nSearching for subtitles with: "+vsearch+" , "+vsearch_prefix+'\n'
  400.                    
  401.                     url = self.searh_url + vsearch + vsearch_prefix
  402.                     try:
  403.                         r = self.session.get(url, timeout=ltv_timeout)
  404.                         r.raise_for_status()
  405.                     except (Exception) as e:
  406.                         if Debug > -1:
  407.                             local.output+='! Error Searching 3 times! '+str(type(e))+'\n'
  408.                             local.output+=url+'\n'
  409.                         with lock:
  410.                             statistics['Failed'] += 1
  411.                         return False
  412.                        
  413.                     soup = BeautifulSoup(r.text, "html.parser")
  414.  
  415.                     div_results = soup.find('div',{'class':'gallery clearfix list_element'})
  416.                     if div_results:
  417.                         div_results = div_results.findAll('article',recursive=False)
  418.                     if not div_results:
  419.                         if Debug > 2:
  420.                             local.output+='No results\n'
  421.                         break
  422.                    
  423.                     for span_article in div_results:
  424.                         span_results = span_article.findAll('div',recursive=False)
  425.  
  426.                         if not span_results:
  427.                             if Debug > 2:
  428.                                 local.output+='No results\n'
  429.                             continue
  430.  
  431.                         for span in span_results:
  432.  
  433.                             try:
  434.                                 td = span.find('a').get('href')
  435.                                 subName = span.find('a').contents[0]
  436.  
  437.                                 flag = span.find('img').get('src')
  438.                             except:
  439.                                 if Debug > 1:
  440.                                     local.output+="! Error parsing result list: "+span.prettify()+'\n'
  441.                                 continue
  442.  
  443.                             if not td:
  444.                                 if Debug > 2:
  445.                                     local.output+='#### Something went wrong ####\n'
  446.                                 continue
  447.                            
  448.                             # Parse the link
  449.                             tmpregex = re.search('/download/([^/\\\]+)/([^/\\\]+)/([^/\\\]+)',td)
  450.  
  451.                             if not tmpregex or tmpregex.lastindex<3:
  452.                                 local.output+='#### Error parsing link:'+td+' ####\n'
  453.                                 continue
  454.                                
  455.                             # Get the download ID
  456.                             download_id = tmpregex.group(1)
  457.                             release = tmpregex.group(3)
  458.  
  459.                             if not download_id or not release:
  460.                                 if Debug > 2:
  461.                                     local.output+='Couldn\'t get download_id and Release\n'
  462.                                 continue
  463.                            
  464.                             if download_id in [x['id'] for x in list_possibilities]:
  465.                                 ## Already listed this
  466.                                 continue
  467.                            
  468.                             ## Get the language
  469.                             tmpregex = re.search('/[a-zA-Z0-9]*/(?:icon|flag)_([a-zA-Z0-9]+)\.(gif|jpg|jpeg|png)',flag)
  470.                            
  471.                             if not tmpregex or tmpregex.lastindex<2:
  472.                                 local.output+='#### Error parsing flag: '+flag+' ####\n'
  473.                                 continue
  474.                             language = tmpregex.group(1)
  475.                            
  476.                            
  477.                             possibility = {}
  478.                             possibility.clear()
  479.                            
  480.                             newPossibilities += 1
  481.                            
  482.                             possibility['%'] = 100
  483.  
  484.                             possibility['id'] = download_id
  485.                            
  486.                             possibility['release'] = release.lower()
  487.                            
  488.                             possibility['sub_name'] = subName.lower()
  489.                            
  490.                             if 'pt' in language:
  491.                                 possibility['language'] = 'pt'
  492.                             elif 'braz' in language:
  493.                                 possibility['language'] = 'br'
  494.                             elif 'usa' in language:
  495.                                 possibility['language'] = 'en'
  496.                             else:
  497.                                 if Debug > 2:
  498.                                     local.output+='Couldn\'t get Language\n'
  499.                                 continue
  500.                            
  501.                             # Filter wanted_languages
  502.                             if possibility['language'] not in preferred_languages:
  503.                                 if Debug > 2:
  504.                                     local.output+='0!!, Wrong language: '+possibility['language']+', from: '+str(preferred_languages)+'\n'
  505.                                 continue
  506.                                
  507.                             #downloads = td.contents[5]
  508.                             #possibility['downloads'] = downloads.lower()
  509.                            
  510.                             #comments = td.contents[7]
  511.                             #possibility['comments'] = comments.lower()
  512.                            
  513.                             #rating = td.contents[8].contents[1]
  514.                             #possibility['rating'] = rating.lower()
  515.                            
  516.                             #uploader = td.parent.find('a').contents[0]
  517.                             #possibility['uploader'] = uploader
  518.                            
  519.                             #date = span.findAll('td')[2].contents[0]
  520.                             #possibility['date'] = date.lower()
  521.                            
  522.                             if Debug > 2:
  523.                                 local.output+='\nFOUND!: '+possibility['language']+' - '+possibility['release']+'\n'
  524.                            
  525.                            
  526.                             releaseShow = parseFileName(possibility['release'])
  527.                            
  528.                             subnameShow = parseFileName(possibility['sub_name'])
  529.                            
  530.                             releaseShow['ShowName'] = list(set(releaseShow['ShowName'] + subnameShow['ShowName']))
  531.                             releaseShow['Year'] = list(set(releaseShow['Year'] + subnameShow['Year']))
  532.                             releaseShow['Season'] = list(set(releaseShow['Season'] + subnameShow['Season']))
  533.                             releaseShow['Episode'] = list(set(releaseShow['Episode'] + subnameShow['Episode']))
  534.                             releaseShow['Group'] = list(set(releaseShow['Group'] + subnameShow['Group']))
  535.                             releaseShow['Quality'] = list(set(releaseShow['Quality'] + subnameShow['Quality']))
  536.                             releaseShow['Size'] = list(set(releaseShow['Size'] + subnameShow['Size']))
  537.                             releaseShow['Undesired'] = list(set(releaseShow['Undesired'] + subnameShow['Undesired']))
  538.                             releaseShow['Unknown'] = list(set(releaseShow['Unknown'] + subnameShow['Unknown']))
  539.                            
  540.                             possibility['%'] = calculateSimilarity(originalShow, releaseShow)
  541.                            
  542.                             if not download_each_lang:
  543.                                 langindex = preferred_languages.index(possibility['language'])
  544.                                 if Debug > 2:
  545.                                     local.output+='-'+str(langindex*21)+', Language '+possibility['language']+' at pos '+str(langindex)+'\n'
  546.                                 possibility['%'] -= 21*langindex
  547.                            
  548.                             list_possibilities.append(possibility)
  549.  
  550.                     if Debug > 2:
  551.                         local.output+='Got results: '+str(newPossibilities)+'\n'
  552.  
  553.                     ## If this result page was not full, don't read the next one
  554.                     if newPossibilities < 20:
  555.                         break
  556.  
  557.         if not list_possibilities:
  558.             if Debug > 2:
  559.                 local.output+='No subtitles found\n'
  560.             with lock:
  561.                 statistics['NoSubs'] += 1
  562.             return False
  563.  
  564.         if Debug > 2:
  565.             local.output+='------------------\n'
  566.         final_list = sorted(list_possibilities, key=lambda k: k['%'], reverse=True)
  567.        
  568.         for idx, possibility in enumerate(final_list):
  569.             if Debug > 1:
  570.                 local.output+='Chance '+str(idx)+', '+str(possibility['%'])+'%, '+possibility['language']+', '+possibility['release'] + ' | ' + possibility['sub_name'] +'\n'
  571.        
  572.         if final_list[0]['language'] not in local.wanted_languages:
  573.             if Debug > 2:
  574.                 local.output+='\n-- Best subtitle already present --\n\n'
  575.             with lock:
  576.                 statistics['NoBest'] += 1
  577.             return False
  578.        
  579.         return final_list[0]
  580.  
  581.     ## Downloads a subtitle given it's ID
  582.     def download(self, subtitle):
  583.        
  584.         download_id = subtitle['id']
  585.         if download_id:
  586.             url_request = self.download_url+download_id
  587.             if Debug == 0:
  588.                 local.output+='Download'
  589.             if Debug > 2:
  590.                 local.output+='\n------- Downloading -------\n'
  591.                 local.output+='Downloading '+subtitle['language']+', '+subtitle['release']+'\n'
  592.            
  593.             try:
  594.                 r = self.session.get(url_request, timeout=ltv_timeout*4)
  595.                
  596.                 # print("\nurl:\n"+str(r.url))
  597.                 # print("\nrequested headers:\n"+str(r.request.headers))
  598.                 # print("\nheaders:\n"+str(r.headers))
  599.                 # print("\ncookies:\n"+str(r.cookies))
  600.                
  601.                 r.raise_for_status()
  602.             except (Exception) as e:
  603.                 if Debug > 1:
  604.                     local.output+='! Error downloading! '+str(type(e))+'\n'
  605.                 return False
  606.            
  607.             legenda = r.content
  608.            
  609.             localName = ""
  610.             if 'Content-Disposition' in r.headers and "filename=" in r.headers['Content-Disposition']:
  611.                 # If the response has Content-Disposition, we take file name from it
  612.                 localName = r.headers['Content-Disposition'].split('filename=')[1]
  613.                 if localName[0] == '"' or localName[0] == "'":
  614.                     localName = localName[1:-1]
  615.            
  616.             if len(localName)>4:
  617.                 self.archivename= os.path.join(self.download_path, str(localName))
  618.             else:
  619.                 self.archivename = os.path.join(self.download_path, str(download_id))
  620.            
  621.             if r.url.endswith('.rar') or ('Content-Type' in r.headers and 'rar' in r.headers['Content-Type']):
  622.                 self.archivename += '.rar'
  623.             elif r.url.endswith('.zip') or ('Content-Type' in r.headers and 'zip' in r.headers['Content-Type']):
  624.                 self.archivename += '.zip'
  625.             elif r.url.endswith('.srt') or ('Content-Type' in r.headers and 'srt' in r.headers['Content-Type']):
  626.                 if Debug > -1:
  627.                     local.output+='Downloaded an .SRT. Are you logged in?\n'
  628.                 return False
  629.             else:
  630.                 if Debug > 2:
  631.                     local.output+='No download MIME TYPE. Not forcing extension\n'
  632.             if Debug > 2:
  633.                 local.output+=' Downloaded :'+self.archivename+'\n'
  634.  
  635.             f = open(self.archivename, 'wb')
  636.             f.write(legenda)
  637.             #pickle.dump(legenda, f)
  638.             f.close()
  639.             if Debug > 2:
  640.                 local.output+='Subtitle downloaded with sucess!\n'
  641.             return True
  642.  
  643.     ## Choose the likeliest and extracts it
  644.     def extract_sub(self, dirpath, originalFilename, originalShow, language):
  645.         global lock
  646.                
  647.         if Debug > 2:
  648.             local.output+='\n------- Extracting -------\n'
  649.         if Debug > 3:
  650.             local.output+='File: '+self.archivename+'\n'
  651.         if Debug > 2:
  652.             local.output+="Extracting a "
  653.         try:
  654.             archive = ZipFile(self.archivename)
  655.             if Debug > 2:
  656.                 local.output+='zip file...\n'
  657.         except:
  658.             try:
  659.                 archive = RarFile(self.archivename)
  660.                 if Debug > 2:
  661.                     local.output+='rar file...\n'
  662.             except:
  663.                 if Debug > -1:
  664.                     local.output+='! Error, Error opening archive: '+self.archivename+'\n'
  665.                     local.output+='UNRAR must be available on console\n'
  666.                 return False
  667.  
  668.         language_compensation = 0
  669.         if not download_each_lang:
  670.             langindex = -1
  671.             langindex = local.wanted_languages.index(language)
  672.             if langindex>=0:
  673.                 language_compensation = 21*langindex
  674.             else:
  675.                 local.output+='No language? '+language+'\n'
  676.  
  677.         files = archive.infolist()
  678.            
  679.         srts = []
  680.         current_maxpoints = 0
  681.         current_maxfile = []
  682.  
  683.         for srtname in files:
  684.            
  685.             testname = srtname.filename.lower()
  686.             testname = os.path.basename(str(testname))
  687.            
  688.             if not testname.endswith(tuple(valid_subtitle_extensions)+('rar', 'zip')):
  689.                 if Debug > 2:
  690.                     local.output+='Non Sub file: ' + str(srtname)+'\n'
  691.                 continue
  692.            
  693.             if Debug > 2:
  694.                 local.output+='\n--- Analyzing: '+str(testname)+'\n'
  695.            
  696.             compressedShow = parseFileName(testname)
  697.            
  698.             points = calculateSimilarity(originalShow, compressedShow)
  699.            
  700.             points = points - language_compensation
  701.            
  702.             if Debug > 2:
  703.                 local.output+='Adding subtitle file with '+str(points)+'% : '+str(testname)+'\n'
  704.            
  705.             if current_maxpoints<points:
  706.                 current_maxpoints = points
  707.                 current_maxfile = srtname
  708.  
  709.         if Debug > 2:
  710.             local.output+='-------\n'
  711.  
  712.         if not current_maxfile or current_maxpoints<1:
  713.             if Debug > -1:
  714.                 local.output+='! Error: No valid subs found on archive\n'
  715.             with lock:
  716.                 statistics['Failed'] += 1
  717.             return False
  718.  
  719.         extract = []
  720.        
  721.         extract.append(current_maxfile)
  722.  
  723.         # maximum=confidence_threshold
  724.         # for idx, [p, n] in enumerate(srts):
  725.         #     print "Result %d, %d%%: %s" % (idx, p, n.filename)
  726.         #     if p >= maximum:
  727.         #         maximum = p
  728.         #         extract.append(n)
  729.            
  730.         ## Extracting
  731.         for fileinfo in extract:
  732.             fileinfo.filename = os.path.basename(fileinfo.filename)
  733.            
  734.             if Debug > 2:
  735.                 local.output+='Extracted '+fileinfo.filename+' with ' +str(current_maxpoints+language_compensation)+'%\n'
  736.  
  737.             if fileinfo.filename.endswith(('rar', 'zip')):
  738.                 if Debug > 2:
  739.                     local.output+='Recursive extract, RAR was inside: '+fileinfo.filename+'\n'
  740.                 archive.extract(fileinfo, self.download_path)
  741.                 self.archivename = os.path.join(self.download_path, fileinfo.filename)
  742.                 if not ltv.extract_sub(dirpath, originalFilename, group, size, quality, language):
  743.                     return False
  744.                 continue
  745.            
  746.             dest_filename = fileinfo.filename
  747.  
  748.             if len(extract) == 1 and rename_subtitle:
  749.                 dest_filename = os.path.splitext(originalFilename)[0] + os.path.splitext(dest_filename)[1]
  750.            
  751.             if append_language:
  752.                 dest_filename = os.path.splitext(dest_filename)[0]+'.'+language+os.path.splitext(dest_filename)[1]
  753.                
  754.             if append_confidence:
  755.                 dest_filename = os.path.splitext(dest_filename)[0]+'.'+str(current_maxpoints+language_compensation)+os.path.splitext(dest_filename)[1]
  756.            
  757.             if Debug > 2:
  758.                 local.output+='Extracting subtitle as: '+dest_filename+'\n'
  759.             dest_fullFilename = os.path.join(dirpath, dest_filename)
  760.            
  761.             try:              
  762.                 fileContents = archive.read(fileinfo)
  763.                
  764.                 f = open(dest_fullFilename, 'wb')
  765.                 f.write(fileContents)
  766.                 f.close()
  767.                
  768.                 if Debug > 2:
  769.                     local.output+='Subtitle saved with sucess in: '+dirpath+'!\n'
  770.                 with lock:
  771.                     statistics['DL'] += 1
  772.                     if not local.wanted_languages == preferred_languages:
  773.                         statistics['Upg'] += 1
  774.                     if language == local.wanted_languages[0]:
  775.                         statistics['Best'] += 1
  776.                     else:
  777.                         statistics['NoBest'] += 1
  778.                     if language == 'pt':
  779.                         statistics['PT'] += 1
  780.                     elif language == 'br':
  781.                         statistics['BR'] += 1
  782.                     elif language == 'en':
  783.                         statistics['EN'] += 1
  784.            
  785.             except (Exception):
  786.                 with lock:
  787.                     statistics['Failed'] += 1
  788.                 if Debug > -1:
  789.                     local.output+='! Error, decrompressing!\n'
  790.                 return False
  791.  
  792.             if clean_old_language:
  793.                 tmp = os.path.splitext(os.path.join(dirpath, originalFilename))[0] + '.??.s*'
  794.                 for tmp2 in glob.glob(re.sub(r'(?<!\[)\]', '[]]', re.sub(r'\[', '[[]', tmp))):
  795.                     if Debug > 2:
  796.                         local.output+='Found: '+tmp2+'\n'
  797.                     if os.path.samefile(dest_fullFilename, tmp2):
  798.                         continue
  799.                     if Debug > 2:
  800.                         local.output+='Deleted old language: '+os.path.basename(tmp2)+'\n'
  801.                     os.remove(tmp2)
  802.  
  803.             ## Create hard/SymLink with the same name as the video, for legacy players
  804.             if hardlink_without_lang_to_best_sub and ( not rename_subtitle or append_language):
  805.                 createLinkSameName(Folder=dirpath, Movie=originalFilename, Destination=dest_filename)
  806.  
  807.         return True
  808.        
  809. def moveMedia(src, dst):
  810.     dstFolder = os.path.dirname(dst)
  811.    
  812.     scrFileName = os.path.splitext(os.path.basename(src))[0]
  813.     dstFileName = os.path.splitext(os.path.basename(dst))[0]
  814.    
  815.     # Moving main video file
  816.     if UpdateFile(src, dst):
  817.         if Debug > 1:
  818.             local.output+='Moved ' + os.path.basename(src) + ' to: '+os.path.basename(dstFolder)+'\n'
  819.     else:
  820.         if Debug > 1:
  821.             local.output+='! Error renaming. File in use? '+filename+'\n'
  822.         return False
  823.    
  824.    
  825.     # Moving related subtitles
  826.     sub_pattern = re.sub(r'(?<!\[)\]', '[]]', re.sub(r'\[', '[[]', os.path.splitext(src)[0]+'.*'))
  827.     for tmpFile in glob.glob(sub_pattern):
  828.         if not os.path.splitext(tmpFile)[1][1:] in valid_subtitle_extensions:
  829.             if Debug > 2:
  830.                 local.output+='Not a valid extension: '+os.path.splitext(tmpFile)[1][1:]+'\n'
  831.             continue
  832.         if Debug > 1:
  833.             local.output+='File found to move: '+tmpFile+'\n'
  834.         newFile = os.path.basename(tmpFile).replace(scrFileName, dstFileName)
  835.         newFullPath = os.path.join(dstFolder, newFile)
  836.         if Debug > 1:
  837.             local.output+='Renaming to: '+newFile+'\n'
  838.        
  839.         if not UpdateFile(tmpFile, newFullPath):
  840.             if Debug > -1:
  841.                 local.output+='! Error recovering subtitle from ETTV folder! '+tmpFile+'\n'
  842.         else:
  843.             if Debug > -1:
  844.                 local.output+='Recovered 1 subtitle from ETTV folder: '+newFile+'\n'
  845.        
  846.     return True
  847.    
  848. def checkAndDeleteFolder(src):
  849.     # Search for subtitles or media files
  850.    
  851.     for files in os.listdir(src):
  852.         if Debug > 2:
  853.             local.output+='File found: '+files+' with ext: '+os.path.splitext(files)[1][1:]+'\n'
  854.         if os.path.splitext(files)[1][1:] in [x for x in valid_subtitle_extensions if x != 'txt']:
  855.             return False
  856.         if os.path.splitext(files)[1][1:] in valid_video_extensions:
  857.             return False
  858.         if os.path.splitext(files)[1][1:] in valid_extension_modifiers:
  859.             return False
  860.         # os.remove(os.path.join(src,files))
  861.    
  862.     if Debug > 1:
  863.         local.output+='Parent folder is empty. Removed!\n'
  864.        
  865.     def del_rw(action, name, exc):
  866.         os.chmod(name, stat.S_IWRITE)
  867.         os.remove(name)
  868.     shutil.rmtree(src, onerror=del_rw)
  869.     # os.rmdir(src)
  870.     return True
  871.    
  872. # Remove garbage from filenames
  873. def cleanAndRenameFile(Folder, filename):
  874.  
  875.     # Generate Regex
  876.     regex = '(' + '|'.join(clean_name_from)+')'
  877.  
  878.     if not re.search('[^a-zA-Z0-9]'+regex+'[^a-zA-Z0-9]', filename, re.I):
  879.         return filename
  880.    
  881.     statementClean = re.compile('[^a-zA-Z0-9]?[\[\(\{]?'+regex+'[\]\)\}]?', re.I)
  882.     newname = statementClean.sub('', filename)
  883.  
  884.     fullFilename = os.path.join(Folder, filename)
  885.     fullNewname = os.path.join(Folder, newname)
  886.  
  887.     # Sanity check
  888.     if fullFilename == fullNewname:
  889.         if Debug > 2:
  890.             local.output+='Error cleaning original name\n'
  891.         return filename
  892.  
  893.     # Cleaning video file
  894.     if UpdateFile(fullFilename, fullNewname):
  895.         if Debug > -1:
  896.             local.output+='Renamed to: '+newname+'\n'
  897.     else:
  898.         if Debug > 2:
  899.             local.output+='! Error renaming. File in use? '+filename+'\n'
  900.         return filename
  901.    
  902.     # Cleaning related subtitles and other files with different extensions
  903.     sub_pattern = re.sub(r'(?<!\[)\]', '[]]', re.sub(r'\[', '[[]', os.path.splitext(fullFilename)[0]+'.*'))
  904.     for tmpFile in glob.glob(sub_pattern):
  905.         tmpNew = statementClean.sub('', tmpFile)
  906.         if tmpNew != tmpFile:
  907.             if UpdateFile(tmpFile, tmpNew):
  908.                 if Debug > -1:
  909.                     local.output+='Renamed sub to: '+tmpNew+'\n'
  910.             else:
  911.                 if Debug > -1:
  912.                     local.output+='! Error renaming subtitles: '+tmpFile+'\n'
  913.        
  914.     return newname
  915.  
  916.  
  917. # Fix ETTV folders
  918. def cleanAndMoveFromSubfolder(origFolder, origFilename):
  919.     shouldMove = False
  920.    
  921.     regex = '(' + '|'.join(clean_name_from)+')'
  922.     statementClean = re.compile('[^a-zA-Z0-9]?[\[\(\{]?'+regex+'[\]\)\}]?', re.I)
  923.  
  924.     origAbsoluteFile = os.path.join(origFolder, origFilename)
  925.    
  926.     parentFolder = os.path.basename(origFolder)
  927.     grandParentFolder = os.path.dirname(origFolder)
  928.    
  929.     if not os.path.lexists(grandParentFolder):
  930.         return (origFolder, origFilename)
  931.    
  932.     cleanParentFolder = statementClean.sub('', parentFolder)
  933.     cleanFilename = statementClean.sub('', origFilename)
  934.     fileExt = os.path.splitext(cleanFilename)[1]
  935.    
  936.    
  937.     if cleanParentFolder == os.path.splitext(cleanFilename)[0]:
  938.         if moveMedia(origAbsoluteFile, os.path.join(grandParentFolder, cleanFilename)):
  939.             deleted = checkAndDeleteFolder(origFolder)
  940.             if Debug > -1:
  941.                 if deleted:
  942.                     local.output+='ETTV subfolder fixed: '+cleanFilename+'\n'
  943.                 else:
  944.                     local.output+='ETTV subfolder fixed, but not yet empty!: '+cleanFilename+'\n'
  945.             return (grandParentFolder, cleanFilename)
  946.         else:
  947.             if Debug > -1:
  948.                 local.output+='ETTV subfolder detected, but failed to fix\n'
  949.             return (origFolder, origFilename)
  950.    
  951.    
  952.     if re.match(".+[^a-zA-Z0-9]S\d\dE\d\d(E\d\d)?[^a-zA-Z0-9].+", cleanParentFolder):
  953.         if Debug > 1:
  954.             local.output+='Father has a TV Show name...'
  955.         try:
  956.             name=re.sub("(.+[^a-zA-Z0-9])S\d\dE\d\d(E\d\d)?[^a-zA-Z0-9].+", '\\1', cleanParentFolder)
  957.             season=int(re.sub(".+[^a-zA-Z0-9]S(\d\d)E\d\d(E\d\d)?[^a-zA-Z0-9].+", '\\1', cleanParentFolder))
  958.             episode=int(re.sub(".+[^a-zA-Z0-9]S\d\dE(\d\d)(E\d\d)?[^a-zA-Z0-9].+", '\\1', cleanParentFolder))
  959.         except (Exception) as e:
  960.             if Debug > -1:
  961.                 local.output+='Very strange error happened, parsing ETTV folder. Report to programmer please!\n'
  962.             return (origFolder, origFilename)
  963.            
  964.         if cleanFilename.startswith((name.lower()+"{:0d}{:02d}").format(int(season), int(episode))):
  965.             destFileName = cleanParentFolder+fileExt
  966.             if Debug > 1:
  967.                 local.output+='Son has the same!!\nMoving to: ' + os.path.join(os.path.basename(grandParentFolder), destFileName) + '\n'
  968.            
  969.             # return (origFolder, origFilename)
  970.             if moveMedia(origAbsoluteFile, os.path.join(grandParentFolder, destFileName)):
  971.                 deleted = checkAndDeleteFolder(origFolder)
  972.                 if Debug > -1:
  973.                     if deleted:
  974.                         local.output+='ETTV subfolder fixed\n'
  975.                     else:
  976.                         local.output+='ETTV subfolder fixed, but not yet empty!\n'
  977.                 return (grandParentFolder, destFileName)
  978.             else:
  979.                 if Debug > -1:
  980.                     local.output+='ETTV subfolder detected, but failed to fix\n'
  981.                 return (origFolder, origFilename)
  982.         else:
  983.             if Debug > 0:
  984.                 local.output+='ETTV Parent is different than Son\n'
  985.     else:
  986.         if Debug > 1:
  987.             local.output+='No ETTV subfolder detected, nothing to fix\n'
  988.     return (origFolder, origFilename)
  989.  
  990. # Create hardlink
  991. def createLinkSameName(Folder, Movie, Destination, HardLink=True):
  992.  
  993.     Movie = os.path.basename(Movie)
  994.     Destination = os.path.basename(Destination)
  995.     fullDestination = os.path.join(Folder, Destination)
  996.  
  997.     linkName = os.path.splitext(Movie)[0] + os.path.splitext(Destination)[1]
  998.     fullLinkName = os.path.join(Folder, linkName)
  999.    
  1000.     if os.path.samefile(fullDestination, fullLinkName):
  1001.         if Debug > 2:
  1002.             local.output+='Link without language already exists: \n  '+fullDestination+' = \n  '+fullLinkName+'\n'
  1003.         return
  1004.    
  1005.     try:
  1006.         os.remove(fullLinkName)
  1007.     except (Exception):
  1008.         #if Debug > 2:
  1009.         #    print 'Error: Couldn\'t remove %s' % (linkName)
  1010.         pass
  1011.  
  1012.     try:
  1013.         if HardLink:
  1014.             os.link(fullDestination, fullLinkName)
  1015.         else: # Relative path only when creating symbolic links
  1016.             os.symlink(Destination, fullLinkName)
  1017.  
  1018.         if Debug > 2:
  1019.             local.output+='Linked: '+linkName+' --> '+Destination+'\n'
  1020.     except (Exception):
  1021.         if Debug > 2:
  1022.             local.output+='! Error linking '+linkName+' --> '+Destination+'\n'
  1023.             local.output+='! print_exc():\n'
  1024.             traceback.print_exc(file=sys.stdout)
  1025.             print()
  1026.  
  1027.     return
  1028.  
  1029. def getAppendRating(fullpath, withYear=True, search=False, imdbID=0):
  1030.     global count, Debug
  1031.     fullFilename = os.path.abspath(fullpath)
  1032.     dirpath, foldername = os.path.split(fullFilename)
  1033.  
  1034.     changed = False
  1035.  
  1036.     tmpregex = re.search('([^\(\)\[\]]+)(?:\((\d{4})(?:\-\d{2,4})?\))\ ?(?:\[([\d\.]+)\])?',foldername)
  1037.  
  1038.     # Only process movie folder names with year
  1039.     if tmpregex is None or tmpregex.lastindex<2:
  1040.         if Debug>0:
  1041.             print("No movie folder: "+foldername)
  1042.         return fullFilename
  1043.  
  1044.     # if count>25:
  1045.     #     print('Too much iMDB-Ratings. Sleeping 2 minutes')
  1046.     #     time.sleep(110)
  1047.     # count+=1
  1048.        
  1049.     year = ''
  1050.     rating= ''
  1051.     # Get the download ID
  1052.     movie = tmpregex.group(1).strip()
  1053.     # if search:
  1054.     #     movie = movie.replace(" and ", " ")
  1055.     #     movie = movie.replace(" at ", " ")
  1056.        
  1057.     year = tmpregex.group(2).strip()
  1058.     if len(year) <= 1:
  1059.         withYear = False
  1060.  
  1061.     if tmpregex.lastindex>2:
  1062.         rating = tmpregex.group(3).strip()
  1063.  
  1064.     payload = {}          
  1065.            
  1066.     if imdbID:
  1067.         payload['i'] = imdbID
  1068.         # data = urllib.parse.urlencode({"i":imdbID})
  1069.        
  1070.     elif search:
  1071.         payload['s'] = movie
  1072.         if withYear:
  1073.             payload['y'] = year
  1074.     else:
  1075.         payload['t'] = movie
  1076.         if withYear:
  1077.             payload['y'] = year
  1078.            
  1079.     url = 'http://www.omdbapi.com'
  1080.    
  1081.  
  1082.     if Debug > 0:
  1083.         print('Searching for: '+url + ", " + str(payload))
  1084.        
  1085.     try:
  1086.        
  1087.         tmpsession = requests.Session()
  1088.         tmpsession.headers.update({'User-Agent': 'LegendasTV-Downloader at GitHub'})
  1089.         tmpsession.mount("http://", requests.adapters.HTTPAdapter(max_retries=3))
  1090.        
  1091.         r = tmpsession.get(url, params=payload, timeout=ltv_timeout*1.5)
  1092.        
  1093.         r.raise_for_status()
  1094.     except (Exception) as e:
  1095.         if Debug > 0:
  1096.             print('! Error getting imdb rating: '+str(type(e))+'')
  1097.         return fullpath
  1098.  
  1099.     the_page = r.text
  1100.    
  1101.     data = json.loads(the_page)
  1102.     data = stringify(data)
  1103.    
  1104.     if Debug > 0:
  1105.         print('Got imdb: '+str(data))
  1106.        
  1107.     if search:
  1108.         if 'Search' in data.keys():
  1109.             data["Search"] = [item for item in data["Search"] if item["Type"]=="movie"]
  1110.            
  1111.             if len(data["Search"])==1 and 'imdbID' in data["Search"][0].keys():
  1112.                 if Debug > 0:
  1113.                     print("Found the movie: " + data["Search"][0]["Title"])
  1114.                 return getAppendRating(fullpath, True, False, data["Search"][0]["imdbID"])
  1115.             else:
  1116.                 print("Multiple movies found with similar name: " + foldername)
  1117.                 return fullFilename
  1118.         elif withYear:
  1119.             if Debug > 0:
  1120.                 print("No movies found. Searching without year")
  1121.             return getAppendRating(fullpath, False, True, 0)
  1122.        
  1123.         print("No movie found while searching for: " + foldername)
  1124.         return fullFilename
  1125.        
  1126.    
  1127.     if not 'Year' in data.keys() or '/' in data["Year"]:
  1128.         if Debug > 0:
  1129.             print("No exact movie found. Searching")
  1130.         return getAppendRating(fullpath, True, True, 0)
  1131.         # if withYear:
  1132.         #     print("No rating found. Searching without year")
  1133.         #     return getAppendRating(fullpath, False)
  1134.         # print("No rating found for: " + foldername + ". The folder name must be wrong")
  1135.         # return fullFilename
  1136.  
  1137.     if year != data["Year"]:
  1138.         print("Year wrong in: " + movie + " " + year + ", found " + data["Year"])
  1139.         return getAppendRating(fullpath, True, True, 0)
  1140.         #year = data["Year"]
  1141.         #changed = True
  1142.  
  1143.     if 'imdbRating' in data.keys() and rating != data["imdbRating"] and not '/' in data["imdbRating"]:
  1144.         print("Rating changed for: " + movie + ", " + rating + " to " + data["imdbRating"])
  1145.         rating = data["imdbRating"]
  1146.         changed = True
  1147.  
  1148.     if changed:
  1149.         newName = movie
  1150.         if len(year) > 1:
  1151.             newName = newName + " ("+year+")"
  1152.         if len(rating) > 1:
  1153.             newName = newName + " ["+rating+"]"
  1154.  
  1155.         newFullPath = os.path.abspath(os.path.join(dirpath, newName))
  1156.  
  1157.         try:
  1158.             os.rename(fullFilename, newFullPath)
  1159.         except (Exception):
  1160.             pass
  1161.  
  1162.  
  1163.         if not os.path.isdir(newFullPath):
  1164.             if Debug > -1:
  1165.                 print("Error renaming imdb. File in use? " + newName)
  1166.             return fullFilename
  1167.         else:
  1168.             if Debug > 0:
  1169.                 print("Renamed with imdb rating: " + newName)
  1170.             return newFullPath
  1171.     else:
  1172.         print("Rating didn't change for: " + foldername)
  1173.     return fullFilename
  1174.  
  1175. # Normalize usual video tags for easier comparison
  1176. def normalizeTags(tag):
  1177.     tag = tag.lower()
  1178.     if tag in ['bluray', 'brrip', 'blueray', 'brip', 'bdrip']:
  1179.         return 'bluray'
  1180.     if tag in ['dvdrip', 'dvd', 'sd']:
  1181.         return 'dvd'
  1182.     if tag in ['webrip', 'webdl']:
  1183.         return 'webdl'
  1184.     if tag in ['hdtv', 'pdtv']:
  1185.         return 'hdtv'
  1186.  
  1187.     if tag in ['x264', 'h264']:
  1188.         return 'x264'
  1189.  
  1190.     if tag in ['480', '480p', '480i']:
  1191.         return '480p'
  1192.     if tag in ['540', '540p', '540i']:
  1193.         return '540p'
  1194.     if tag in ['720', '720p', '720i']:
  1195.         return '720p'
  1196.     if tag in ['1080', '1080p', '1080i']:
  1197.         return '1080p'
  1198.  
  1199.     if tag in ['proper', 'repack']:
  1200.         return 'repack'
  1201.  
  1202.     if tag in ['directors', 'dircut']:
  1203.         return 'directors'
  1204.     return tag
  1205.  
  1206. def fixTags(filename):
  1207.     filename=re.sub("[^a-zA-Z0-9](h|x)[^a-zA-Z0-9]264[^a-zA-Z0-9]", '.x264.', filename)
  1208.  
  1209.     filename=re.sub("[^a-zA-Z0-9]hd[^a-zA-Z0-9]tv[^a-zA-Z0-9]", '.hdtv.', filename)
  1210.     filename=re.sub("[^a-zA-Z0-9]web[^a-zA-Z0-9]dl[^a-zA-Z0-9]", '.webdl.', filename)
  1211.     filename=re.sub("[^a-zA-Z0-9]web[^a-zA-Z0-9]rip[^a-zA-Z0-9]", '.webrip.', filename)
  1212.     filename=re.sub("[^a-zA-Z0-9]dvd[^a-zA-Z0-9]rip[^a-zA-Z0-9]", '.dvdrip.', filename)
  1213.     filename=re.sub("[^a-zA-Z0-9]b(d|r)?[^a-zA-Z0-9]rip[^a-zA-Z0-9]", '.brrip.', filename)
  1214.  
  1215.     filename=re.sub("[^a-zA-Z0-9]dd5[^a-zA-Z0-9]1[^a-zA-Z0-9]", '.dd51.', filename)
  1216.  
  1217.     filename=re.sub("[^a-zA-Z0-9](en?|it|fr|es)[^a-zA-Z0-9]subs[^a-zA-Z0-9]", '.esubs.', filename)
  1218.     return filename
  1219.  
  1220. def parseFileName(filename, isShow=False):
  1221.    
  1222.     detected={'ShowName':[], 'Year':[], 'Season':[], 'Episode':[], 'Group':[], 'Quality':[], 'Size':[], 'Undesired':[], 'Unknown':[]}
  1223.    
  1224.     # Start analyzis per-se
  1225.     filename = filename.lower()
  1226.     filename = fixTags(filename)
  1227.    
  1228.     search_string = re.split('[^a-zA-Z0-9]', filename)
  1229.  
  1230.     # Removing empty strings
  1231.     search_string = [ st for st in search_string if st ]
  1232.  
  1233.     # Removing Extensions
  1234.     if search_string[-1] in valid_extension_modifiers:
  1235.         search_string.pop()
  1236.     if search_string[-1] in valid_video_extensions:
  1237.         search_string.pop()
  1238.     if search_string[-1] in valid_subtitle_extensions:
  1239.         search_string.pop()
  1240.     if search_string[-1] in valid_extension_modifiers:
  1241.         search_string.pop()
  1242.     if search_string[-1] in valid_video_extensions:
  1243.         search_string.pop()
  1244.     if search_string[-1] in valid_subtitle_extensions:
  1245.         search_string.pop()
  1246.  
  1247.     # Removing Garbage
  1248.     #for idx, val in reversed(list(enumerate(search_string))):
  1249.     #     if val in garbage:
  1250.     #        search_string.pop(idx)
  1251.     #        continue
  1252.    
  1253.     ## To speed up searching for season tag later
  1254.     if re.match(".+[^a-zA-Z0-9]s?\d\d[xe]\d\d([xe]\d\d)?.*", filename, re.I):
  1255.         standardSeasonFormat=True
  1256.     else:
  1257.         standardSeasonFormat=False
  1258.    
  1259.    
  1260.     #possibleGroup = search_string[0]
  1261.     possibleGroup=""
  1262.    
  1263.     endOfName=0
  1264.     for item in search_string:
  1265.        
  1266.         # Found season and episode tag
  1267.         if standardSeasonFormat and re.match("[s]?\d?\d[xe]\d\d([xe]\d\d)?", item):
  1268.             tmpregex = re.search('[s]?(\d?\d)[xe](\d\d)(?:[xe](\d\d))?',item)
  1269.             detected['Season'].append(int(tmpregex.group(1)))
  1270.             detected['Episode'].append(int(tmpregex.group(2)))
  1271.             if tmpregex.lastindex>2:
  1272.                 detected['Episode'].append(int(tmpregex.group(3)))
  1273.             endOfName = 1
  1274.             continue
  1275.        
  1276.         # Found video resolution tag
  1277.         if sizeRegex.match(item):
  1278.             detected['Size'].append(normalizeTags(item))
  1279.             endOfName = 1
  1280.             continue
  1281.        
  1282.         # Found a 4 digits number, probably Year
  1283.         if re.match("\d\d\d\d", item):
  1284.             detected['Year'].append(item)
  1285.             endOfName = 1
  1286.             continue
  1287.  
  1288.         # Found a 3 digits number
  1289.         if len(detected['ShowName'])>0 and not standardSeasonFormat and re.match("\d\d\d", item):
  1290.             tmpregex = re.search('(\d)(\d\d)',item)
  1291.             detected['Season'].append(int(tmpregex.group(1)))
  1292.             detected['Episode'].append(int(tmpregex.group(2)))
  1293.             endOfName = 1
  1294.             continue
  1295.        
  1296.         # Found well-known group
  1297.         if item in known_release_groups:
  1298.             detected['Group'].append(item)
  1299.             endOfName = 1
  1300.             continue
  1301.  
  1302.         # Found generic quality tag
  1303.         if item in video_quality:
  1304.             detected['Quality'].append(normalizeTags(item))
  1305.             endOfName = 1
  1306.             continue
  1307.  
  1308.         # Found known garbage
  1309.         if item in garbage:
  1310.             continue
  1311.            
  1312.         # Found known garbage
  1313.         if item in clean_name_from:
  1314.             continue
  1315.            
  1316.         # Found undesired word
  1317.         if item in undesired:
  1318.             detected['Undesired'].append(item)
  1319.             endOfName = 1
  1320.             continue
  1321.            
  1322.         # 2CDs video found
  1323.         if re.match("cd\d", item) or re.match("\dcd", item):
  1324.             detected['Quality'].append('2cd')
  1325.             detected['Quality'].append(item)
  1326.             endOfName = 1
  1327.             continue
  1328.        
  1329.         if not endOfName:
  1330.             detected['ShowName'].append(item)
  1331.             # if re.match("^\d$", item): # After a number, consider the rest as Unknown
  1332.             #     endOfName = 2
  1333.             continue
  1334.        
  1335.         #if endOfName == 2:
  1336.         #    outSubTitle.append(item)
  1337.         #    continue
  1338.        
  1339.         if not detected['Group']: # Last unknown is possibly the release group
  1340.             if possibleGroup:
  1341.                 detected['Unknown'].append(possibleGroup)
  1342.             possibleGroup = item
  1343.             continue
  1344.        
  1345.         detected['Unknown'].append(item)
  1346.        
  1347.     if not detected['Group'] and possibleGroup:
  1348.         detected['Group'].append(possibleGroup)
  1349.    
  1350.     if (not detected['Season'] and len(detected['Year'])>1) or (isShow and not detected['Season'] and detected['Year']):
  1351.         item=detected['Year'].pop()
  1352.         detected['Season'].append(int(re.sub("(\d\d)(\d\d)", '\\1', item)))
  1353.         detected['Episode'].append(int(re.sub("(\d\d)(\d\d)", '\\2', item)))
  1354.        
  1355.     return detected
  1356.    
  1357. def calculateSimilarity(originalShow, possibleShow):
  1358.     similarity=100
  1359.    
  1360.     if Debug > 1:
  1361.         local.output+='Processing Release:\n'
  1362.         local.output+='ShowName='+str(possibleShow['ShowName'])+'\n'
  1363.         local.output+='Year='+str(possibleShow['Year'])+'\n'
  1364.         local.output+='Season='+str(possibleShow['Season'])+'\n'
  1365.         local.output+='Episode='+str(possibleShow['Episode'])+'\n'
  1366.         local.output+='Group='+str(possibleShow['Group'])+'\n'
  1367.         local.output+='Quality='+str(possibleShow['Quality'])+'\n'
  1368.         local.output+='Size='+str(possibleShow['Size'])+'\n'
  1369.         local.output+='Undesired='+str(possibleShow['Undesired'])+'\n'
  1370.         local.output+='Unknown='+str(possibleShow['Unknown'])+'\n'
  1371.         local.output+='\n'
  1372.    
  1373.     ### Evaluate name
  1374.     # Quickly XOR both name-lists to detect differences
  1375.     if (set(originalShow['ShowName']) ^ set(possibleShow['ShowName'])):
  1376.         for tmp in [j for j in originalShow['ShowName']]:
  1377.             if tmp not in possibleShow['ShowName']:
  1378.                 if Debug > 2:
  1379.                     local.output+='-20, Missing word: '+tmp+' in name: '+str(possibleShow['ShowName'])+'\n'
  1380.                 similarity -= 20
  1381.         # Check for reverse missing names
  1382.         for tmp in [j for j in possibleShow['ShowName']]:
  1383.             if tmp not in originalShow['ShowName']:
  1384.                 if Debug > 1:
  1385.                     local.output+='-15, Too many words: '+tmp+' in release: '+str(possibleShow['ShowName'])+'\n'
  1386.                 similarity -= 15
  1387.    
  1388.     ### Evaluate Year if present
  1389.     # Quickly check if there's a common Year and pass on
  1390.     if not (set(originalShow['Year']) & set(possibleShow['Year'])):
  1391.         if originalShow['Year']:
  1392.             if originalShow['Year'][0] not in possibleShow['Year']:
  1393.                 if possibleShow['Year']:
  1394.                     if Debug > 2:
  1395.                         local.output+='-15, Wrong Year: '+str(originalShow['Year'][0])+' in: '+str(possibleShow['Year'])+'\n'
  1396.                     similarity -= 15
  1397.                 else:
  1398.                     if Debug > 2:
  1399.                         local.output+='-8, Missing Year: '+str(originalShow['Year'][0])+'\n'
  1400.                     similarity -= 8
  1401.            
  1402.     ### Evaluate season number in name
  1403.     # Quickly check if there's a common Year and pass on
  1404.     if (set(originalShow['Season']) ^ set(possibleShow['Season'])):
  1405.         if originalShow['Season']:
  1406.             if originalShow['Season'][0] not in possibleShow['Season']:
  1407.                 if Debug > 2:
  1408.                     local.output+='-15, Missing Season: '+str(originalShow['Season'])+' in: '+str(possibleShow['Season'])+'\n'
  1409.                 similarity -= 15
  1410.     if (set(originalShow['Episode']) ^ set(possibleShow['Episode'])):
  1411.         if originalShow['Episode']:
  1412.             if originalShow['Episode'][0] not in possibleShow['Episode']:
  1413.                 if Debug > 2:
  1414.                     local.output+='-10, Missing Episode: '+str(originalShow['Episode'])+' in: '+str(possibleShow['Episode'])+'\n'
  1415.                 similarity -= 10
  1416.  
  1417.     ### Filter group
  1418.     # Quickly check if there's a common Group and pass on
  1419.     if not (set(originalShow['Group']) & set(possibleShow['Group'])):
  1420.         if originalShow['Group']:
  1421.             for tmp in [j for j in originalShow['Group']]:
  1422.                 if tmp not in possibleShow['Group'] and tmp not in possibleShow['Unknown']:
  1423.                     if Debug > 1:
  1424.                         local.output+="-20, Groups don't match perfectly: "+str(originalShow['Group'])+' to '+str(possibleShow['Group'])+'\n'
  1425.                     similarity -= 20
  1426.    
  1427.     ### Filter size
  1428.     # Quickly check if there's a common Size and pass on
  1429.     if not (set(originalShow['Size']) & set(possibleShow['Size'])):
  1430.         if originalShow['Size']:
  1431.             for tmp in [j for j in originalShow['Size']]:
  1432.                 if tmp not in possibleShow['Size'] and tmp not in possibleShow['Unknown']:
  1433.                     if Debug > 1:
  1434.                         local.output+="-14, Size doesn't match perfectly: "+str(originalShow['Size'])+' to '+str(possibleShow['Size'])+'\n'
  1435.                     similarity -= 14
  1436.    
  1437.     ### Filter quality
  1438.     # Quickly XOR both quality-lists to detect differences
  1439.     if (set(originalShow['Quality']) ^ set(possibleShow['Quality'])):
  1440.         for tmp in [j for j in originalShow['Quality']]:
  1441.             if tmp not in possibleShow['Quality']:
  1442.                 if Debug > 2:
  1443.                     local.output+='-5, Missing quality: '+tmp+' in name: '+str(possibleShow['Quality'])+'\n'
  1444.                 similarity -= 5
  1445.         # Check for reverse missing names
  1446.         for tmp in [j for j in possibleShow['Quality']]:
  1447.             if tmp not in originalShow['Quality']:
  1448.                 if Debug > 1:
  1449.                     local.output+='-3, Too many qualities: '+tmp+' in release: '+str(possibleShow['Quality'])+'\n'
  1450.                 similarity -= 3
  1451.    
  1452.     # Devalue undesired words
  1453.     for tmp in possibleShow['Undesired']:
  1454.         if Debug > 2:
  1455.             local.output+='-2, Undesired word found: '+tmp+'\n'
  1456.         similarity -= 2
  1457.        
  1458.     return similarity
  1459.  
  1460. # Threaded function: grab from queue and analyze
  1461. def ltvdownloader(videosQ):
  1462.     global lock, Done
  1463.     local.output = ''
  1464.     local.wanted_languages = []
  1465.  
  1466.     while not Done:
  1467.         try:
  1468.             if local.output:
  1469.                 videosQ.task_done()
  1470.                 with lock:
  1471.                     try:
  1472.                         print(local.output)
  1473.                         #print('remaining items: '+str(videosQ.qsize()))
  1474.                     except (Exception):
  1475.                         print(local.output.encode('utf-8','ignore'))
  1476.                         pass
  1477.                        
  1478.             local.output=''
  1479.             originalFilename= videosQ.get(False)
  1480.  
  1481.             videoTitle=[]
  1482.             videoSubTitle=[]
  1483.             season=0
  1484.             episode=0
  1485.             year=0
  1486.             quality=[]
  1487.             size=''
  1488.             group=''
  1489.  
  1490.             dirpath=''
  1491.  
  1492.             dirpath, originalFilename = os.path.split(os.path.abspath(originalFilename))
  1493.  
  1494.             if Debug > -1:
  1495.                 local.output+='\n'+str(threading.current_thread().getName())+'/'+str(videosQ.qsize())+': '+originalFilename+'\n'
  1496.  
  1497.             # Remove garbage of movie name and accompanying files
  1498.             if clean_name:
  1499.                 if fix_ETTV_subfolder:
  1500.                     dirpath, originalFilename = cleanAndMoveFromSubfolder(dirpath, originalFilename)
  1501.                 originalFilename = cleanAndRenameFile(dirpath, originalFilename)
  1502.            
  1503.             # check already existing subtitles to avoid re-download
  1504.             existSubs=[]
  1505.             subFound=''
  1506.             sublang=''
  1507.            
  1508.             # Check without language
  1509.             tmp = os.path.splitext(os.path.join(dirpath, originalFilename))[0] + '.s*'
  1510.  
  1511.             # Escape square brackets in filenames, Glob's fault...
  1512.             for subFound in glob.glob(re.sub(r'(?<!\[)\]', '[]]', re.sub(r'\[', '[[]', tmp))):
  1513.                 existSubs.append(subFound)
  1514.                 if Debug > 1:
  1515.                     local.output+='Found a subtitle: '+subFound+'\n'
  1516.                 break
  1517.            
  1518.             local.wanted_languages = preferred_languages[:]
  1519.            
  1520.             # Check with language
  1521.             if append_language:
  1522.                 for idx, lang in reversed(list(enumerate(local.wanted_languages))):
  1523.                     tmp = os.path.splitext(os.path.join(dirpath, originalFilename))[0] + '.'+lang+'.s*'
  1524.                     for sublang in glob.glob(re.sub(r'(?<!\[)\]', '[]]', re.sub(r'\[', '[[]', tmp))):
  1525.                         existSubs.append(sublang)
  1526.                         if Debug > 1:
  1527.                             local.output+='Found a \''+lang+'\' subtitle: '+sublang+'\n'
  1528.                         if idx<stopSearchWhenExistsLang:
  1529.                             local.wanted_languages = []
  1530.                         else:
  1531.                             local.wanted_languages = local.wanted_languages[0:idx]
  1532.                            
  1533.             if subFound and not ForceSearch and (not sublang or not os.path.samefile(subFound, sublang)):
  1534.                 with lock:
  1535.                     statistics['Best'] += 1
  1536.                 if Debug > -1:
  1537.                     local.output+='No-language subtitles already present\n'
  1538.                 continue
  1539.            
  1540.             ## Create symlink with the same name as the video, for some players that don't support multiple languages
  1541.             if append_language and hardlink_without_lang_to_best_sub and (len(local.wanted_languages) != len(preferred_languages)):
  1542.                 createLinkSameName(Folder=dirpath, Movie=originalFilename, Destination=sublang)
  1543.        
  1544.             if len(local.wanted_languages) == 0:
  1545.                 if len(input_string) == 2:
  1546.                     if Debug > 2:
  1547.                         local.output+='Single argument: Forcing search\n'
  1548.                 else:
  1549.                     with lock:
  1550.                         statistics['Best'] += 1
  1551.                     if Debug > -1:
  1552.                         local.output+='Best-language subtitles already present\n'
  1553.                     continue
  1554.  
  1555.             ###############################
  1556.            
  1557.             parsedShow = parseFileName(originalFilename)
  1558.             if Debug > 0:
  1559.                 local.output+='Processed name:\n'
  1560.                 local.output+='outShowName='+str(parsedShow['ShowName'])+'\n'
  1561.                 local.output+='outYear='+str(parsedShow['Year'])+'\n'
  1562.                 local.output+='outSeason='+str(parsedShow['Season'])+'\n'
  1563.                 local.output+='outEpisode='+str(parsedShow['Episode'])+'\n'
  1564.                 local.output+='outGroup='+str(parsedShow['Group'])+'\n'
  1565.                 local.output+='outQuality='+str(parsedShow['Quality'])+'\n'
  1566.                 local.output+='outSize='+str(parsedShow['Size'])+'\n'
  1567.                 local.output+='outUndesired='+str(parsedShow['Undesired'])+'\n'
  1568.                 local.output+='outUnknown='+str(parsedShow['Unknown'])+'\n'
  1569.                 local.output+='\n'
  1570.            
  1571.             with lock:
  1572.                 if not parsedShow['ShowName']:
  1573.                     statistics['Failed'] += 1
  1574.                     if Debug > -1:
  1575.                         local.output+='! Error, failed to parse show name from: '+originalFilename+'\n'
  1576.                     continue
  1577.                
  1578.                 if len(parsedShow['Size'])>1:
  1579.                     statistics['Errors'] += 1
  1580.                     if Debug > -1:
  1581.                         local.output+='! Error, two Sizes in file: '+str(parsedShow['Size'])+' in '+originalFilename+'\n'
  1582.                
  1583.                 if not parsedShow['Group']:
  1584.                     statistics['Errors'] += 1
  1585.                     if Debug > -1:
  1586.                         local.output+="! Error, couldn't parse Release Group from: "+originalFilename+'\n'
  1587.  
  1588.                 if parsedShow['Season'] and parsedShow['Episode']:
  1589.                     statistics['Shows'] += 1
  1590.                 else:
  1591.                     statistics['Movies'] += 1
  1592.  
  1593.             if Debug > 2:
  1594.                 local.output+='------------------\n'
  1595.  
  1596.             subtitle = ltv.search(parsedShow)
  1597.            
  1598.             if not subtitle:
  1599.                 with lock:
  1600.                     if local.wanted_languages == preferred_languages:
  1601.                         statistics['NoSubs'] += 1
  1602.                         if Debug > -1:
  1603.                             local.output+='No subtitles found\n'
  1604.                     else:
  1605.                         statistics['NoBest'] += 1
  1606.                         if Debug > -1:
  1607.                             local.output+='No better subtitles found\n'
  1608.                 continue
  1609.            
  1610.             if subtitle['%'] < confidence_threshold:
  1611.                 with lock:
  1612.                     if local.wanted_languages == preferred_languages:
  1613.                         statistics['NoSubs'] += 1
  1614.                     else:
  1615.                         statistics['NoBest'] += 1
  1616.                 if Debug > -1:
  1617.                     local.output+='Only bad subtitles, similiarity: '+str(subtitle['%'])+'\n'
  1618.                 continue
  1619.                
  1620.             if not ltv.download(subtitle):
  1621.                 time.sleep(random.uniform(1.0, 4.0))
  1622.                 if not ltv.download(subtitle):
  1623.                     if Debug > -1:
  1624.                         local.output+='. Failed to download subtitle: '+subtitle['release']+'\n'
  1625.                     continue
  1626.            
  1627.             if Debug == 0:
  1628.                 local.output+='ed: '+subtitle['language']
  1629.                
  1630.             ltv.extract_sub(dirpath, originalFilename, parsedShow, subtitle['language'])
  1631.             if Debug == 0:
  1632.                 local.output+=', '+subtitle['release']+'\n'
  1633.             continue
  1634.  
  1635.  
  1636.         except (queue.Empty):
  1637.             #print('Waiting for jobs for '+str(threading.current_thread().getName()))
  1638.             if Done:
  1639.                 return
  1640.             time.sleep(random.uniform(1.0, 4.0))
  1641.             pass
  1642.         except:
  1643.             print('print_exc():')
  1644.             traceback.print_exc(file=sys.stdout)
  1645.             return
  1646.  
  1647.  
  1648. ## Main starts here
  1649. ## Main starts here
  1650. ## Main starts here
  1651. ## Main starts here
  1652. ## Main starts here
  1653. ## Main starts here
  1654. ## Main starts here
  1655. ## Main starts here
  1656. ## Main starts here
  1657. ## Main starts here
  1658. ## Main starts here
  1659. ## Main starts here
  1660.  
  1661. if __name__ == '__main__':
  1662.  
  1663.     global statistics
  1664.     global ltv
  1665.  
  1666.     preferred_languages = [x.lower() for x in preferred_languages]
  1667.     clean_name_from = [x.lower() for x in clean_name_from]
  1668.     valid_video_extensions = [x.lower() for x in valid_video_extensions]
  1669.     valid_subtitle_extensions = [x.lower() for x in valid_subtitle_extensions]
  1670.    
  1671.     known_release_groups = [x.lower() for x in known_release_groups]
  1672.     garbage = [x.lower() for x in garbage]
  1673.     undesired = [x.lower() for x in undesired]
  1674.     video_quality = [x.lower() for x in video_quality]
  1675.     video_size = [x.lower() for x in video_size]
  1676.    
  1677.     sizeRegex = re.compile("("+'|'.join(video_size)+")(i|p)", re.I)
  1678.    
  1679.     statistics={'Videos':0, 'NotVideos':0, 'Folders':0, 'Shows':0, 'Movies':0, 'Failed':0, 'Errors':0, 'Best':0, 'DL':0, 'Upg':0, 'NoBest':0, 'NoSubs':0, 'PT':0, 'BR':0, 'EN':0}
  1680.  
  1681.  
  1682.     ltv = LegendasTV(ltv_username, ltv_password)
  1683.  
  1684.     if not OnlyIMDBRating:
  1685.         if Debug > -1:
  1686.             print('Logging in Legendas.TV')
  1687.         if not ltv.login():
  1688.             if Debug > -1:
  1689.                 print('Press any key to exit...')
  1690.             junk = getch()
  1691.             sys.exit()
  1692.         if Debug > 0:
  1693.             print('Logged with success!')
  1694.  
  1695.     input_string = sys.argv[1:]
  1696.  
  1697.     if len(input_string) == 0:
  1698.         input_string.append(default_folder)
  1699.  
  1700.     # Mark where the original input ends
  1701.     input_string.append("-OI")
  1702.  
  1703.     videosQ = queue.Queue()
  1704.  
  1705.     # Start worker threads here
  1706.     for i in range(thread_count):
  1707.         t = threading.Thread(target=ltvdownloader, args = (videosQ,), daemon=True)
  1708.         t.start()
  1709.  
  1710.  
  1711.     if Debug > -1:
  1712.         print('Parsing arguments. First results can take a few seconds.\n')
  1713.  
  1714.     OriginalInputFinished = False
  1715.  
  1716.     count=0
  1717.     # Parsing all arguments (Files)
  1718.     for originalFilename in input_string:
  1719.         dirpath=''
  1720.        
  1721.         if Done: # Signal received
  1722.             break
  1723.  
  1724.         # Flag to remove garbage from filename in this item
  1725.         clean_name = clean_original_filename
  1726.  
  1727.         if originalFilename == '-r':
  1728.             recursive_folders = True
  1729.             continue
  1730.  
  1731.         if originalFilename == '-OI':
  1732.             OriginalInputFinished = True
  1733.             continue
  1734.  
  1735.         if originalFilename == '-f':
  1736.             ForceSearch = True
  1737.             continue
  1738.  
  1739.         if originalFilename == '-OnlyIMDBRating':
  1740.             if Debug > -1:
  1741.                 print('Only doing IMDB Rating!')
  1742.             OnlyIMDBRating = True
  1743.             continue
  1744.  
  1745.         if originalFilename == '-s':
  1746.             silentMode = True
  1747.             getch = None
  1748.             continue
  1749.  
  1750.  
  1751.         if os.path.islink(originalFilename):
  1752.             if Debug > 0:
  1753.                 print('Symbolic link ignored! %s' % (os.path.basename(originalFilename)))
  1754.             statistics['NotVideos'] += 1
  1755.             continue
  1756.        
  1757.         if os.path.isfile(originalFilename):
  1758.             if originalFilename.endswith(tuple(valid_extension_modifiers)):
  1759.                 originalFilename = os.path.splitext(originalFilename)[0]
  1760.                 clean_name = False # Can't rename
  1761.  
  1762.             if not originalFilename.endswith(tuple(valid_video_extensions)):
  1763.                 if Debug > 2:
  1764.                     print('Not a video file: %s' % (os.path.basename(originalFilename)))
  1765.                 statistics['NotVideos'] += 1
  1766.                 continue
  1767.             if len(input_string)<=2:
  1768.                 ForceSearch=True
  1769.                 if Debug > -1:
  1770.                     print('Single argument: Forcing search, ignore existing subs')
  1771.        
  1772.         elif os.path.isdir(originalFilename):
  1773.             if not recursive_folders:
  1774.                 if fix_ETTV_subfolder and re.match(".+[^a-zA-Z0-9]S\d\dE\d\d(E\d\d)?[^a-zA-Z0-9].+", originalFilename):
  1775.                     if Debug > 0:
  1776.                         print('Found ETTV folder: %s' % (originalFilename))
  1777.                 elif OriginalInputFinished:
  1778.                     if Debug > 2:
  1779.                         print('Directory found, recursiveness OFF: %s' % (originalFilename))
  1780.                     continue
  1781.                 else:
  1782.                     if originalFilename != '.':
  1783.                         recursive_folders = True
  1784.                     if Debug > -1:
  1785.                         print('Searching whole directory: %s' % (originalFilename))
  1786.             else:
  1787.                 if Debug > 0:
  1788.                     print('Recursing directory: %s' % (os.path.abspath(originalFilename)))
  1789.  
  1790.             if append_iMDBRating:
  1791.                 originalFilename = getAppendRating((os.path.abspath(originalFilename)))
  1792.  
  1793.             statistics['Folders'] += 1
  1794.             for files in os.listdir(originalFilename):
  1795.                 input_string.append(os.path.join(originalFilename, files))
  1796.             continue
  1797.  
  1798.         elif not os.path.exists(originalFilename):
  1799.             if Debug > 2:
  1800.                 print('! Error, file not present! Moved? %s' % (originalFilename))
  1801.             continue
  1802.  
  1803.         else:
  1804.             statistics['Failed'] += 1
  1805.             if Debug > -1:
  1806.                 print('! Error, Not a file nor a directory?!?! %s' % (originalFilename))
  1807.             continue
  1808.        
  1809.         statistics['Videos'] += 1
  1810.  
  1811.         if not os.path.dirname(os.path.abspath(originalFilename)):
  1812.             statistics['Failed'] += 1
  1813.             if Debug > -1:
  1814.                 print('Error, no path!!')
  1815.             #dirpath = os.getcwd()
  1816.             continue
  1817.  
  1818.         if not OnlyIMDBRating:
  1819.             videosQ.put(os.path.abspath(originalFilename))
  1820.  
  1821.     while not videosQ.empty():
  1822.         time.sleep(1)
  1823.  
  1824.     videosQ.join()
  1825.     Done=True
  1826.  
  1827.     if Debug > 2:
  1828.         print('------------------')
  1829.    
  1830.    
  1831.     ltv.logout()
  1832.    
  1833.     if Debug > -1:
  1834.        
  1835.         print('\n\nFinal statistics:', end="")
  1836.         print('Failed!! %d, Errors: %d' % (statistics['Failed'], statistics['Errors'] ))
  1837.        
  1838.         print('\nFolders analyzed: %d' % (statistics['Folders']))
  1839.         print('Movies: %d,  Shows: %d,  NotVideos: %d' % (statistics['Movies'], statistics['Shows'], statistics['NotVideos']))
  1840.        
  1841.         print('\nSubtitles downloaded: %d, of which %d were upgrades' % (statistics['DL'], statistics['Upg']))
  1842.         print('PT: %d,  BR: %d,  EN: %d' % (statistics['PT'], statistics['BR'], statistics['EN']))
  1843.        
  1844.         print('\nFinal subtitles status in parsed library:')
  1845.         print('Best: %d,  Upgradeable: %d,  No Subs: %d' % (statistics['Best'], statistics['NoBest'], statistics['NoSubs']))
  1846.  
  1847.     if Debug > -1:
  1848.         if(platform.system().lower().find("windows") > -1):
  1849.               print('\nPress any key to exit...')
  1850.               junk = getch()
  1851.  
  1852.  
  1853.     sys.exit()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement