Infinit Music Search and Download on services without boundary
import requests
import json
import time
import re
import random
from urllib import parse

callback = {
    'callback': 'jQuery_' + str(random.randint(20000000000000000000, 30000000000000000000)) + "_" + str(
        int(time.time() * 1000))
}

o = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
     'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'x', 'y', 'z', '1',
     '2', '3']

main_host = 'https://new.myfreemp3juices.cc/'

dw_host = ''  # Could be modified at some time

headerDm = {
    'Accept': 'text/plain'
}

headerX = {  # search
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) '
                  'Version/15.4 Safari/605.1.15',
    'X-Requested-With': 'XMLHttpRequest',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}

data = {
    'q': 'main theme (Arr.Bateman) maksim',
    'page': '0'
}

search_byte = b'downloadServerUrl:window.location.protocol+"//'


def encode_formdata(obj):
    str_t = []
    for key in obj:
        str_t.append(parse.quote(key, encoding='utf-8') + '=' + parse.quote(obj[key], encoding='utf-8'))

    return_str = '&'.join(str_t)
    return return_str


def d(t):
    length = len(o)
    e = ''

    if t == 0:
        return o[0]

    if t < 0:
        t *= -1
        e += '-'

    while t > 0:
        val = t % length
        t = t // length
        e += o[val]

    return e


def check():
    global dw_host

    session = requests.session()
    js_for_parse = main_host + '/myfreemp3juice.cc.js'
    resp_domain = session.get(url=js_for_parse, headers=headerDm, stream=True)

    if resp_domain.status_code == 200:
        for chunk in resp_domain.iter_content(chunk_size=512):
            if chunk and search_byte in chunk:
                start_index = chunk.find(search_byte) + len(search_byte) + 1
                end_index = chunk.find(b'",', start_index)
                dw_host = 'https://' + chunk[start_index:end_index].decode('utf-8')

                print(f'downloadServerUrl: {dw_host}')
                break
    else:
        raise ConnectionError("Please Check Internet Connection, or create an issue on repo page")

    # Search songs
    search_word = encode_formdata(callback)
    search_url = main_host + 'api/api_search.php?' + search_word

    resp_sch = session.post(url=search_url, data=data, headers=headerX)

    search_data = resp_sch.content.decode('utf-8')
    start_index = search_data.find('(')
    end_index = search_data.rfind(')')
    extracted_data = search_data[start_index + 1:end_index]

    verify = json.loads(extracted_data)['response']
    print(verify)

    select = 1
    select_data = verify[select]
    dw_url = dw_host + d(select_data['owner_id']) + ':' + d(select_data['id'])

    dw_resp = session.get(url=dw_url, headers=headerX)
    filename = select_data['title'] + ' - ' + select_data['artist'] + '.mp3'
    filename = re.sub(r'[\\/:*?<>|"]', '', filename)
    with open(filename, 'wb') as file:
        file.write(dw_resp.content)
    print(select_data)


if __name__ == '__main__':
    check()

assistence/assist.py
SnapdragonLee/MegaMDL
import json
import os

str1 = '穮谁镋城밎絠闙筪䗴酾⣎'
str2 = '鄓봏舳䶠蕩藸饹鈏眂繦䷒艣䜄酿逖너缨臣睛诶'
str3 = '者隁鯙矎艥翧獬访襲阄밃腢铖䁨紅兲餈砒瑚郔稹'
str4 = '鄓봏舳䶠蕦礇莃鳌ꨏ砧藒罟諵鑺鼄眍瑭䷒艣䛵醈霋렀猨鋣獝苐'
str5 = '鄓봏舳䶠癩賳蹶贎븁筞䳥腪ៀ'

COLORS = ["\033[1m\033[38;5;246m",  # Grey
          "\033[1m\033[38;5;46m",  # Green
          "\033[1m\033[38;5;161m",  # Red
          "\033[1m\033[38;5;220m",  # Yellow
          "\033[0m", ]  # Reset

