Skip to content
This repository was archived by the owner on Jun 3, 2024. It is now read-only.

Cleaned cli bit and allow more file extentions #5

Merged
merged 1 commit into from
Aug 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

## What is mmdl ❓

MMDL is a cli app which allows you to quickly and efficiently download one or multiple songs from YouTube.
**TLDR**: MMDL is a cli app which allows you to quickly and efficiently download one or multiple songs from YouTube.

I wanted a tool to quickly and efficiently download songs/audios from YouTube based on the name of the song. I also wanted the songs to be tagged with metadata. This is why I created this simple to use tool.

### Why

Expand Down
Binary file added images/mmdl_go.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/mmdl_help.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion mmdl.egg-info/PKG-INFO
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ License-File: LICENSE

## What is mmdl ❓

MMDL is a cli app which allows you to quickly and efficiently download one or multiple songs from YouTube.
**TLDR**: MMDL is a cli app which allows you to quickly and efficiently download one or multiple songs from YouTube.

I wanted a tool to quickly and efficiently download songs/audios from YouTube based on the name of the song. I also wanted the songs to be tagged with metadata. This is why I created this simple to use tool.

### Why

Expand Down
1 change: 0 additions & 1 deletion mmdl.egg-info/SOURCES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ mmdl/__init__.py
mmdl/ask.py
mmdl/cli.py
mmdl/globals.py
mmdl/mdl.py
mmdl/utils.py
mmdl/yt_utils.py
mmdl.egg-info/PKG-INFO
Expand Down
117 changes: 33 additions & 84 deletions mmdl/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from mmdl import MusicDownloader
from .ask import asker
from rich.console import Console
from .utils import *
import questionary
console = Console()
from click_help_colors import HelpColorsGroup, HelpColorsCommand
Expand Down Expand Up @@ -50,23 +51,15 @@ def go(verbose, debug):
# Go Command
> Easy way to download songs. Uses inputs/inquirer. (Simply run 'mmdl go')
"""
print_logo()

if debug:
console.log("Verbose: ", verbose)
console.log("Debug: ", debug)

console.print("""\b[red]
_ _
| | |
_ __ ___ _ __ ___ __| | |
| '_ ` _ \| '_ ` _ \ / _` | |
| | | | | | | | | | | (_| | | [/]by techboy-coder[red]
|_| |_| |_|_| |_| |_|\__,_|_| [/]find me on https://github.com/techboy-coder

[green]mmdl [Mega Music Downloader] - A tool to easily download music.[/green]
""")

song_names=asker()
console.print("\n[cyan]> [/] Total number of songs: %s. \n" % (len(song_names)))
num_of_songs_printer(len(song_names))
# List, verbose, debug
MusicDownloader(song_names, verbose, debug).download_songs()

Expand Down Expand Up @@ -114,19 +107,11 @@ def file(file, seperator, verbose, debug):
console.log("Verbose: ", verbose)
console.log("Debug: ", debug)

console.print("""\b[red]
_ _
| | |
_ __ ___ _ __ ___ __| | |
| '_ ` _ \| '_ ` _ \ / _` | |
| | | | | | | | | | | (_| | | [/]by techboy-coder[red]
|_| |_| |_|_| |_| |_|\__,_|_| [/]find me on https://github.com/techboy-coder

[green]mmdl [Mega Music Downloader] - A tool to easily download music.[/green]
""")
console.print("\n[cyan]> [/] Total number of songs: %s. \n" % (len(songs)))
if not questionary.confirm("Do you want to continue").ask():
quit()
print_logo()

num_of_songs_printer(len(songs))

wanna_continue()
# file, verbose, debug
MusicDownloader(songs, verbose, debug).download_songs()
return
Expand Down Expand Up @@ -174,17 +159,8 @@ def list(songs, verbose, debug, ask):
console.log("Verbose: ", verbose)
console.log("Debug: ", debug)

console.print("""\b[red]
_ _
| | |
_ __ ___ _ __ ___ __| | |
| '_ ` _ \| '_ ` _ \ / _` | |
| | | | | | | | | | | (_| | | [/]by techboy-coder[red]
|_| |_| |_|_| |_| |_|\__,_|_| [/]find me on https://github.com/techboy-coder

[green]mmdl [Mega Music Downloader] - A tool to easily download music.[/green]
""")
console.print("\n[cyan]> [/] Total number of songs: %s. \n" % (len(songs_list)))
print_logo()
num_of_songs_printer(len(songs_list))
# file, verbose, debug
MusicDownloader(songs_list, verbose, debug).download_songs()
return
Expand All @@ -209,66 +185,48 @@ def ytmusic(file, verbose, debug, ask):
"""
if not ask and not file:
ask = True
if ask:
console.print("[cyan][>][/] We'll be manually asking you for the file location.")
console.print("""

guide = """
[bold red]YT-Music[/bold red].
- Go to your YTMusic liked songs playlist (https://music.youtube.com/playlist?list=LM)
- Make sure you are logged in
- Press Ctrl/Cmd + Shift + i and open the dev tools
- Keep scrolling down until you reach the end of your playlist (Songs will stop loading)
- Copy the all the html markup
- Create a text file and paste the html into it.
""")
if not questionary.confirm("Only continue if you have done the task.").ask():
quit()
"""

if ask:
console.print("[cyan][>][/] We'll be manually asking you for the file location.")
console.print(guide)
wanna_continue("Only continue if you have done the task.")

file = questionary.path("Where is that file located?").ask()
with open(file, "r", encoding="utf-8") as f:
data = f.read()
h = fromstring(data)
sel = CSSSelector("yt-formatted-string.title.style-scope.ytmusic-responsive-list-item-renderer.complex-string > a.yt-simple-endpoint.style-scope.yt-formatted-string")
songs_list=[e.text for e in sel(h)]
if not songs_list[0]:
console.log("[red][-] Hmm. No songs could be parsed from html. Did you select the correct HTML? If you see a error please make a bug report. Thanks!")
quit()

if not ask:
if not file:
console.log("[red][-] You need to enter the file location or add the -a flag.")
quit()
data = file.read()
h = fromstring(data)
sel = CSSSelector("yt-formatted-string.title.style-scope.ytmusic-responsive-list-item-renderer.complex-string > a.yt-simple-endpoint.style-scope.yt-formatted-string")
songs_list=[e.text for e in sel(h)]
if not songs_list[0]:
console.log("[red][-] Hmm. No songs could be parsed from html. Did you select the correct HTML? If you see a error please make a bug report. Thanks!")
console.print("""
[bold red]YT-Music[/bold red].
- Go to your YTMusic liked songs playlist (https://music.youtube.com/playlist?list=LM)
- Make sure you are logged in
- Press Ctrl/Cmd + Shift + i and open the dev tools
- Keep scrolling down until you reach the end of your playlist (Songs will stop loading)
- Copy the all the html markup
- Create a text file and paste the html into it.
""")


h = fromstring(data)
sel = CSSSelector("yt-formatted-string.title.style-scope.ytmusic-responsive-list-item-renderer.complex-string > a.yt-simple-endpoint.style-scope.yt-formatted-string")
songs_list=[e.text for e in sel(h)]
if not songs_list[0]:
console.log("[red][-] Hmm. No songs could be parsed from html. Did you select the correct HTML? If you see a error please make a bug report. Thanks!")
console.print(guide)


if debug:
console.log("Songs: ", str(songs_list))
console.log("Verbose: ", verbose)
console.log("Debug: ", debug)
console.print("""\b[red]
_ _
| | |
_ __ ___ _ __ ___ __| | |
| '_ ` _ \| '_ ` _ \ / _` | |
| | | | | | | | | | | (_| | | [/]by techboy-coder[red]
|_| |_| |_|_| |_| |_|\__,_|_| [/]find me on https://github.com/techboy-coder

[green]mmdl [Mega Music Downloader] - A tool to easily download music.[/green]
""")
console.print("\n[cyan]> [/] Total number of songs: %s. \n" % (len(songs_list)))
if not questionary.confirm("Do you want to continue").ask():
quit()
print_logo()
num_of_songs_printer(len(songs_list))
wanna_continue()
# file, verbose, debug
MusicDownloader(songs_list, verbose, debug).download_songs()
return
Expand Down Expand Up @@ -300,16 +258,7 @@ def single(song, verbose, debug):
console.log("Verbose: ", verbose)
console.log("Debug: ", debug)

console.print("""\b[red]
_ _
| | |
_ __ ___ _ __ ___ __| | |
| '_ ` _ \| '_ ` _ \ / _` | |
| | | | | | | | | | | (_| | | [/]by techboy-coder[red]
|_| |_| |_|_| |_| |_|\__,_|_| [/]find me on https://github.com/techboy-coder

[green]mmdl [Mega Music Downloader] - A tool to easily download music.[/green]
""")
print_logo()
songs = [song]
console.print("\n[cyan]> [/] Song: %s. \n" % (song))
# file, verbose, debug
Expand Down
76 changes: 1 addition & 75 deletions mmdl/mdl.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,81 +36,6 @@
##Dev Dep
import shutil

class DisplayablePath(object):
display_filename_prefix_middle = '├──'
display_filename_prefix_last = '└──'
display_parent_prefix_middle = ' '
display_parent_prefix_last = '│ '

def __init__(self, path, parent_path, is_last):
self.path = Path(str(path))
self.parent = parent_path
self.is_last = is_last
if self.parent:
self.depth = self.parent.depth + 1
else:
self.depth = 0

@property
def displayname(self):
if self.path.is_dir():
return self.path.name + '/'
return self.path.name

@classmethod
def make_tree(cls, root, parent=None, is_last=False, criteria=None):
root = Path(str(root))
criteria = criteria or cls._default_criteria

displayable_root = cls(root, parent, is_last)
yield displayable_root

children = sorted(list(path
for path in root.iterdir()
if criteria(path)),
key=lambda s: str(s).lower())
count = 1
for path in children:
is_last = count == len(children)
if path.is_dir():
yield from cls.make_tree(path,
parent=displayable_root,
is_last=is_last,
criteria=criteria)
else:
yield cls(path, displayable_root, is_last)
count += 1

@classmethod
def _default_criteria(cls, path):
return True

@property
def displayname(self):
if self.path.is_dir():
return self.path.name + '/'
return self.path.name

def displayable(self):
if self.parent is None:
return self.displayname

_filename_prefix = (self.display_filename_prefix_last
if self.is_last
else self.display_filename_prefix_middle)

parts = ['{!s} {!s}'.format(_filename_prefix,
self.displayname)]

parent = self.parent
while parent and parent.parent is not None:
parts.append(self.display_parent_prefix_middle
if parent.is_last
else self.display_parent_prefix_last)
parent = parent.parent

return ''.join(reversed(parts))

class MusicDownloader():
def __init__(self, song_names: list[str], verbose: int, debug: bool):
"""Music Downloader Class. This is the main class :/
Expand Down Expand Up @@ -171,6 +96,7 @@ def download_songs(self): # sourcery no-metrics
]
temp = []
cwd = Utils.get_cwd()

for f in filenames:
# print(f["filename"])
does_exist = executor.submit(Utils.check_file_exists, f["filename"], f)
Expand Down
37 changes: 36 additions & 1 deletion mmdl/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
from pathlib import Path
from rich.logging import RichHandler
import concurrent.futures
from rich.console import Console
import questionary
console = Console()

# log=logging

Expand Down Expand Up @@ -58,4 +61,36 @@ def check_file_exists(filepath: str, rest):
# print("lkj")
# print(path, filepath)
# print(Path(path+"/"+filepath).is_file())
return [Path(filepath).is_file(), rest]
# if any(File.endswith(".mp3") or File.endswith(".mp3") for File in os.listdir(".")):
# return True
# return False
exists=Path(os.path.splitext(filepath)[0]+".mp3").is_file() or Path(os.path.splitext(filepath)[0]+".m4a").is_file() or Path(os.path.splitext(filepath)[0]+".opus").is_file()
return [exists, rest]


def print_logo():
console.print("""\b[red]
_ _
| | |
_ __ ___ _ __ ___ __| | |
| '_ ` _ \| '_ ` _ \ / _` | |
| | | | | | | | | | | (_| | | [/]by techboy-coder[red]
|_| |_| |_|_| |_| |_|\__,_|_| [/]find me on https://github.com/techboy-coder

[green]mmdl [Mega Music Downloader] - A tool to easily download music.[/green]
""")

def num_of_songs_printer(num):
console.print("\n[cyan]> [/] Total number of songs: %s. \n" % (num))

def wanna_continue(msg="Do you want to continue"):
if not questionary.confirm(msg).ask():
quit()

def check_file(filename):
possible_extensions = ('', '.txt', '.dat')
for e in possible_extensions:
if os.path.isfile(filename + e):
return filename + e
else:
return None
6 changes: 1 addition & 5 deletions mmdl/yt_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def __init__(self, mmdl: bool):
{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
# 'preferredquality': '192',
}
],
'outtmpl': str(self.output_dir)+'/%(title)s.%(ext)s',
Expand All @@ -40,15 +40,11 @@ def download(self, url: str, do_download: bool, rest: None):
with youtube_dl.YoutubeDL(self.ytdl_opts) as ydl:
info = ydl.extract_info(url, download=True)
filename = ydl.prepare_filename(info)
filename = filename.replace("webm","mp3")
filename = filename.replace("m4a", "mp3")
return {"filename": filename, "url": url, "rest":rest}
else:
with youtube_dl.YoutubeDL(self.ytdl_opts) as ydl:
info = ydl.extract_info(url, download=False)
filename = ydl.prepare_filename(info)
filename = filename.replace("webm","mp3")
filename = filename.replace("m4a", "mp3")
return {"filename": filename, "url": url, "rest":rest}

def logger(self):
Expand Down