add small tools
This commit is contained in:
parent
c10bd094da
commit
620f030d5f
20
main.py
20
main.py
@ -15,6 +15,7 @@ from modules.submenus.settings import settings_menu
|
|||||||
from modules.functions.settings.save_load_settings import load_settings
|
from modules.functions.settings.save_load_settings import load_settings
|
||||||
from modules.utils.clear_screen import cls_stay
|
from modules.utils.clear_screen import cls_stay
|
||||||
from modules.functions.mainly.load_file_song import get_lyric_from_folder
|
from modules.functions.mainly.load_file_song import get_lyric_from_folder
|
||||||
|
from modules.submenus.tools import tools_menu
|
||||||
|
|
||||||
|
|
||||||
class MainProcess(object):
|
class MainProcess(object):
|
||||||
@ -31,24 +32,27 @@ class MainProcess(object):
|
|||||||
"1": "单个歌曲的歌词下载",
|
"1": "单个歌曲的歌词下载",
|
||||||
"2": "多个歌曲的歌词下载",
|
"2": "多个歌曲的歌词下载",
|
||||||
"3": "从网易云下载的歌曲中获取歌词",
|
"3": "从网易云下载的歌曲中获取歌词",
|
||||||
|
"t": "小工具",
|
||||||
"s": "进入设置",
|
"s": "进入设置",
|
||||||
"i": "程序信息",
|
"i": "程序信息",
|
||||||
})
|
})
|
||||||
r = rinput("请选择:")
|
r = rinput("请选择:")
|
||||||
|
match r:
|
||||||
if r == "1":
|
case "1":
|
||||||
download_one_lyric(self)
|
download_one_lyric(self)
|
||||||
elif r == "2":
|
case "2":
|
||||||
mdl(self)
|
mdl(self)
|
||||||
elif r == "3":
|
case "3":
|
||||||
get_lyric_from_folder(self)
|
get_lyric_from_folder(self)
|
||||||
elif r == "0":
|
case "0":
|
||||||
exit(0)
|
exit(0)
|
||||||
elif r == "i":
|
case "t":
|
||||||
|
tools_menu(self)
|
||||||
|
case "i":
|
||||||
print_info(self)
|
print_info(self)
|
||||||
elif r == "s":
|
case "s":
|
||||||
settings_menu(self)
|
settings_menu(self)
|
||||||
else:
|
case _:
|
||||||
input("请输入正确的选项\n按回车键继续...")
|
input("请输入正确的选项\n按回车键继续...")
|
||||||
|
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ def get_lyric_from_folder(self):
|
|||||||
suffix="", max=len(ncm_files), color="green", width=9999) as bar:
|
suffix="", max=len(ncm_files), color="green", width=9999) as bar:
|
||||||
total = len(ncm_files)
|
total = len(ncm_files)
|
||||||
allocated = 0 # 已经分配的任务数量
|
allocated = 0 # 已经分配的任务数量
|
||||||
while True: # 进入循环,执行 新建进程->检测队列->检测任务完成 的循环
|
while True: # 进入循环,执行 "新建进程->检测队列->检测任务完成" 的循环
|
||||||
sleep(0.05)
|
sleep(0.05)
|
||||||
if current_process <= max_process and allocated < total: # 分配进程
|
if current_process <= max_process and allocated < total: # 分配进程
|
||||||
Process(target=process_work,
|
Process(target=process_work,
|
||||||
@ -176,7 +176,7 @@ def get_lyric_from_folder(self):
|
|||||||
passed += 1
|
passed += 1
|
||||||
current_process -= 1
|
current_process -= 1
|
||||||
bar.print_onto_bar(Fore.YELLOW +
|
bar.print_onto_bar(Fore.YELLOW +
|
||||||
f"\"{r['musicName']} - "
|
f"\"{r['musicName']} by "
|
||||||
f"{''.join([x + ', ' for x in [x[0] for x in r['artist']]])[:-2]}"
|
f"{''.join([x + ', ' for x in [x[0] for x in r['artist']]])[:-2]}"
|
||||||
"\"" + Fore.GREEN + " 已完成!")
|
"\"" + Fore.GREEN + " 已完成!")
|
||||||
bar.next()
|
bar.next()
|
||||||
|
@ -6,7 +6,6 @@ from modules.utils.inputs import rinput
|
|||||||
from modules.functions.mainly.get_song import get_song_lyric
|
from modules.functions.mainly.get_song import get_song_lyric
|
||||||
from modules.utils.bar import CompactArrowBar
|
from modules.utils.bar import CompactArrowBar
|
||||||
|
|
||||||
|
|
||||||
def mdl(self):
|
def mdl(self):
|
||||||
"""多个歌词文件的下载
|
"""多个歌词文件的下载
|
||||||
|
|
||||||
@ -34,7 +33,7 @@ def mdl(self):
|
|||||||
with CompactArrowBar(f"进度: %(index){len(str(len(ids)))}d/%(max)d",
|
with CompactArrowBar(f"进度: %(index){len(str(len(ids)))}d/%(max)d",
|
||||||
suffix="", max=len(ids), color="yellow", width=9999) as bar:
|
suffix="", max=len(ids), color="yellow", width=9999) as bar:
|
||||||
for i in range(0, len(ids)):
|
for i in range(0, len(ids)):
|
||||||
r = get_song_lyric(ids[i], self.settings.lyric_path, self.settings.lyric_path, bar=bar)
|
r = get_song_lyric(ids[i], self.settings.lyric_path, self.settings.lyric_format, bar=bar)
|
||||||
if r == "dl_err_connection":
|
if r == "dl_err_connection":
|
||||||
bar.print_onto_bar(Fore.RED + "下载发生错误!可能是连接被拒绝!请检查网络后再试\n按回车键继续任务(该任务会被跳过)...")
|
bar.print_onto_bar(Fore.RED + "下载发生错误!可能是连接被拒绝!请检查网络后再试\n按回车键继续任务(该任务会被跳过)...")
|
||||||
input()
|
input()
|
||||||
|
3
modules/functions/mainly/multi_unlock.py
Normal file
3
modules/functions/mainly/multi_unlock.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
|
def mult_unlock(...)
|
@ -24,19 +24,20 @@ def settings_menu(self):
|
|||||||
"4": "部分动态效果",
|
"4": "部分动态效果",
|
||||||
"s": "切换设置自动保存"
|
"s": "切换设置自动保存"
|
||||||
})
|
})
|
||||||
if r == "0":
|
match r:
|
||||||
|
case "0":
|
||||||
return
|
return
|
||||||
elif r == "1":
|
case "1":
|
||||||
__set_lyric_path(self)
|
__set_lyric_path(self)
|
||||||
elif r == "2":
|
case "2":
|
||||||
__remove_output_files(self)
|
__remove_output_files(self)
|
||||||
elif r == "3":
|
case "3":
|
||||||
__set_lyric_format(self)
|
__set_lyric_format(self)
|
||||||
elif r == "4":
|
case "4":
|
||||||
pass
|
pass
|
||||||
elif r == "s":
|
case "s":
|
||||||
self.settings.auto_save = not self.settings.auto_save
|
self.settings.auto_save = not self.settings.auto_save
|
||||||
else:
|
case _:
|
||||||
input("输入无效!按回车键继续...")
|
input("输入无效!按回车键继续...")
|
||||||
|
|
||||||
|
|
||||||
|
50
modules/submenus/tools.py
Normal file
50
modules/submenus/tools.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
"""小工具以及菜单"""
|
||||||
|
import os
|
||||||
|
from colorama import Fore
|
||||||
|
|
||||||
|
from modules.utils.prints import print_menu
|
||||||
|
from modules.utils.clear_screen import cls_stay
|
||||||
|
from modules.utils.inputs import cinput
|
||||||
|
from modules.functions.mainly.load_file_song import load_and_decrypt_from_ncm, process_work
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def tools_menu(self):
|
||||||
|
while True:
|
||||||
|
cls_stay(self, "[小工具菜单]")
|
||||||
|
print_menu({
|
||||||
|
"0": "返回上级菜单",
|
||||||
|
"d": "解锁指定ncm文件/指定文件夹"
|
||||||
|
})
|
||||||
|
r = cinput("请选择:")
|
||||||
|
match r:
|
||||||
|
case "0":
|
||||||
|
return
|
||||||
|
case "d":
|
||||||
|
ncm_unlock(self)
|
||||||
|
input("按回车继续...")
|
||||||
|
case _:
|
||||||
|
input("请输入正确的选项\n按回车键继续...")
|
||||||
|
|
||||||
|
|
||||||
|
def ncm_unlock(self):
|
||||||
|
cls_stay(self, "[小工具 - 文件解锁]")
|
||||||
|
path = cinput("请输入绝对路径:").replace("\\","")
|
||||||
|
if not os.path.exists(path): # 判断目标存在与否
|
||||||
|
print("目标不存在!")
|
||||||
|
return
|
||||||
|
if os.path.isfile(path): # 目标为文件则执行单文件解密
|
||||||
|
r = load_and_decrypt_from_ncm(path, os.path.split(path)[-1], "original", True)
|
||||||
|
match r:
|
||||||
|
case "file_not_found":
|
||||||
|
print("文件未找到")
|
||||||
|
case "perm_error":
|
||||||
|
print("权限错误。请检查是否拥有对应权限或者文件是否被占用。")
|
||||||
|
case _:
|
||||||
|
print(f"解锁完毕!文件保存在:\n{Fore.GREEN}{r[-1]}")
|
||||||
|
return
|
||||||
|
elif os.path.isdir(path): # 目标为文件夹则执行文件夹遍历
|
||||||
|
...
|
||||||
|
else:
|
||||||
|
print("无法识别目标文件。请确认目标文件是否正确以及是否拥有对应权限。")
|
||||||
|
|
@ -8,6 +8,7 @@ from Cryptodome.Cipher import AES
|
|||||||
from Cryptodome.Util.Padding import unpad
|
from Cryptodome.Util.Padding import unpad
|
||||||
from Cryptodome.Util.strxor import strxor as xor
|
from Cryptodome.Util.strxor import strxor as xor
|
||||||
from mutagen import mp3, flac, id3
|
from mutagen import mp3, flac, id3
|
||||||
|
from modules.utils.wrappers import escape_file_not_found, escape_permission_error
|
||||||
|
|
||||||
|
|
||||||
def regular_filename(filename):
|
def regular_filename(filename):
|
||||||
@ -28,7 +29,14 @@ def regular_filename(filename):
|
|||||||
return filename
|
return filename
|
||||||
|
|
||||||
|
|
||||||
def load_and_decrypt_from_ncm(file_path, target_dir, out_format) -> dict | str: # author: Nzix Repo: nondanee
|
@escape_file_not_found
|
||||||
|
@escape_permission_error
|
||||||
|
def load_and_decrypt_from_ncm(file_path, target_dir, out_format, return_output_path=False) -> dict | str | tuple:
|
||||||
|
# Original author: Nzix Repo: nondanee
|
||||||
|
"""解锁指定文件并按照规则保存在指定位置
|
||||||
|
``file_path`` 源文件路径
|
||||||
|
``target_dir`` 解锁后文件保存路径
|
||||||
|
``out_format`` 输出文件格式,使用“字典”格式字符串,若使用源文件名仅替换后缀则传入\"original\""""
|
||||||
|
|
||||||
core_key = binascii.a2b_hex('687A4852416D736F356B496E62617857')
|
core_key = binascii.a2b_hex('687A4852416D736F356B496E62617857')
|
||||||
meta_key = binascii.a2b_hex('2331346C6A6B5F215C5D2630553C2728')
|
meta_key = binascii.a2b_hex('2331346C6A6B5F215C5D2630553C2728')
|
||||||
@ -89,7 +97,9 @@ def load_and_decrypt_from_ncm(file_path, target_dir, out_format) -> dict | str:
|
|||||||
f.seek(image_space - image_size, 1)
|
f.seek(image_space - image_size, 1)
|
||||||
|
|
||||||
# media data
|
# media data
|
||||||
if meta_length:
|
if out_format == "original":
|
||||||
|
output_path = f"{os.path.splitext(file_path)[0]}.{meta_data['format']}"
|
||||||
|
elif meta_length:
|
||||||
output_path = os.path.join(target_dir, regular_filename(out_format % {"name": meta_data["musicName"],
|
output_path = os.path.join(target_dir, regular_filename(out_format % {"name": meta_data["musicName"],
|
||||||
"artists": "".join(
|
"artists": "".join(
|
||||||
[x[0]+"," for x in meta_data["artist"]]
|
[x[0]+"," for x in meta_data["artist"]]
|
||||||
@ -145,6 +155,12 @@ def load_and_decrypt_from_ncm(file_path, target_dir, out_format) -> dict | str:
|
|||||||
audio['album'] = meta_data['album']
|
audio['album'] = meta_data['album']
|
||||||
audio['artist'] = '/'.join([artist[0] for artist in meta_data['artist']])
|
audio['artist'] = '/'.join([artist[0] for artist in meta_data['artist']])
|
||||||
audio.save()
|
audio.save()
|
||||||
|
if return_output_path:
|
||||||
|
return meta_data, output_path
|
||||||
|
else:
|
||||||
return meta_data
|
return meta_data
|
||||||
|
else:
|
||||||
|
if return_output_path:
|
||||||
|
return "no_meta_data", output_path
|
||||||
else:
|
else:
|
||||||
return "no_meta_data"
|
return "no_meta_data"
|
||||||
|
28
modules/utils/wrappers.py
Normal file
28
modules/utils/wrappers.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
"""一些有的没有的装饰器"""
|
||||||
|
|
||||||
|
|
||||||
|
def escape_file_not_found(func):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
try:
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
except FileNotFoundError:
|
||||||
|
return "file_not_found"
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
def escape_decrypt_unsatisfied_file(func):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
try:
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
except (AssertionError, IsADirectoryError):
|
||||||
|
return "file_not_satisfied"
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
def escape_permission_error(func):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
try:
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
except PermissionError:
|
||||||
|
return "perm_error"
|
||||||
|
return wrapper
|
Loading…
Reference in New Issue
Block a user