|
|
@ -1,4 +1,5 @@ |
|
|
|
import asyncio |
|
|
|
import asyncio |
|
|
|
|
|
|
|
import random |
|
|
|
import subprocess |
|
|
|
import subprocess |
|
|
|
|
|
|
|
|
|
|
|
from loguru import logger |
|
|
|
from loguru import logger |
|
|
@ -15,12 +16,13 @@ from src.mp4 import extract_media, extract_song, encapsulate, write_metadata, fi |
|
|
|
from src.save import save |
|
|
|
from src.save import save |
|
|
|
from src.types import GlobalAuthParams, Codec |
|
|
|
from src.types import GlobalAuthParams, Codec |
|
|
|
from src.url import Song, Album, URLType, Artist, Playlist |
|
|
|
from src.url import Song, Album, URLType, Artist, Playlist |
|
|
|
from src.utils import check_song_exists, if_raw_atmos, playlist_write_song_index, get_codec_from_codec_id |
|
|
|
from src.utils import check_song_exists, if_raw_atmos, playlist_write_song_index, get_codec_from_codec_id, timeit |
|
|
|
|
|
|
|
|
|
|
|
task_lock = asyncio.Semaphore(16) |
|
|
|
task_lock = asyncio.Semaphore(16) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@logger.catch |
|
|
|
@logger.catch |
|
|
|
|
|
|
|
@timeit |
|
|
|
async def rip_song(song: Song, auth_params: GlobalAuthParams, codec: str, config: Config, device: Device, |
|
|
|
async def rip_song(song: Song, auth_params: GlobalAuthParams, codec: str, config: Config, device: Device, |
|
|
|
force_save: bool = False, specified_m3u8: str = "", playlist: PlaylistInfo = None): |
|
|
|
force_save: bool = False, specified_m3u8: str = "", playlist: PlaylistInfo = None): |
|
|
|
async with task_lock: |
|
|
|
async with task_lock: |
|
|
@ -80,7 +82,16 @@ async def rip_song(song: Song, auth_params: GlobalAuthParams, codec: str, config |
|
|
|
codec = get_codec_from_codec_id(codec_id) |
|
|
|
codec = get_codec_from_codec_id(codec_id) |
|
|
|
raw_song = await download_song(song_uri) |
|
|
|
raw_song = await download_song(song_uri) |
|
|
|
song_info = await extract_song(raw_song, codec) |
|
|
|
song_info = await extract_song(raw_song, codec) |
|
|
|
decrypted_song = await decrypt(song_info, keys, song_data, device) |
|
|
|
if device.hyperDecryptDevices: |
|
|
|
|
|
|
|
if all([hyper_device.decryptLock.locked() for hyper_device in device.hyperDecryptDevices]): |
|
|
|
|
|
|
|
decrypted_song = await decrypt(song_info, keys, song_data, random.choice(device.hyperDecryptDevices)) |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
for hyperDecryptDevice in device.hyperDecryptDevices: |
|
|
|
|
|
|
|
if not hyperDecryptDevice.decryptLock.locked(): |
|
|
|
|
|
|
|
decrypted_song = await decrypt(song_info, keys, song_data, hyperDecryptDevice) |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
decrypted_song = await decrypt(song_info, keys, song_data, device) |
|
|
|
song = await encapsulate(song_info, decrypted_song, config.download.atmosConventToM4a) |
|
|
|
song = await encapsulate(song_info, decrypted_song, config.download.atmosConventToM4a) |
|
|
|
if not if_raw_atmos(codec, config.download.atmosConventToM4a): |
|
|
|
if not if_raw_atmos(codec, config.download.atmosConventToM4a): |
|
|
|
metadata_song = await write_metadata(song, song_metadata, config.metadata.embedMetadata, config.download.coverFormat) |
|
|
|
metadata_song = await write_metadata(song, song_metadata, config.metadata.embedMetadata, config.download.coverFormat) |
|
|
@ -96,6 +107,7 @@ async def rip_song(song: Song, auth_params: GlobalAuthParams, codec: str, config |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@logger.catch |
|
|
|
@logger.catch |
|
|
|
|
|
|
|
@timeit |
|
|
|
async def rip_album(album: Album, auth_params: GlobalAuthParams, codec: str, config: Config, device: Device, |
|
|
|
async def rip_album(album: Album, auth_params: GlobalAuthParams, codec: str, config: Config, device: Device, |
|
|
|
force_save: bool = False): |
|
|
|
force_save: bool = False): |
|
|
|
album_info = await get_album_info(album.id, auth_params.anonymousAccessToken, album.storefront, |
|
|
|
album_info = await get_album_info(album.id, auth_params.anonymousAccessToken, album.storefront, |
|
|
@ -115,6 +127,7 @@ async def rip_album(album: Album, auth_params: GlobalAuthParams, codec: str, con |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@logger.catch |
|
|
|
@logger.catch |
|
|
|
|
|
|
|
@timeit |
|
|
|
async def rip_playlist(playlist: Playlist, auth_params: GlobalAuthParams, codec: str, config: Config, device: Device, |
|
|
|
async def rip_playlist(playlist: Playlist, auth_params: GlobalAuthParams, codec: str, config: Config, device: Device, |
|
|
|
force_save: bool = False): |
|
|
|
force_save: bool = False): |
|
|
|
playlist_info = await get_playlist_info_and_tracks(playlist.id, auth_params.anonymousAccessToken, |
|
|
|
playlist_info = await get_playlist_info_and_tracks(playlist.id, auth_params.anonymousAccessToken, |
|
|
@ -133,6 +146,7 @@ async def rip_playlist(playlist: Playlist, auth_params: GlobalAuthParams, codec: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@logger.catch |
|
|
|
@logger.catch |
|
|
|
|
|
|
|
@timeit |
|
|
|
async def rip_artist(artist: Artist, auth_params: GlobalAuthParams, codec: str, config: Config, device: Device, |
|
|
|
async def rip_artist(artist: Artist, auth_params: GlobalAuthParams, codec: str, config: Config, device: Device, |
|
|
|
force_save: bool = False, include_participate_in_works: bool = False): |
|
|
|
force_save: bool = False, include_participate_in_works: bool = False): |
|
|
|
artist_info = await get_artist_info(artist.id, artist.storefront, auth_params.anonymousAccessToken, |
|
|
|
artist_info = await get_artist_info(artist.id, artist.storefront, auth_params.anonymousAccessToken, |
|
|
|