with open('config/config.json', 'rb') as f:
    config = json.load(f)
f.close()

save_dir = config.get('save_dir', '')

if not os.path.isabs(save_dir):
    script_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    save_dir = os.path.join(script_dir, save_dir)

os.makedirs(save_dir, exist_ok=True)

default_mod = config.get('default_mod', '')
mp3_format = config.get('mp3_320k_format', '')

key = [0x1791, 0x1e71, 0x489f, 0x2211, 0x11fa, 0x0ef9, 0x289f]


def inter(inp: str):
    hex_string = ''
    for i, char in enumerate(inp):
        decrypted_char = chr(ord(char) - key[(len(inp) - i * 4) % 7])
        hex_string += hex(ord(decrypted_char))[2:]
    return bytes.fromhex(hex_string).decode('utf-8')


search_page = inter(str1)
detail_page = inter(str2)
q_page = inter(str3)
q_dw = inter(str4)
ripper_page = inter(str5)

# def m(oup: str):
#     original_string = oup
#     hex_string = original_string.encode('utf-8').hex()
#     print(hex_string)
#     utf16_characters = [chr(int(hex_string[i:i + 4], 16) + key[(int((len(hex_string) + 3) / 4) - i) % 7]) for i in
#                         range(0, len(hex_string), 4)]
#     return ''.join(utf16_characters)

const/basic.py
SnapdragonLee/MegaMDL
from const.basic import *
from procedure.download import dw_from_main, dw_from_qobuz
from procedure.search import check_procedure, check_connection

if __name__ == '__main__':
    mod = int(default_mod) if default_mod != '' else check_connection()

    if mod == 1:
        print('Main Mode Enabled')
    elif mod == 2:
        print('Backup Mode Enabled')
    elif mod == 5:
        print('Slow Hi-Res Download Mode Enabled')
    else:
        raise ConnectionError('Please check your config, connection or try this app after a server recover')

    query_input = input('Please input search words: ')
    query_list = check_procedure(query_input, mod)

    if query_list is None:
        print('Please try it again or change searching keyword')  # todo: Need to modify the structure of control flow

    select_input = int(input('Please select a song: '))
    song_select = query_list[select_input - 1]

    selectable_list = []
    for i, d_type in enumerate(song_select[5]):
        if d_type is None: continue
        selectable_list.append(f'[{i + 1}] {COLORS[i]}{d_type}{COLORS[4]}')

    print('Please select the quality: \n' + '     '.join(selectable_list))
    quality_input = int(input())
    if not song_select[5][quality_input - 1]:
        print("Please select the download options listed, you are requesting Non-Existent resource")
        exit("Exiting")
    if quality_input == 4 or quality_input == 3:
        if song_select[6][quality_input - 1][8:10] == 'sl':
            rtn = dw_from_qobuz(song_select[1], song_select[2], song_select[6][quality_input - 1])
        else:
            rtn = dw_from_main(song_select[1], song_select[2], song_select[6][quality_input - 1])
    else:
        rtn = dw_from_main(song_select[1], song_select[2], song_select[6][quality_input - 1])

    print('Download procedure finished!' if rtn else 'Download procedure failed. You can wait a while or try it again')

    # todo: should I make it public?

main.py
SnapdragonLee/MegaMDL
import re
import time
from urllib.parse import quote

import requests

from const.basic import *


