|
- # get args
- # make torrent
- # read mediainfo
- # upload torrent
- # move torrent to watch dir
-
- # Standard library packages
- from subprocess import check_output
- import re
- import os
- import sys
- import argparse
- from urllib.parse import urlparse
- import json
- # Third-party packages
- from bs4 import BeautifulSoup
- from torf import Torrent
- from pathlib import Path
- # JPS-AU files
- import smpy
-
- from pymediainfo import MediaInfo
-
- def asciiart ():
- print("""
- ███████╗███╗ ███╗ █████╗ ██╗ ██╗ ████████╗██╗ ██╗
- ██╔════╝████╗ ████║ ██╔══██╗██║ ██║ ╚══██╔══╝██║ ██║
- ███████╗██╔████╔██║█████╗███████║██║ ██║█████╗██║ ██║ ██║
- ╚════██║██║╚██╔╝██║╚════╝██╔══██║██║ ██║╚════╝██║ ╚██╗ ██╔╝
- ███████║██║ ╚═╝ ██║ ██║ ██║╚██████╔╝ ██║ ╚████╔╝
- ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝
-
- """)
-
-
- def getargs():
- """
- Get arguments using argparse
- """
- parser = argparse.ArgumentParser()
- parser.add_argument('-i', '--input', help='Initiate upload on input file', nargs='?', required=True)
- parser.add_argument('-d', '--debug', help='Enable debug mode.', action='store_true')
- parser.add_argument("-dry", "--dryrun", help="Dryrun will carry out all actions other than the actual upload to SM.", action="store_true")
- parser.add_argument("-rt", "--releasetype", help='Set the release type. (PV, Music Performance, TV Music, TV Variety, TV-Drama)', nargs='?')
- parser.add_argument("-a", "--artists", help='Set the artists. (Romaji\English). Split multiple with ","', nargs='?')
- parser.add_argument("-oa", "--originalartist", help='Set the artist. (Original Language)', nargs='?')
- parser.add_argument("-ca", "--contributingartists", help='Set the contributing artists. (Romaji\English). Split multiple with ","', nargs='?')
- parser.add_argument("-ti", "--title", help='Set the title. (Romaji\English)', nargs='?')
- parser.add_argument("-oti", "--originaltitle", help='Set the title. (Original Language)', nargs='?')
- parser.add_argument("-t", "--tags", help="Add additional tags to the upload. At least 2 tags are required", nargs='?')
- parser.add_argument("-y", "--year", help='Set the torrent year (YYYYMMDD or YYYY).', nargs='?')
- #parser.add_argument("-f", "--freeleech", help="Enables freeleech. ()", action="store_true")
- parser.add_argument("-eti", "--editiontitle", help='Set the edition title', nargs='?')
- parser.add_argument("-ey", "--editionyear", help='Set the torrent edition year (YYYYMMDD or YYYY).', nargs='?')
- parser.add_argument("-ms", "--mediasource", help='Set the media source. (HDTV, Web)', nargs='?')
- parser.add_argument("-s", "--sub", help='Set the subtitle type. (NoSubs,Softsubs,Hardsub)', nargs='?')
- parser.add_argument("-l", "--language", help='Set the language (Japanese, English, Korean, Chinese, Vietnamese, Other)', nargs='?')
- parser.add_argument("-im", "--imageURL", help='Set the torrent cover URL.', nargs='?')
- parser.add_argument("-ss", "--screenshots", help='Set the torrent screenshots', nargs='?')
- parser.add_argument("-tdes", "--torrentdescription", help='Add a torrent description', nargs='?')
- parser.add_argument("-tgdes", "--torrentgroupdescription", help='Add a torrent group description. This is a required argument.', nargs='?', required=True)
-
- return parser.parse_args()
-
-
-
- def gatherdata():
- """
- Retrieve data about the upload. Ask for user input if necessary.
-
- :return: releasedata: dict
- """
- releasedata = {"submit": "true"}
- releasedata["album_desc"] = torrentgroupdescription
-
- if torrentdescription:
- releasedata['release_desc'] = torrentdescription
-
- list_of_types = ["PV", "Music Performance", "TV Music", "TV Variety", "TV-Drama"]
- if releasetype in list_of_types:
- if releasetype == "PV":
- releasedata["type"] = 5
- elif releasetype == "Music Performance":
- releasedata["type"] = 6
- elif releasetype == "TV Music":
- releasedata["type"] = 7
- elif releasetype == "TV Variety":
- releasedata["type"] = 8
- elif releasetype == "TV-Drama":
- releasedata["type"] = 9
- else:
- while(True):
- input_lang = input("\n" + "_" * 100 + "\nEnter a number to choose the upload type. \n1=PV\n2=Music Performance\n3=TV Music\n4=TV Variety\n5=TV-Drama\n")
- if input_lang == "1":
- releasedata["type"] = 5
- break
- elif input_lang == "2":
- releasedata["type"] = 6
- break
- elif input_lang == "3":
- releasedata["type"] = 7
- break
- elif input_lang == "4":
- releasedata["type"] = 8
- break
- elif input_lang == "5":
- releasedata["type"] = 9
- break
- print("Invalid choice.")
- if artists:
- releasedata['idols[]'] = artists
- else:
- input_english_artist = input("\n" + "_" * 100 + "\nEnter the romaji/english ARTIST name. Separate multiple with \",\". \n")
- input_english_artist = [x.strip() for x in input_english_artist.split(',')]
- releasedata['idols[]'] = input_english_artist
-
- if originalartist:
- releasedata['artist_jp'] = originalartist
- else:
- input_artist = input("\n" + "_" * 100 + "\nEnter the original ARTIST name. Press enter to skip if this torrent has multiple artists or artist name is already english. \n")
- releasedata['artist_jp'] = input_artist
-
- if contributingartists:
- input_english_contributing_artist = contributingartists
- else:
- input_english_contributing_artist = input("\n" + "_" * 100 + "\nEnter the romaji/english CONTRIBUTING ARTIST name. Separate with \",\". Press enter to skip.\n")
- if input_english_contributing_artist != "":
- input_english_contributing_artist = [x.strip() for x in input_english_contributing_artist.split(',')]
- releasedata['contrib_artists[]'] = input_english_contributing_artist
-
- if title:
- releasedata['title'] = title
- else:
- input_english_title = input("\n" + "_" * 100 + "\nEnter the romaji/english TITLE:\n")
- releasedata['title'] = input_english_title
-
- if originaltitle:
- releasedata['title_jp'] = originaltitle
- else:
- input_title = input("\n" + "_" * 100 + "\nEnter the original TITLE. Press enter to skip.\n")
- releasedata['title_jp'] = input_title
-
- if year:
- releasedata["year"] = year
- else:
- input_year = input("\n" + "_" * 100 + "\nEnter the year as YYYYMMDD or YYYY.\n")
- releasedata["year"] = input_year
-
- if editiontitle:
- releasedata['remastertitle'] = editiontitle
- else:
- input_editiontitle = input("\n" + "_" * 100 + "\nEnter the edition TITLE. Press enter to skip.\n")
- if input_editiontitle != "":
- if editionyear:
- releasedata["remasteryear"] = editionyear
- else:
- input_editionyear = input("\n" + "_" * 100 + "\nEnter the edition year as YYYYMMDD or YYYY.\n")
- releasedata["remasteryear"] = input_editionyear
- releasedata['remastertitle'] = input_editiontitle
-
- if sub:
- releasedata["sub"] = sub
- else:
- while(True):
- input_sub = input("\n" + "_" * 100 + "\nEnter a number to choose subtitle type. \n1=NoSubs\n2=Softsubs\n3=Hardsubs\n")
- if input_sub == "1":
- releasedata["sub"] = "NoSubs"
- break
- elif input_sub == "2":
- releasedata["sub"] = "Softsubs"
- break
- elif input_sub == "3":
- releasedata["sub"] = "Hardsubs"
- break
- print("Invalid choice.")
-
- if language:
- releasedata["lang"] = language
- else:
- while(True):
- input_lang = input("\n" + "_" * 100 + "\nEnter a number to choose subtitle type. \n1=Japanese\n2=English\n3=Korean\n4=Chinese\n5=Vietnamese\n6=Other\n")
- if input_lang == "1":
- releasedata["lang"] = "Japanese"
- break
- elif input_lang == "2":
- releasedata["lang"] = "English"
- break
- elif input_lang == "3":
- releasedata["lang"] = "Korean"
- break
- elif input_lang == "2":
- releasedata["lang"] = "Chinese"
- break
- elif input_lang == "3":
- releasedata["lang"] = "Vietnamese"
- break
- elif input_lang == "2":
- releasedata["lang"] = "Other"
- break
- print("Invalid choice.")
-
- if mediasource:
- releasedata['media'] = mediasource
- else:
- while(True):
- input_lang = input("\n" + "_" * 100 + "\nEnter a number to choose the media source. \n1=HDTV\n2=Web\n")
- if input_lang == "1":
- releasedata["media"] = "HDTV"
- break
- elif input_lang == "2":
- releasedata["media"] = "Web"
- break
- print("Invalid choice.")
-
-
-
-
-
-
- if tags:
- releasedata["tags"] = tags
- else:
- while(True):
- input_tags = input("\n" + "_" * 100 + "\nEnter the tags. Separate multiple with \",\". Minimum 1 tag required.\n")
- if len(input_tags.split(",")) != 0:
- releasedata["tags"] = input_tags
- break
- else:
- print("Please enter at least one tag.")
-
- if screenshots:
- input_screenshots = screenshots
- else:
- input_screenshots = input("\n" + "_" * 100 + "\nEnter the screenshot links. Separate multiple with \",\". Press enter to skip.\n")
- if input_screenshots != "":
- input_screenshots = input_screenshots.replace(",","\n")
- releasedata["screenshots"] = input_screenshots
-
- return releasedata
-
- def add_mediainfo_to_releasedata(filename, releasedata):
- """
- Retrieve mediainfo and append it to the releasedata dictionary.
- :return: releasedata: dict
- """
- mediainfosall = ""
- media_info = MediaInfo.parse(filename)
- mediainfosall += str(MediaInfo.parse(filename, text=True))
- replacement = str(Path(filename).parent)
- mediainfosall = mediainfosall.replace(replacement, '')
- for track in media_info.tracks:
- if track.track_type == 'General':
- # releasedataout['language'] = track.audio_language_list # Will need to check if this is reliable
- if 'container' not in releasedata: # Not an ISO, only set container if we do not already know its an ISO
- releasedata['container'] = track.file_extension.upper()
- else: # We have ISO - get category data based Mediainfo if we have it
- if track.file_extension.upper() == 'VOB':
- releasedata['category'] = 'DVD'
- elif track.file_extension.upper() == 'M2TS': # Not used yet as we cannot handle Bluray / UDF
- releasedata['category'] = 'Bluray'
-
- if track.track_type == 'Video':
- validatecodec = {
- "MPEG Video": "MPEG-2",
- "AVC": "h264",
- "HEVC": "h265",
- "MPEG-4 Visual": "DivX", # MPEG-4 Part 2 / h263 , usually xvid / divx
- }
- for old, new in validatecodec.items():
- if track.format == old:
- releasedata['codec'] = new
-
- standardresolutions = {
- "3840": "1920",
- "1920": "1080",
- "1440": "1080",
- "1280": "720",
- "720": "480",
- }
- for width, height in standardresolutions.items():
- if str(track.width) == width and str(track.height) == height:
- releasedata['ressel'] = height
-
- if 'ressel' in releasedata.keys(): # Known resolution type, try to determine if interlaced
- if track.scan_type == "Interlaced" or track.scan_type == "MBAFF" or (track.width == 1440 and track.height == 1080):
- releasedata['ressel'] += "i"
- else:
- releasedata['ressel'] += "p" # Sometimes a Progressive encode has no field set
- else: # Custom resolution
- releasedata['ressel'] = 'Other'
- releasedata['resolution'] = str(track.width) + "x" + str(track.height)
-
- if track.track_type == 'Audio' or track.track_type == 'Audio #1': # Handle multiple audio streams, we just get data from the first for now
- if track.format in ["AAC", "DTS", "PCM", "AC3"]:
- releasedata['audioformat'] = track.format
- elif track.format == "AC-3":
- releasedata['audioformat'] = "AC3"
- elif track.format == "MPEG Audio" and track.format_profile == "Layer 3":
- releasedata['audioformat'] = "MP3"
- elif track.format == "MPEG Audio" and track.format_profile == "Layer 2":
- releasedata['audioformat'] = "MP2"
- releasedata["mediainfo"] = mediainfosall
-
- return releasedata
-
- # Creates torrent file using torf module.
- def createtorrent(authkey, filepath, releasedata):
- """
- Creates a torrent.
- :param: authkey: authkey string
- :param: filepath: full path of the file for torrent creation
- :param: releasedata: dict
- :return: filename of created torrent
- """
- t = Torrent(path=filepath,
- trackers=[authkey]) # Torf requires we store authkeys in a list object. This makes it easier to add multiple announce urls.
- # Set torrent to private as standard practice for private trackers
- t.private = True
- t.source = "SugoiMusic"
- t.generate()
- ## Format releasedata to bring a suitable torrent name.
- # The reason we don't just use the directory name is because of an error in POSTING.
- # POSTS do not seem to POST hangul/jp characters alongside files.
- # filename = f"{releasedata['idols[]']} - {releasedata['title']} [{releasedata['media']}-{releasedata['audioformat']}].torrent"
- filename = f"{releasedata['title']}.torrent"
- filename = filename.replace("/","")
- try:
- t.write(filename)
- print("_" * 100)
- print("Torrent creation:\n")
- print(f"{filename} has been created.")
- except:
- print("_" * 100)
- print("Torrent creation:\n")
- os.remove(filename)
- print(f"{filename} already exists, existing torrent will be replaced.")
- t.write(filename)
- print(f"{filename} has been created.")
-
- return filename
-
- def getauthkey():
- """
- Get SM session authkey for use by uploadtorrent() data dict.
- Uses SM login data
-
- :return: authkey
- """
- smpage = sm.retrieveContent("https://sugoimusic.me/torrents.php?id=118") # Arbitrary page on JPS that has authkey
- soup = BeautifulSoup(smpage.text, 'html5lib')
- rel2 = str(soup.select('#content .thin .main_column .torrent_table tbody'))
- authkey = re.findall('authkey=(.*)&torrent_pass=', rel2)
- return authkey
-
- def uploadtorrent(torrent, imageURL, releasedata):
- """
- Uploads a torrent.
- :param: torrent: torrent filename.
- :param: imageURL: url to a cover image
- :param: releasedata: dict
- """
- # POST url.
- uploadurl = "https://sugoimusic.me/upload.php"
-
- # Dataset containing all of the information obtained from our FLAC files.
- data = releasedata
- data['image'] = imageURL
-
- if not dryrun:
- data['auth'] = authkey
-
-
- if debug:
- print('_' * 100)
- print('Release Data:\n')
- for field in data:
- print(field)
- print(data)
-
- try:
- postDataFiles = {
- 'file_input': open(torrent, 'rb')
- #'userfile': open(cover, 'rb')
- }
- except FileNotFoundError:
- print("_" * 100)
- print('File not found!\nPlease confirm file locations and names. Cover image or .torrent file could not be found')
- sys.exit()
-
- # If dryrun argument has not ben passed we will POST the results to JPopSuki.
- if dryrun != True:
- SMres = sm.retrieveContent(uploadurl, "post", data, postDataFiles)
- SMerrorTorrent = re.findall('red; text-align: center;">(.*)</p>', SMres.text)
- # SMerrorLogon = re.findall('<p>Invalid (.*)</p>', SMres.text)
- if len(SMerrorTorrent)!=0:
- print("Upload failed. Torrent error")
- print(SMerrorTorrent)
- # if len(SMerrorTorrent)!=0:
- # print("Upload failed. Logon error")
- # print(SMerrorLogon)
-
- ## TODO Filter through JPSres.text and create error handling based on responses
- #print(JPSres.text)
-
- def localfileorganization(torrent, directory, watch_folder, downloads_folder):
- # Move torrent directory to downloads_folder
- # if cfg['local_prefs']['add_to_downloads_folder']:
- # try:
- # os.mkdir(os.path.join(downloads_folder, os.path.basename(directory)))
- # except FileExistsError:
- # pass
- # copytree(directory, os.path.join(downloads_folder, os.path.basename(directory)))
- # shutil.rmtree(directory)
- if cfg['local_prefs']['add_to_watch_folder']:
- os.rename(torrent, f"{watch_folder}/{torrent}")
-
-
- if __name__ == "__main__":
- asciiart()
- args = getargs()
-
- # TODO consider calling args[] directly, we will then not need this line
- dryrun = debug = imageURL = tags = inputfile = artists = contributingartists = title = None
- originalartist = originaltitle = torrentdescription = torrentgroupdescription = editiontitle = editionyear = sub = language = year = mediasource = releasetype = screenshots = None
- inputfile = args.input
-
- torrentgroupdescription = args.torrentgroupdescription
- torrentdescription = args.torrentdescription
- if args.dryrun:
- dryrun = True
-
- if args.debug:
- debug = True
-
- # if args.freeleech:
- # freeleech = True
-
- if args.imageURL:
- imageURL = args.imageURL
-
- if args.releasetype:
- releasetype = args.releasetype
-
- if args.title:
- title = args.title
-
- if args.artists:
- artists = args.artists
-
- if args.contributingartists:
- contributingartists = args.contributingartists
-
- if args.originalartist:
- originalartist = args.originalartist
-
- if args.originaltitle:
- originaltitle = args.originaltitle
-
- if args.editiontitle:
- editiontitle = args.editiontitle
-
- if args.language:
- language = args.language
-
- if args.year:
- year = args.year
-
- if args.editionyear:
- editionyear = args.editionyear
-
- if args.sub:
- sub = args.sub
-
- if args.mediasource:
- mediasource = args.mediasource
-
- if args.tags:
- tags = args.tags
-
- if args.screenshots:
- screenshots = args.screenshots
-
- releasedata = gatherdata()
- releasedata_and_mediainfo = add_mediainfo_to_releasedata(inputfile, releasedata)
- if debug:
- print("Release data and MediaInfo complete. Uploading torrent now.")
- with open(f'json_data/config.json') as f:
- cfg = json.load(f)
- loginData = {'username': cfg['credentials']['username'], 'password': cfg['credentials']['password']}
- loginUrl = "https://sugoimusic.me/login.php"
- loginTestUrl = "https://sugoimusic.me"
- successStr = "Enabled users"
- passkey = cfg['credentials']['passkey']
- annouceurl = "https://tracker.sugoimusic.me:24601/"+passkey+"/announce"
-
- # j is an object which can be used to make requests with respect to the loginsession
- sm = smpy.MyLoginSession(loginUrl, loginData, loginTestUrl, successStr, debug=args.debug)
- # Acquire authkey
- authkey = getauthkey()
-
- torrentfile = createtorrent(annouceurl, inputfile, releasedata_and_mediainfo)
- uploadtorrent(torrentfile, imageURL, releasedata_and_mediainfo)
-
- # Setting variable for watch/download folders
- # ftp_watch_folder = cfg['ftp_prefs']['ftp_watch_folder']
- # ftp_downloads_folder = cfg['ftp_prefs']['ftp_downloads_folder']
- local_watch_folder = cfg['local_prefs']['local_watch_folder']
- # local_downloads_folder = cfg['local_prefs']['local_downloads_folder']
-
- if not dryrun:
- if cfg['local_prefs']['add_to_watch_folder'] or cfg['local_prefs']['add_to_downloads_folder']:
- localfileorganization(torrent=torrentfile, watch_folder=local_watch_folder)
-
-
-
-
-
-
|