|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715 |
-
- import re
- import os
- import sys
- import shutil
- import string
- import argparse
- import html
- from urllib.parse import urlparse
- import json
- import ftplib
-
-
- import requests
- from bs4 import BeautifulSoup
- from mutagen.flac import FLAC
- from mutagen.mp3 import MP3
- from torf import Torrent
- from tqdm import tqdm
- from langdetect import detect
-
-
- import smpy
-
- def asciiart ():
- print("""
- ███████╗███╗ ███╗ █████╗ ██╗ ██╗
- ██╔════╝████╗ ████║ ██╔══██╗██║ ██║
- ███████╗██╔████╔██║█████╗███████║██║ ██║
- ╚════██║██║╚██╔╝██║╚════╝██╔══██║██║ ██║
- ███████║██║ ╚═╝ ██║ ██║ ██║╚██████╔╝
- ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝
- """)
-
-
- def getargs():
- parser = argparse.ArgumentParser()
- parser.add_argument('-dir', '--directory', help='Initiate upload on directory', nargs='?', required=True)
- parser.add_argument("-f", "--freeleech", help="Enables freeleech", action="store_true")
- parser.add_argument("-t", "--tags", help="Add additional tags to the upload", nargs='?')
- 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 JPS.", action="store_true")
- parser.add_argument("-i", "--imageURL", help='Set the torrent cover URL', nargs='?')
- return parser.parse_args()
-
-
- 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")
- 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 copytree(src, dst, symlinks=False, ignore=None):
- for item in os.listdir(src):
- s = os.path.join(src, item)
- d = os.path.join(dst, item)
- if os.path.isdir(s):
- shutil.copytree(s, d, symlinks, ignore)
- else:
- shutil.copy2(s, d)
-
-
- def createtorrent(authkey, directory, filename, releasedata):
- t = Torrent(path=directory,
- trackers=[authkey])
-
- t.private = True
- t.source = "SugoiMusic"
- t.generate()
-
-
-
-
- filename = f"{releasedata['title']} [{releasedata['media']}-{releasedata['audioformat']}].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 readflac(filename):
- read = FLAC(filename)
-
-
- tags={
- "ALBUM": read.get('album'),
- "ALBUMARTIST": read.get('albumartist'),
- "ARTIST": read.get('artist'),
- "DATE": read.get('date')[0],
- "GENRE": "",
- "TITLE": read.get('title'),
- "COMMENT": read.get('comment'),
- "TRACKNUMBER": read.get('tracknumber')[0].zfill(2),
- "DISCNUMBER": read.get('discnumber')}
-
-
- tags['GROUPING'] = read.get('grouping')
-
-
- if tags['GROUPING'] == None:
- tags['GROUPING'] = read.get('contentgroup')
-
-
- required_tags = ['ALBUM', 'ALBUMARTIST','DATE','TRACKNUMBER']
- for k,v in tags.items():
- if v == None:
- if k in required_tags:
- print(f"{k} has returned {v}, this is a required tag")
- sys.exit()
-
- return tags
-
-
- def readmp3(filename):
- read = MP3(filename)
-
-
- tags={
- "ALBUM": read.get('TALB'),
- "ALBUMARTIST": read.get('TPE2'),
- "ARTIST": read.get('TPE1'),
- "DATE": str(read.get('TDRC')),
- "GENRE": read.get('TCON').text,
- "TITLE": read.get('TIT2'),
- "COMMENT": read.get('COMM::eng'),
- "GROUPING": read.get('TIT1'),
- "TRACKNUMBER": re.sub(r"\/.*", "", str(read.get('TRCK'))).zfill(2),
- "DISCNUMBER": re.sub(r"\/.*", "", str(read.get('TPOS')))}
-
- required_tags = ['ALBUM', 'ALBUMARTIST','DATE','TRACKNUMBER']
- for k,v in tags.items():
- if v == None:
- if k in required_tags:
- print(f"{k} has returned {v}, this is a required tag")
- sys.exit()
-
- return tags
-
-
- def generatelog(track_titles, log_filename, log_directory):
-
- track_titles = '\n'.join([str(x) for x in track_titles])
-
-
- log_contents = f"""[size=5][b]Tracklist[/b][/size]\n{track_titles}
- """
-
-
- if cfg['local_prefs']['save_tracklist']:
-
- with open(f"{log_directory}/{log_filename}.log", "w+") as f:
- f.write(log_contents)
-
- f.seek(0)
- log_contents = f.read()
- f.close()
-
-
- if debug:
- print("_" * 100)
- print(f"Log Contents/Tracklisting: {log_contents}")
-
- return log_contents
-
- def readlog(log_name, log_directory):
- with open(f"{log_directory}/{log_name}.log", "r+") as f:
- log_contents = f.read()
- f.close()
-
- return log_contents
-
- def add_to_hangul_dict(hangul , english , category):
- hangul = str(hangul)
- english = str(english)
-
- categories = ['version','general','artist','genres', 'label', 'distr']
- file = f"json_data/dictionary.json"
- json_file = open(file, 'r', encoding='utf-8', errors='ignore')
- dictionary = json.load(json_file)
- json_file.close()
-
- new = dict()
- for cats in dictionary:
-
- new[cats] = dict()
-
- for key,value in dictionary[cats].items():
-
- new[cats][key] = value
-
- if hangul in new[category].keys():
-
- if new[category].get(hangul) is None:
-
- if english != 'None':
- new[category][hangul] = english
-
- else:
-
- if english != 'None':
- new[category][hangul] = english
- else:
-
- if english == 'None':
- new[category][hangul] = None
- else:
- new[category][hangul] = english
-
- json_write = open(file, 'w+', encoding='utf-8')
- json_write.write(json.dumps(new, indent=4, ensure_ascii=False))
- json_write.close()
-
- def translate(string, category, result=None, output=None):
-
- file = "json_data/dictionary.json"
- with open(file, encoding='utf-8', errors='ignore') as f:
- dictionary = json.load(f, strict=False)
-
- category = str(category)
- string = str(string)
- search = dictionary[category]
- string = string.strip()
-
- if string == 'Various Artists':
- output = ['Various Artists',None]
- else:
-
- if re.search("\((?P<inside>.*)\)", string):
-
-
-
- parenthesis = string.split("(")
- pre_parenthesis = parenthesis[0].strip()
- in_parenthesis = parenthesis[1].replace(")","").strip()
-
-
-
- if re.search("[^\u0000-\u007F]+",pre_parenthesis) and re.search("[^\u0000-\u007F]+",in_parenthesis):
-
- first = 'kr'
- second = 'kr'
- else:
- if re.search("[^\u0000-\u007F]+",pre_parenthesis):
- first = 'kr'
- second = 'eng'
- else:
- first = 'eng'
- second = 'kr'
-
- if first == 'kr' and second == 'eng':
-
- hangul = pre_parenthesis
- english = in_parenthesis
- add_to_hangul_dict(hangul,english,category)
-
- elif first == 'eng' and second == 'kr':
-
- hangul = in_parenthesis
- english = pre_parenthesis
- add_to_hangul_dict(hangul,english,category)
- elif first == 'kr' and second == 'kr':
-
- hangul = pre_parenthesis
- english = None
- add_to_hangul_dict(pre_parenthesis,None,category)
- add_to_hangul_dict(hangul,None,category)
- else:
-
- hangul = None
- english = pre_parenthesis
-
- output = [hangul,english]
-
-
- else:
-
-
- if re.search("[^\u0000-\u007F]+", string):
-
- if string in search.keys():
-
- if search.get(string) is None:
-
- output = [string,None]
- else:
-
- output = [string,search.get(string)]
- else:
- output = [string,None]
- add_to_hangul_dict(string, None, category)
-
-
- else:
- for key,value in search.items():
- if key == string:
- output = [value,string]
- break
- else:
- output = [string,string]
-
- return output
-
- def gatherdata(directory):
-
- list_album_artists = []
- list_track_artists = []
- list_album = []
- list_genre = []
- translated_genre = []
- translated_album_artists = []
- tracklist_entries = []
-
- releasedata = {}
-
-
-
- log_available = False
- flac_present = False
- mp3_present = False
-
- for file in os.listdir(directory):
- file_location = os.path.join(directory, file)
- if file.endswith(".flac"):
-
- tags = readflac(file_location)
- flac_present = True
-
- if tags['DISCNUMBER'] == None:
- tracklist_entry = f"[b]{tags['TRACKNUMBER']}[/b]. {tags['TITLE'][0]}"
- else:
- tracklist_entry = f"[b]{tags['DISCNUMBER'][0]}-{tags['TRACKNUMBER']}[/b]. {tags['TITLE'][0]}"
-
- tracklist_entries.append(tracklist_entry)
-
- if debug:
- print ("_" * 100)
- print(f"Tags for {file}:\n{tags}")
-
- if file.endswith(".mp3"):
-
- tags = readmp3(file_location)
- mp3_present = True
-
- if tags['DISCNUMBER'] == "None":
- tracklist_entry = f"[b]{tags['TRACKNUMBER']}[/b]. {tags['TITLE'][0]}"
- else:
- tracklist_entry = f"[b]{tags['DISCNUMBER']}-{tags['TRACKNUMBER']}[/b]. {tags['TITLE'][0]}"
-
- tracklist_entries.append(tracklist_entry)
-
- if debug:
- print ("_" * 100)
- print(f"Tags for {file}:\n{tags}")
-
-
- if len(tags['GENRE']) == 1:
- tags['GENRE'] = tags['GENRE'][0].split(";")
- for aa in tags['ALBUMARTIST']:
- list_album_artists.append(aa)
- for a in tags['ARTIST']:
- list_track_artists.append(a)
- list_album.append(tags['ALBUM'][0])
-
-
-
-
-
- if flac_present:
- format = 'FLAC'
- bitrate = 'Lossless'
- if mp3_present:
- format = 'MP3'
- bitrate = '320'
- if flac_present and mp3_present:
- print("Mutt detected, exiting.")
- sys.exit()
-
- if file.endswith(".log"):
- log_available = True
-
- if log_available == True:
- media = 'CD'
- else:
- media = 'Web'
-
-
- file = "json_data/dictionary.json"
- with open(file, encoding='utf-8', errors='ignore') as f:
- dictionary = json.load(f, strict=False)
-
-
- if additional_tags != None:
- split_tags = additional_tags.split(",")
- for s in split_tags:
- list_genre.append(s)
-
-
- for g in set(list_genre):
- translation = translate(g, "genres")[0]
- translated_genre.append(translation)
-
-
- for a in set(list_album_artists):
- if tags['ALBUMARTIST'][0] == 'Various Artists':
- translated_artist_name = 'V.A.'
- translated_album_artists.append("V.A.")
- else:
- translated_artist_name = translate(string=tags['ALBUMARTIST'][0], category="artist")
- translated_album_artists.append(translated_artist_name[0])
-
-
- unique_album_artists = ','.join(set(translated_album_artists))
- unique_track_artists = ','.join(set(list_track_artists))
- unique_genre = ','.join(set(translated_genre))
- unique_album = set(list_album)
-
-
-
- log_directory = cfg['local_prefs']['log_directory']
-
- if cfg['local_prefs']['generate_tracklist']:
- log_filename = f"{unique_album_artists} - {tags['ALBUM'][0]}"
- album_description = generatelog(tracklist_entries, log_filename, log_directory)
- else:
- log_filename = tags['COMMENT'][0]
- album_description = readlog(log_filename, log_directory)
-
-
-
- if cfg['local_prefs']['enable_release_description']:
- try:
- release_description = f"Sourced from [url=https://music.bugs.co.kr/album/{tags['COMMENT'][0]}]Bugs[/url]"
-
- except:
- release_description = ""
-
- else:
- release_description = ""
-
-
-
- releasedata['submit'] = 'true'
-
-
- accepted_types = ['Album', 'Single', 'EP']
-
- try:
- releasedata['type'] = translate(tags['GROUPING'][0], "release_types")[0]
- except TypeError:
- releasedata['type'] = input("\n" + "_" * 100 + "\nGrouping is empty or has received an error, please enter manually (Album/Single/EP)\n")
-
-
- if releasedata['type'] not in accepted_types:
- while True:
- releasedata['type'] = input("\n" + "_" * 100 + "\nGrouping tag did not return an album type, please enter manually (Album/Single/EP)\n")
-
- if releasedata['type'] not in accepted_types:
- continue
- else:
- break
-
- if releasedata['type'] == "Album":
- releasedata['type'] = 0
- elif releasedata['type'] == "Single":
- releasedata['type'] = 2
- else:
- releasedata['type'] = 1
-
- releasedata['title'] = tags['ALBUM'][0]
- releasedata['idols[]'] = unique_album_artists
-
- if unique_album_artists != unique_track_artists:
- releasedata['artist_jp'] = unique_track_artists
-
- releasedata['year'] = re.sub(r"[^0-9]", "", tags['DATE'])
- releasedata['audioformat'] = format
- releasedata['bitrate'] = bitrate
- releasedata['media'] = media
- releasedata['album_desc'] = album_description
- releasedata['release_desc'] = release_description
- releasedata['tags'] = unique_genre
-
-
- if freeleech:
- releasedata['freeleech'] = "true"
-
-
-
- en = detectlanguage(releasedata['title'])
- if debug:
- print("_" * 100)
- print("Title/Artist Language:\n")
- print(f"{releasedata['title']} < English = {en}")
- if en == False:
- input_english_title = input("\n" + "_" * 100 + "\nKorean/Japanese Detected. Please enter the romaji/english title:\n")
-
- releasedata['title_jp'] = releasedata['title']
-
- releasedata['title'] = input_english_title
-
- en = detectlanguage(releasedata['idols[]'])
- if debug:
- print(f"{releasedata['idols[]']} < English = {en}")
- if en == False:
- input_english_artist = input("\n" + "_" * 100 + "\nKorean/Japanese Detected. Seperate multiple main artists with \",\". Please enter the romaji/english artist name:\n")
-
-
- input_english_artist = [x.strip() for x in input_english_artist.split(',')]
- releasedata['idols[]'] = input_english_artist
-
- return releasedata
-
-
- def split(word):
- return [char for char in word]
-
- def detectlanguage(string):
-
-
- characters = split(string)
- language_list = []
- for c in characters:
- try:
- language = detect(c)
- language_list.append(language)
- except:
- langauge = "error"
-
- if 'ko' or 'ja' in language_list:
- en = False
- else:
- en = True
-
- return en
-
- def uploadtorrent(torrent, imageURL, releasedata):
-
- uploadurl = "https://sugoimusic.me/upload.php"
-
-
- data = releasedata
- data['image'] = imageURL
-
- if not dryrun:
- data['auth'] = authkey
-
-
- if debug:
- print('_' * 100)
- print('Release Data:\n')
- print(releasedata)
-
- try:
- postDataFiles = {
- 'file_input': open(torrent, '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 != True:
- JPSres = sm.retrieveContent(uploadurl, "post", data, postDataFiles)
- print('\nUpload POSTED. It may take a moment for this upload to appear on SugoiMusic.')
-
-
-
-
-
- def ftp_transfer(fileSource, fileDestination, directory, folder_name, watch_folder):
-
-
- session = ftplib.FTP(cfg['ftp_prefs']['ftp_server'],cfg['ftp_prefs']['ftp_username'],cfg['ftp_prefs']['ftp_password'])
-
- session.encoding='utf-8'
-
-
- print("_" * 100)
- print("FTP Login Successful")
- print(f"Server Name: {cfg['ftp_prefs']['ftp_server']} : Username: {cfg['ftp_prefs']['ftp_username']}\n")
-
- if cfg['ftp_prefs']['add_to_downloads_folder']:
-
-
- try:
- session.mkd(f"{fileDestination}/{folder_name}")
- print(f'Created directory {fileDestination}/{folder_name}')
- except ftplib.error_perm:
- pass
-
-
- print(f"Beginning transfer...")
-
- session.cwd(f"{fileDestination}/{folder_name}")
-
- for file in os.listdir(directory):
- with open(f"{directory}/{file}",'rb') as f:
- filesize = os.path.getsize(f"{directory}/{file}")
-
-
- with tqdm(unit = 'blocks', unit_scale = True, leave = False, miniters = 1, desc = f'Uploading [{file}]', total = filesize) as tqdm_instance:
- session.storbinary('STOR ' + file, f, 2048, callback = lambda sent: tqdm_instance.update(len(sent)))
- print(f"{file} | Complete!")
- f.close()
-
- if cfg['ftp_prefs']['add_to_watch_folder']:
- with open(fileSource,'rb') as t:
-
- session.cwd(watch_folder)
-
-
-
- session.storbinary(f"STOR {torrentfile}", t)
- print(f"{torrentfile} | Sent to watch folder!")
- t.close()
-
- session.quit()
-
- def localfileorganization(torrent, directory, watch_folder, 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()
-
-
- dryrun = freeleech = tags = directory = debug = imageURL = None
-
- directory = args.directory
- additional_tags = args.tags
-
- if args.dryrun:
- dryrun = True
-
- if args.debug:
- debug = True
-
- if args.freeleech:
- freeleech = True
-
- if args.imageURL:
- imageURL = args.imageURL
-
-
- 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"
-
-
- sm = smpy.MyLoginSession(loginUrl, loginData, loginTestUrl, successStr, debug=args.debug)
-
- authkey = getauthkey()
-
- releasedata = gatherdata(directory)
-
-
- folder_name = os.path.basename(os.path.normpath(directory))
-
-
-
-
-
- torrentfile = createtorrent(annouceurl, directory, folder_name, releasedata)
-
-
- uploadtorrent(torrentfile, imageURL, releasedata)
-
-
- 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['ftp_prefs']['enable_ftp']:
- ftp_transfer(fileSource=torrentfile, fileDestination=ftp_downloads_folder, directory=directory, folder_name=folder_name, watch_folder=ftp_watch_folder)
-
- if cfg['local_prefs']['add_to_watch_folder'] or cfg['local_prefs']['add_to_downloads_folder']:
- localfileorganization(torrent=torrentfile, directory=directory, watch_folder=local_watch_folder, downloads_folder=local_downloads_folder)
|