def dw_from_main(name, artist, origin_url: str) -> bool:
    origin_trans_url = ripper_page + 'dl?url=' + quote(origin_url) + f'&format={mp3_format}&donotshare=true'
    s = requests.session()

    flag_origin = False
    for attempt in range(5):
        try:
            resp = s.get(url=origin_trans_url)
            if resp.status_code == 200:
                flag_origin = True
                break
        except requests.ConnectionError:
            time.sleep(0.5)
            continue
    if not flag_origin:
        print('Please check your connection or try this app after a while')
        return False

    origin_redirect = ripper_page + 'dl/' + resp.json()['id']

    dw_status = False

    while not dw_status:
        try:
            resp = s.get(url=origin_redirect)
            if resp.status_code == 200:
                content = resp.json()
                origin_status = content['status']
                dw_status = (origin_status == 'done')
                if 'percent' not in content:
                    continue
                origin_percent = content['percent']
                if origin_status != 'done':
                    process = "\r[%3s%%]: |%-50s|\033[K" % (int(origin_percent), '|' * int(origin_percent / 2))
                    time.sleep(3)
                else:
                    process = "\r[%3s%%]: |%-50s|" % (100, '|' * 50)
                print(process, end='', flush=True)

            else:
                print('Server is down, Please try again or wait a little while')
                return False
        except requests.ConnectionError:
            print('Please check your connection or try this app after a while')
            return False

    print()
    times = -1
    while times < 8:
        times += 1
        time.sleep(1)
        try:
            resp = s.get(url=ripper_page + content['url'][2:])
            if resp.status_code == 200:
                filename = os.path.basename(
                    re.sub(r'[\\/:*?<>|"]', '',
                           name + ' - ' + artist + content['url'][content['url'].rfind('.'):])
                )
                file_path = os.path.join(save_dir, filename)
                with open(file_path, 'wb') as mp3_file:
                    mp3_file.write(resp.content)
                print(f"\nThe download is completed and saved in {file_path}")
                break
        except requests.ConnectionError:
            continue
    return True


def dw_from_qobuz(name, artist, qobuz_url: str):
    s = requests.session()

    flag_qobuz = False
    for attempt in range(3):
        try:
            resp = s.get(url=qobuz_url)
            if resp.status_code == 200:
                flag_qobuz = True
                break
        except requests.ConnectionError:
            time.sleep(0.5)
            continue

    if not flag_qobuz:
        print('Please check your connection or try this app after a while')
        return False
    filename = re.sub(r'[\\/:*?<>|"]', '', os.path.basename(name + ' - ' + artist + '.flac'))
    file_path = os.path.join(save_dir, filename)
    with open(file_path, 'wb') as hires_file:
        hires_file.write(resp.content)
    print(f"\nThe download is completed and saved in {file_path}")
    return True


if __name__ == '__main__':
    dw_from_main('https://listen.tidal.com/track/96970498')

procedure/download.py
SnapdragonLee/MegaMDL
import concurrent.futures
import re

import requests

from const.basic import *


# Define a function to send POST requests and collect information
def collect_info(data, entry, sequence, mod: int):
    m128k_st = False
    hq_st = False
    sq_st = False
    hires_st = False
    type_list = []
    s = requests.session()

    try:
        response = s.post(url=detail_page, json=data)  # Replace with your actual URL and data
        if response.status_code != 200:
            raise Exception(f'Request failed with status code: {response.status_code}. Please check your network.')
    except Exception as e:
        raise Exception(f'Connection Error occurred, Please restart script!: {e}')

    # Decode the JSON response
    dat = response.json()
    links = dat['data']['item']['links']
    if 'qobuz' in links:
        if mod != 5:
            try:
                temp_q = links['qobuz'][0]['link']
                resp = requests.get(q_page + 'q=' + temp_q[temp_q.rfind('/') + 1:])
                if resp.status_code != 200:
                    raise Exception(f'Request failed with status code: {response.status_code}. Server maybe closed.')
            except Exception as e:
                raise Exception(f'Connection Error occurred, Please restart script!: {e}')
            if resp.json()['tracks']['total'] != 0:
                q_dat = resp.json()['tracks']['items'][0]
                if int(temp_q[temp_q.rfind('/') + 1:]) == q_dat['id']:
                    if q_dat['hires']:
                        hires_st = True
                        q_link = q_dw + 'id=' + str(q_dat['id'])
                    else:
                        sq_st = True
                        sq_link = q_dw + 'id=' + str(q_dat['id'])
    if mod != 2:
        if 'tidal' in links:
            sq_st = True
            sq_link = links['tidal'][0]['link']
        elif 'deezer' in links:
            sq_st = True
            sq_link = links['deezer'][0]['link']

        if 'qobuz' in links:
            hires_st = True
            q_link = links['qobuz'][0]['link']
        if 'spotify' in links:
            hq_st = True
    if 'soundcloud' in links:
        m128k_st = True
    track_name = entry['name']
    artists = ', '.join(artist['name'] for artist in entry['artists'])
    release_date = re.sub(r'T.*?Z', '', dat['data']['item']['releaseDate'])
    release_type = ['LQ' if m128k_st else None, 'HQ' if hq_st else None,
                    'SQ' if sq_st else None, 'Hi-res' if hires_st else None]

    if m128k_st: type_list.append(f"{COLORS[0]}LQ{COLORS[4]}")
    if hq_st: type_list.append(f"{COLORS[1]}HQ{COLORS[4]}")
    if sq_st: type_list.append(f"{COLORS[2]}SQ{COLORS[4]}")
    if hires_st: type_list.append(f"{COLORS[3]}Hi-res{COLORS[4]}")
    return_txt = ', '.join(type_list)

    return (sequence, track_name, artists, release_date, return_txt, release_type,
            [
                links['soundcloud'][0]['link'] if m128k_st else None,
                links['spotify'][0]['link'] if hq_st else None,
                sq_link if sq_st else None,
                q_link if hires_st else None
            ])


