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

Commit 60a4303

Browse files
Merge pull request #7 from techboy-coder/dev
2 parents 40bda50 + 50746bf commit 60a4303

21 files changed

+184
-360
lines changed

README.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
![mmdl](https://raw.githubusercontent.com/techboy-coder/mmdl/main/mmdl%20image.png)
1+
![mmdl](mmdl_image.png)
22

33
# mmdl - Mega Music Downloader
44

55
![License](https://img.shields.io/pypi/l/mmdl?style=for-the-badge) ![PyPI](https://img.shields.io/pypi/v/mmdl?style=for-the-badge) ![Downloads](https://img.shields.io/pypi/dw/mmdl?style=for-the-badge)
66

77
## What is mmdl ❓
88

9-
MMDL is a cli app which allows you to quickly and efficiently download one or multiple songs from YouTube.
9+
**TLDR**: MMDL is a cli app which allows you to quickly and efficiently download one or multiple songs from YouTube.
10+
11+
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.
1012

1113
### Why
1214

@@ -68,15 +70,15 @@ Please [open a issue](https://github.com/techboy-coder/mmdl/issues/new) with som
6870

6971
### Questions ❓
7072

71-
Please [start/check a discussion](https://github.com/techboy-coder/mmdl/discussions/new).
73+
Please [start/search for a discussion](https://github.com/techboy-coder/mmdl/discussions/new).
7274

7375
## Contributing 🤜
7476

75-
We welcome contributions very much. They are appreciated.
77+
We welcome contributions very much (Even small ones). They are appreciated.
7678

7779
### Steps
7880

79-
1. Check for bugs/issues you would like to solve.
81+
1. Check for bugs/issues you would like to solve or think of new features you would like to implement.
8082
2. Fork the repo and make your changes.
8183
3. Send a pull request.
8284

@@ -89,7 +91,11 @@ We welcome contributions very much. They are appreciated.
8991
- https://github.com/willmcgugan/rich - Rich by Will McGugan
9092
- https://github.com/ytdl-org/youtube-dl - YoutubeDl
9193

92-
## License ⚖️
94+
## Legality ⚖️
95+
96+
**I assume no liability or responsibility for how this app is used.** Please stay legal and respect the laws in your country. This tool is intended for archiving music for which you have a license.
97+
98+
## License 📜
9399

94100
The MIT License (MIT)
95101

build/lib/mmdl/ask.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,17 @@ def asker():
2323
).ask()
2424

2525
if single_songs == "One song":
26-
return [questionary.text("What is the song name").ask()]
26+
return [questionary.text("What is the song name?").ask()]
2727
else:
2828
input_method = questionary.select(
29-
"Which songs do you want to download?",
29+
"How do you want to download?",
3030
choices=[
31-
"Songs, comma seperated",
31+
"Write song titles, comma seperated",
3232
'List in textfile (1 Song per line)',
3333
'From YTMusic (beta)',
3434
]).ask() # returns value of selection
3535

36-
if input_method == "From YTMusic":
36+
if input_method == "From YTMusic (beta)":
3737
console.print("""[bold red]YT-Music[/bold red].
3838
- Go to your YTMusic liked songs playlist (https://music.youtube.com/playlist?list=LM)
3939
- Make sure you are logged in
@@ -57,8 +57,8 @@ def asker():
5757
text_file = open(file ,encoding='utf-8')
5858
songs_list = text_file.read().splitlines()
5959
return songs_list
60-
elif input_method=="Songs, comma seperated":
61-
songs_list = questionary.text("Write all songs (comma seperated)").ask().split(",")
60+
elif input_method=="Write song titles, comma seperated":
61+
songs_list = questionary.text("Write all songs (comma seperated):").ask().split(",")
6262
return songs_list
6363
except Exception as e:
6464
## eventually change :/

build/lib/mmdl/cli.py

Lines changed: 35 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from mmdl import MusicDownloader
1818
from .ask import asker
1919
from rich.console import Console
20+
from .utils import *
2021
import questionary
2122
console = Console()
2223
from click_help_colors import HelpColorsGroup, HelpColorsCommand
@@ -50,23 +51,15 @@ def go(verbose, debug):
5051
# Go Command
5152
> Easy way to download songs. Uses inputs/inquirer. (Simply run 'mmdl go')
5253
"""
54+
print_logo()
5355

5456
if debug:
5557
console.log("Verbose: ", verbose)
5658
console.log("Debug: ", debug)
5759

58-
console.print("""\b[red]
59-
_ _
60-
| | |
61-
_ __ ___ _ __ ___ __| | |
62-
| '_ ` _ \| '_ ` _ \ / _` | |
63-
| | | | | | | | | | | (_| | | [/]by techboy-coder[red]
64-
|_| |_| |_|_| |_| |_|\__,_|_| [/]find me on https://github.com/techboy-coder
65-
66-
[green]mmdl [Mega Music Downloader] - A tool to easily download music.[/green]
67-
""")
60+
6861
song_names=asker()
69-
console.print("\n[cyan]> [/] Total number of songs: %s. \n" % (len(song_names)))
62+
num_of_songs_printer(len(song_names))
7063
# List, verbose, debug
7164
MusicDownloader(song_names, verbose, debug).download_songs()
7265

@@ -114,19 +107,11 @@ def file(file, seperator, verbose, debug):
114107
console.log("Verbose: ", verbose)
115108
console.log("Debug: ", debug)
116109

117-
console.print("""\b[red]
118-
_ _
119-
| | |
120-
_ __ ___ _ __ ___ __| | |
121-
| '_ ` _ \| '_ ` _ \ / _` | |
122-
| | | | | | | | | | | (_| | | [/]by techboy-coder[red]
123-
|_| |_| |_|_| |_| |_|\__,_|_| [/]find me on https://github.com/techboy-coder
124-
125-
[green]mmdl [Mega Music Downloader] - A tool to easily download music.[/green]
126-
""")
127-
console.print("\n[cyan]> [/] Total number of songs: %s. \n" % (len(songs)))
128-
if not questionary.confirm("Do you want to continue").ask():
129-
quit()
110+
print_logo()
111+
112+
num_of_songs_printer(len(songs))
113+
114+
wanna_continue()
130115
# file, verbose, debug
131116
MusicDownloader(songs, verbose, debug).download_songs()
132117
return
@@ -153,14 +138,14 @@ def list(songs, verbose, debug, ask):
153138
"""
154139
if ask:
155140
console.print("[cyan][>][/] We'll be manually asking you for songs.")
156-
songs_list = questionary.text("Write all songs search terms (comma seperated)").ask()
141+
songs_list = questionary.text("Write all songs search terms (comma seperated): ").ask()
157142
if not songs_list:
158143
quit()
159144
songs_list = songs_list.split(",")
160145
else:
161146
if len(songs) < 1:
162147
# console.print("[cyan][-][/] You didn't specify any songs. So we'll be manually asking them to you.")
163-
songs_list = questionary.text("Write all songs search terms (comma seperated)").ask()
148+
songs_list = questionary.text("Write all songs search terms (comma seperated):").ask()
164149
if not songs_list:
165150
quit()
166151
songs_list = songs_list.split(",")
@@ -174,17 +159,8 @@ def list(songs, verbose, debug, ask):
174159
console.log("Verbose: ", verbose)
175160
console.log("Debug: ", debug)
176161

177-
console.print("""\b[red]
178-
_ _
179-
| | |
180-
_ __ ___ _ __ ___ __| | |
181-
| '_ ` _ \| '_ ` _ \ / _` | |
182-
| | | | | | | | | | | (_| | | [/]by techboy-coder[red]
183-
|_| |_| |_|_| |_| |_|\__,_|_| [/]find me on https://github.com/techboy-coder
184-
185-
[green]mmdl [Mega Music Downloader] - A tool to easily download music.[/green]
186-
""")
187-
console.print("\n[cyan]> [/] Total number of songs: %s. \n" % (len(songs_list)))
162+
print_logo()
163+
num_of_songs_printer(len(songs_list))
188164
# file, verbose, debug
189165
MusicDownloader(songs_list, verbose, debug).download_songs()
190166
return
@@ -209,66 +185,48 @@ def ytmusic(file, verbose, debug, ask):
209185
"""
210186
if not ask and not file:
211187
ask = True
212-
if ask:
213-
console.print("[cyan][>][/] We'll be manually asking you for the file location.")
214-
console.print("""
188+
189+
guide = """
215190
[bold red]YT-Music[/bold red].
216191
- Go to your YTMusic liked songs playlist (https://music.youtube.com/playlist?list=LM)
217192
- Make sure you are logged in
218193
- Press Ctrl/Cmd + Shift + i and open the dev tools
219194
- Keep scrolling down until you reach the end of your playlist (Songs will stop loading)
220195
- Copy the all the html markup
221196
- Create a text file and paste the html into it.
222-
""")
223-
if not questionary.confirm("Only continue if you have done the task.").ask():
224-
quit()
197+
"""
198+
199+
if ask:
200+
console.print("[cyan][>][/] We'll be manually asking you for the file location.")
201+
console.print(guide)
202+
wanna_continue("Only continue if you have done the task.")
203+
225204
file = questionary.path("Where is that file located?").ask()
226205
with open(file, "r", encoding="utf-8") as f:
227206
data = f.read()
228-
h = fromstring(data)
229-
sel = CSSSelector("yt-formatted-string.title.style-scope.ytmusic-responsive-list-item-renderer.complex-string > a.yt-simple-endpoint.style-scope.yt-formatted-string")
230-
songs_list=[e.text for e in sel(h)]
231-
if not songs_list[0]:
232-
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!")
233-
quit()
207+
234208
if not ask:
235209
if not file:
236210
console.log("[red][-] You need to enter the file location or add the -a flag.")
237211
quit()
238212
data = file.read()
239-
h = fromstring(data)
240-
sel = CSSSelector("yt-formatted-string.title.style-scope.ytmusic-responsive-list-item-renderer.complex-string > a.yt-simple-endpoint.style-scope.yt-formatted-string")
241-
songs_list=[e.text for e in sel(h)]
242-
if not songs_list[0]:
243-
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!")
244-
console.print("""
245-
[bold red]YT-Music[/bold red].
246-
- Go to your YTMusic liked songs playlist (https://music.youtube.com/playlist?list=LM)
247-
- Make sure you are logged in
248-
- Press Ctrl/Cmd + Shift + i and open the dev tools
249-
- Keep scrolling down until you reach the end of your playlist (Songs will stop loading)
250-
- Copy the all the html markup
251-
- Create a text file and paste the html into it.
252-
""")
213+
214+
215+
h = fromstring(data)
216+
sel = CSSSelector("yt-formatted-string.title.style-scope.ytmusic-responsive-list-item-renderer.complex-string > a.yt-simple-endpoint.style-scope.yt-formatted-string")
217+
songs_list=[e.text for e in sel(h)]
218+
if not songs_list[0]:
219+
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!")
220+
console.print(guide)
253221

254222

255223
if debug:
256224
console.log("Songs: ", str(songs_list))
257225
console.log("Verbose: ", verbose)
258226
console.log("Debug: ", debug)
259-
console.print("""\b[red]
260-
_ _
261-
| | |
262-
_ __ ___ _ __ ___ __| | |
263-
| '_ ` _ \| '_ ` _ \ / _` | |
264-
| | | | | | | | | | | (_| | | [/]by techboy-coder[red]
265-
|_| |_| |_|_| |_| |_|\__,_|_| [/]find me on https://github.com/techboy-coder
266-
267-
[green]mmdl [Mega Music Downloader] - A tool to easily download music.[/green]
268-
""")
269-
console.print("\n[cyan]> [/] Total number of songs: %s. \n" % (len(songs_list)))
270-
if not questionary.confirm("Do you want to continue").ask():
271-
quit()
227+
print_logo()
228+
num_of_songs_printer(len(songs_list))
229+
wanna_continue()
272230
# file, verbose, debug
273231
MusicDownloader(songs_list, verbose, debug).download_songs()
274232
return
@@ -300,16 +258,7 @@ def single(song, verbose, debug):
300258
console.log("Verbose: ", verbose)
301259
console.log("Debug: ", debug)
302260

303-
console.print("""\b[red]
304-
_ _
305-
| | |
306-
_ __ ___ _ __ ___ __| | |
307-
| '_ ` _ \| '_ ` _ \ / _` | |
308-
| | | | | | | | | | | (_| | | [/]by techboy-coder[red]
309-
|_| |_| |_|_| |_| |_|\__,_|_| [/]find me on https://github.com/techboy-coder
310-
311-
[green]mmdl [Mega Music Downloader] - A tool to easily download music.[/green]
312-
""")
261+
print_logo()
313262
songs = [song]
314263
console.print("\n[cyan]> [/] Song: %s. \n" % (song))
315264
# file, verbose, debug

build/lib/mmdl/mdl.py

Lines changed: 1 addition & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -36,81 +36,6 @@
3636
##Dev Dep
3737
import shutil
3838

39-
class DisplayablePath(object):
40-
display_filename_prefix_middle = '├──'
41-
display_filename_prefix_last = '└──'
42-
display_parent_prefix_middle = ' '
43-
display_parent_prefix_last = '│ '
44-
45-
def __init__(self, path, parent_path, is_last):
46-
self.path = Path(str(path))
47-
self.parent = parent_path
48-
self.is_last = is_last
49-
if self.parent:
50-
self.depth = self.parent.depth + 1
51-
else:
52-
self.depth = 0
53-
54-
@property
55-
def displayname(self):
56-
if self.path.is_dir():
57-
return self.path.name + '/'
58-
return self.path.name
59-
60-
@classmethod
61-
def make_tree(cls, root, parent=None, is_last=False, criteria=None):
62-
root = Path(str(root))
63-
criteria = criteria or cls._default_criteria
64-
65-
displayable_root = cls(root, parent, is_last)
66-
yield displayable_root
67-
68-
children = sorted(list(path
69-
for path in root.iterdir()
70-
if criteria(path)),
71-
key=lambda s: str(s).lower())
72-
count = 1
73-
for path in children:
74-
is_last = count == len(children)
75-
if path.is_dir():
76-
yield from cls.make_tree(path,
77-
parent=displayable_root,
78-
is_last=is_last,
79-
criteria=criteria)
80-
else:
81-
yield cls(path, displayable_root, is_last)
82-
count += 1
83-
84-
@classmethod
85-
def _default_criteria(cls, path):
86-
return True
87-
88-
@property
89-
def displayname(self):
90-
if self.path.is_dir():
91-
return self.path.name + '/'
92-
return self.path.name
93-
94-
def displayable(self):
95-
if self.parent is None:
96-
return self.displayname
97-
98-
_filename_prefix = (self.display_filename_prefix_last
99-
if self.is_last
100-
else self.display_filename_prefix_middle)
101-
102-
parts = ['{!s} {!s}'.format(_filename_prefix,
103-
self.displayname)]
104-
105-
parent = self.parent
106-
while parent and parent.parent is not None:
107-
parts.append(self.display_parent_prefix_middle
108-
if parent.is_last
109-
else self.display_parent_prefix_last)
110-
parent = parent.parent
111-
112-
return ''.join(reversed(parts))
113-
11439
class MusicDownloader():
11540
def __init__(self, song_names: list[str], verbose: int, debug: bool):
11641
"""Music Downloader Class. This is the main class :/
@@ -171,6 +96,7 @@ def download_songs(self): # sourcery no-metrics
17196
]
17297
temp = []
17398
cwd = Utils.get_cwd()
99+
174100
for f in filenames:
175101
# print(f["filename"])
176102
does_exist = executor.submit(Utils.check_file_exists, f["filename"], f)

0 commit comments

Comments
 (0)