Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

224 wiersze
9.2 KiB

  1. # Standard library packages
  2. import logging
  3. import re
  4. from jps2sm.myloginsession import jpopsuki
  5. from jps2sm.constants import Categories, VideoOptions
  6. from jps2sm.utils import GetArgs
  7. # Third-party packages
  8. from bs4 import BeautifulSoup
  9. import torrent_parser as tp
  10. logger = logging.getLogger('main.' + __name__)
  11. def decide_music_performance(artists, multiplefiles, duration):
  12. """
  13. Return if upload should be a Music Performance or not
  14. A music performance is a cut from a Music TV show and is 25 mins or less long and therefore also not a TV Show artist
  15. We assume we are being called if Cat = TV Music
  16. :return: str: 'Music Performance' or 'TV Music'
  17. """
  18. if multiplefiles is True or duration > 1500000: # 1 500 000 ms = 25 mins
  19. return 'TV Music'
  20. else: # Single file that is < 25 mins, decide if Music Performance
  21. if len(artists) > 1: # Multiple artists
  22. logger.debug('Upload is a Music Performance as it has derived multiple artists and is 25 mins or less')
  23. return 'Music Performance' # JPS TV Show artists never have multiple artists
  24. JPSartistpage = jpopsuki(f"https://jpopsuki.eu/artist.php?name={artists[0]}")
  25. soup = BeautifulSoup(JPSartistpage.text, 'html5lib')
  26. categoriesbox = str(soup.select('#content .thin .main_column .box.center'))
  27. categories = re.findall(r'\[(.+)\]', categoriesbox)
  28. if any({*Categories.NonTVCategories} & {*categories}): # Exclude any TV Shows for being mislabeled as Music Performance
  29. logger.debug('Upload is a Music Performance as it is 25 mins or less and not a TV Show')
  30. return 'Music Performance'
  31. else:
  32. logger.debug('Upload is not a Music Performance')
  33. return 'TV Music'
  34. def get_alternate_fansub_category_id(artist, group_name):
  35. """
  36. Attempts to detect the actual category for JPS Fansubs category torrents and if not ask the user to select an alternate category.
  37. If it is a TV show, this TV show category type is detected and returned, else query the user from a list of potential categories.
  38. :param artist: str artist name
  39. :return: int alternative category ID based on Categories.SM()
  40. """
  41. JPSartistpage = jpopsuki(f"https://jpopsuki.eu/artist.php?name={artist}")
  42. soup = BeautifulSoup(JPSartistpage.text, 'html5lib')
  43. categoriesbox = str(soup.select('#content .thin .main_column .box.center'))
  44. categories = re.findall(r'\[(.+)\]', categoriesbox)
  45. if not any({*Categories.NonTVCategories} & {*categories}) and " ".join(categories).count('TV-') == 1:
  46. # Artist has no music and only 1 TV Category, artist is a TV show and we can auto detect the category for FanSub releases
  47. autodetectcategory = re.findall(r'(TV-(?:[^ ]+))', " ".join(categories))[0]
  48. logger.debug(f'Autodetected SM category {autodetectcategory} for JPS Fansubs torrent')
  49. return autodetectcategory
  50. else: # Cannot autodetect
  51. AlternateFanSubCategoriesIDs = (5, 6, 7, 8, 9, 11) # Matches indices in Categories()
  52. logger.warning(f'Cannot auto-detect correct category for torrent group {group_name}.')
  53. print('Select Category:')
  54. option = 1
  55. optionlookup = {}
  56. for alternativefansubcategoryid in AlternateFanSubCategoriesIDs:
  57. for cat, catid in Categories.SM.items():
  58. if alternativefansubcategoryid == catid:
  59. print(f'({option}) {cat}')
  60. optionlookup[option] = alternativefansubcategoryid
  61. option += 1
  62. alternatecategoryoption = input('Choose alternate category or press ENTER to skip: ')
  63. if alternatecategoryoption == "":
  64. logger.error('No alternate Fansubs category chosen.')
  65. return "Fansubs" # Allow upload to fail
  66. else:
  67. category = optionlookup[int(alternatecategoryoption)]
  68. logger.info(f'Alternate Fansubs category {category} chosen')
  69. return category
  70. def validate_jps_video_data(releasedata, categorystatus):
  71. """
  72. Validate and process dict supplied by getreleasedata() via collate() to extract all available data
  73. from JPS for video torrents, whilst handling weird cases where VideoTorrent is uploaded as a Music category
  74. :param releasedata:
  75. :param categorystatus: str: good or bad. good for correct category assigned and bad if this is a Music Torrent
  76. mistakenly uploaded as a non-VC category!
  77. :return: releasedataout{} validated container, codec, media, audioformat
  78. """
  79. releasedataout = {}
  80. # JPS uses the audioformat field (represented as releasedata[0] here) for containers and codecs in video torrents
  81. # If a known container is used as audioformat set it as the container on SM
  82. if releasedata[0] in VideoOptions.badcontainers:
  83. releasedataout['container'] = releasedata[0]
  84. else:
  85. releasedataout['container'] = 'CHANGEME'
  86. # If a known codec is used as audioformat set it as the codec on SM
  87. if releasedata[0] in VideoOptions.badcodecs:
  88. if releasedata[0] == "MPEG2": # JPS uses 'MPEG2' for codec instead of the correct 'MPEG-2'
  89. releasedataout['codec'] = "MPEG-2"
  90. else:
  91. releasedataout['codec'] = releasedata[0]
  92. else:
  93. releasedataout['codec'] = 'CHANGEME' # assume default
  94. if categorystatus == "good":
  95. releasedataout['media'] = releasedata[1]
  96. else:
  97. releasedataout['media'] = releasedata[2]
  98. if releasedata[0] == 'AAC': # For video torrents, the only correct audioformat in JPS is AAC
  99. releasedataout['audioformat'] = "AAC"
  100. else:
  101. releasedataout['audioformat'] = "CHANGEME"
  102. return releasedataout
  103. def validate_jps_bitrate(jps_bitrate):
  104. """
  105. Validate JPS bad bitrates to sensible bitrates ready for upload to SM
  106. :param jps_bitrate:
  107. :return: sm_bitrate
  108. """
  109. bitrates = {
  110. "Hi-Res 96/24": "24bit Lossless 96kHz",
  111. "24bit/48kHz": "24bit Lossless 48kHz",
  112. "Hi-Res": "24bit Lossless",
  113. "Hi-Res 48/24": "24bit Lossless 48kHz",
  114. "24bit/96kHz": "24bit Lossless 96kHz",
  115. "24bit/48Khz": "24bit Lossless 48kHz",
  116. "24bit/96Khz": "24bit Lossless 96kHz",
  117. "24bit/48khz": "24bit Lossless 48kHz",
  118. "Hi-Res Lossless": "24bit Lossless",
  119. "160": "Other",
  120. "Variable": "Other",
  121. "320 (VBR)": "Other",
  122. "Scans": "",
  123. "Booklet": "",
  124. "1080p": "",
  125. "720p": "",
  126. "256 (VBR)": "APS (VBR)",
  127. "155": "Other"
  128. }
  129. sm_bitrate = jps_bitrate # Default is to leave bitrate alone if not mentioned here, such as bitrates that are OK on both JPS and SM
  130. for old, new in bitrates.items():
  131. if jps_bitrate == old:
  132. sm_bitrate = new
  133. return sm_bitrate
  134. def decide_exc_filter(audioformat, media, releasedata):
  135. """
  136. Implement audioformat and media exclusion filters
  137. :return: boolean: True or False
  138. """
  139. args = GetArgs()
  140. if audioformat == args.parsed.excaudioformat:
  141. logger.info(f'Excluding {releasedata} as exclude audioformat {args.parsed.excaudioformat} is set')
  142. return True
  143. elif media == args.parsed.excmedia:
  144. logger.info(f'Excluding {releasedata} as exclude media {args.parsed.excmedia} is set')
  145. return True
  146. return False
  147. def decide_ep(torrentfilename, uploaddata):
  148. """
  149. Return if Album upload should be an EP or not.
  150. EPs are considered to have < 7 tracks, excluding off-vocals and uploaded to JPS as an Album
  151. We assume we are being called only if Cat = Album
  152. :param torrentfilename:
  153. :param uploaddata:
  154. :return: str: 'EP' or 'Album'
  155. """
  156. if uploaddata['media'].lower() == 'bluray' or uploaddata['media'].lower() == 'dvd':
  157. return 'Album'
  158. torrent_metadata = tp.parse_torrent_file(torrentfilename)
  159. music_extensions = ['.flac', '.mp3', '.ogg', '.alac', '.m4a', '.wav', '.wma', '.ra']
  160. off_vocal_phrases = ['off-vocal', 'offvocal', 'off vocal', 'inst.', 'instrumental', 'english ver', 'japanese ver', 'korean ver']
  161. track_count = 0
  162. has_cue = False
  163. track_extensions = set()
  164. for file in torrent_metadata['info']['files']:
  165. file_path = file['path'][-1].lower()
  166. if file_path.endswith('.iso'):
  167. return 'Album'
  168. if file_path.endswith('.cue'):
  169. has_cue = True
  170. if list(filter(file_path.endswith, music_extensions)) and \
  171. not any(substring in file_path for substring in off_vocal_phrases):
  172. # Count music files which are not an off-vocal or instrumental
  173. logger.debug(f"Deciding if EP with torrent with these tracks: {file['path'][-1]}")
  174. track_count += 1
  175. track_extensions.add(file_path.split('.')[-1])
  176. if has_cue and track_extensions == {'flac'}:
  177. logger.debug(f'Upload is not an EP as it has a .cue file and only .flac files')
  178. return 'Album'
  179. if track_count < 7:
  180. logger.debug(f'Upload is an EP as it has {track_count} standard tracks')
  181. return 'EP'
  182. else:
  183. logger.debug(f'Upload is not an EP as it has {track_count} tracks')
  184. return 'Album'