def collect_info_main(query_list, mod: int):
    futures = []
    with concurrent.futures.ThreadPoolExecutor() as executor:
        for entry in query_list:
            query_data = {
                'url': entry['sourceUrl'],
                'country': 'US',
            }
            futures.append(executor.submit(collect_info, query_data, entry, len(futures) + 1, mod))
        concurrent.futures.wait(futures)
    return [future.result() for future in futures]

procedure/multi.py
SnapdragonLee/MegaMDL
import requests
from tabulate import tabulate
from wcwidth import wcswidth

from const.basic import *
from procedure.multi import collect_info_main


def check_connection():
    url = search_page
    s = requests.session()
    mod = 0

    try:
        resp = s.get(url)
        if resp.status_code != 200:
            return False
    except requests.ConnectionError:
        return False

    url = ripper_page
    flag_ripper = False
    for attempt in range(3):
        try:
            resp = s.get(url, timeout=3)
            if resp.status_code == 200:
                flag_ripper = True
                mod += 1
                break
        except Exception:
            continue
    if not flag_ripper:
        mod += 2

    url = q_page
    try:
        resp = s.get(url, timeout=3)
        if resp.status_code != 200:
            mod += 4
    except Exception:
        mod += 4
    if mod < 6:
        return mod


def search_song(query: str, mod: int):
    # Build the API request URL
    search_url = search_page + f'api/songwhip/search?q={query}&country=US&limit=8'
    session = requests.session()

    try:
        response = session.get(url=search_url)
        if response.status_code == 200:
            # Decode the JSON response
            dat = response.json()
        else:
            return f'Request failed with status code: {response.status_code}. Please check your network.'
    except Exception as e:
        return f'An exception occurred: {e}'

    query_list = dat['data']['tracks']
    return collect_info_main(query_list, mod)


def check_procedure(input_str: str, mod: int):
    query_final = search_song(input_str, mod)

    if len(query_final):
        selected_column = [row[:-2] for row in query_final]
        heads = ['', 'Track Name', 'Artist(s)', 'Release Data', 'Selectable Downloads']
        column_widths = [wcswidth(str(header)) for header in heads]
        for row in selected_column:
            for i, value in enumerate(row):
                if i > 4: break
                column_widths[i] = max(column_widths[i], wcswidth(str(value)))

        alignments = ["center" for _ in heads]
        print(tabulate(selected_column, heads, colalign=alignments, tablefmt='fancy_grid',
                       maxcolwidths=column_widths))
        return query_final
    else:
        return None

procedure/search.py
SnapdragonLee/MegaMDL