1+ ###############################################################
2+ # Published on ... under the MIT Licence
3+ # Copyright 2021 techboy-coder
4+ # _ _
5+ # | | |
6+ # _ __ ___ _ __ ___ __| | |
7+ # | '_ ` _ \| '_ ` _ \ / _` | |
8+ # | | | | | | | | | | | (_| | | by techboy-coder
9+ # |_| |_| |_|_| |_| |_|\__,_|_| find me on https://github.com/techboy-coder
10+ #
11+ # mmdl [Mega Music Downloader] - A tool to easily download music.
12+ ###############################################################
13+ from __future__ import unicode_literals
14+ from lxml .cssselect import CSSSelector
15+ from lxml .html import fromstring
16+ import click
17+ from mmdl import MusicDownloader
18+ from .ask import asker
19+ from rich .console import Console
20+ import questionary
21+ console = Console ()
22+ from click_help_colors import HelpColorsGroup , HelpColorsCommand
23+ CONTEXT_SETTINGS = dict (help_option_names = ['-h' , '--help' ])
24+
25+ @click .group (context_settings = CONTEXT_SETTINGS , cls = HelpColorsGroup , help_headers_color = 'red' , help_options_color = 'green' )
26+ def main ():
27+ """\b
28+ _ _
29+ | | |
30+ _ __ ___ _ __ ___ __| | |
31+ | '_ ` _ \| '_ ` _ \ / _` | |
32+ | | | | | | | | | | | (_| | | by techboy-coder
33+ |_| |_| |_|_| |_| |_|\__,_|_| find me on https://github.com/techboy-coder
34+
35+ mmdl [Mega Music Downloader] - A tool to easily download music.
36+
37+ > Enter 'mmdl go' to start downloading songs.
38+ """
39+ pass
40+
41+ @main .command (context_settings = CONTEXT_SETTINGS , cls = HelpColorsCommand , help_headers_color = 'red' , help_options_color = 'green' )
42+ @click .option ("-v" ,"--verbose" , help = "Verbose level" , type = int , required = False , default = 1 )
43+ @click .option ("-d" ,"--debug" , help = "Enable debug mode" , is_flag = True )
44+ def go (verbose , debug ):
45+ """
46+ Easy mode. Just answer few questions and download your songs.
47+
48+ mmdl [Music Downloader] - A tool to easily download music. \n
49+
50+ # Go Command
51+ > Easy way to download songs. Uses inputs/inquirer. (Simply run 'mmdl go')
52+ """
53+
54+ if debug :
55+ console .log ("Verbose: " , verbose )
56+ console .log ("Debug: " , debug )
57+
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+ """ )
68+ song_names = asker ()
69+ console .print ("\n [cyan]> [/] Total number of songs: %s. \n " % (len (song_names )))
70+ # List, verbose, debug
71+ MusicDownloader (song_names , verbose , debug ).download_songs ()
72+
73+ @main .group (context_settings = CONTEXT_SETTINGS , cls = HelpColorsGroup , help_headers_color = 'red' , help_options_color = 'green' )
74+ def download ():
75+ """
76+ Download your songs the way you want!
77+
78+ mmdl [Mega Music Downloader] - A tool to easily download music. \n
79+ # Download Section
80+ > Here are possible ways to download songs.
81+ Ways to download:\n
82+ - Single song\n
83+ - Multiple songs\n
84+ - From file\n
85+ - As multiple songs (e.g. song1, song2, song3, ...)\n
86+ - From your YTMusic liked songs playlist (beta)\n
87+ """
88+ pass
89+
90+ @download .command (context_settings = CONTEXT_SETTINGS , cls = HelpColorsCommand , help_headers_color = 'red' , help_options_color = 'green' )
91+ @click .argument ("file" , type = click .File ("r" ), required = True )
92+ @click .option ("-s" ,"--seperator" , help = "Seperator of song_names" , type = str , default = "\n " )
93+ @click .option ("-v" ,"--verbose" , help = "Verbose level" , type = int , required = False , default = 1 )
94+ @click .option ("-d" ,"--debug" , help = "Enable debug mode" , is_flag = True )
95+ def file (file , seperator , verbose , debug ):
96+ """
97+ Get songs from a file and then download them.
98+
99+ mmdl [Music Downloader] - A tool to easily download music.
100+
101+ ## File Section
102+ > Download multiple songs from a file.
103+
104+ Run 'mmdl download file <filepath e.g. ~/Downloads/file.txt>'.
105+ """
106+
107+ # print(type(file))
108+ # text_file = open(file ,encoding='utf-8')
109+ songs = file .read ().split (seperator )
110+ if debug :
111+ console .log ("File: " , file )
112+ console .log ("Seperator: " , repr (seperator ))
113+ console .log ("Songs: " , str (songs ))
114+ console .log ("Verbose: " , verbose )
115+ console .log ("Debug: " , debug )
116+
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 ()
130+ # file, verbose, debug
131+ MusicDownloader (songs , verbose , debug ).download_songs ()
132+ return
133+
134+ @download .command (context_settings = CONTEXT_SETTINGS , cls = HelpColorsCommand , help_headers_color = 'red' , help_options_color = 'green' )
135+ @click .argument ("songs" , type = str , nargs = - 1 , required = False )
136+ # @click.argument("seperator", type=str, required=True, nargs=1, default=",")
137+ @click .option ("-v" ,"--verbose" , help = "Verbose level" , type = int , required = False , default = 1 )
138+ @click .option ("-d" ,"--debug" , help = "Enable debug mode" , is_flag = True )
139+ @click .option ("-a" ,"--ask" , help = "Get songs via input (easy)" , is_flag = True )
140+ def list (songs , verbose , debug , ask ):
141+ """
142+ Download multiple songs.
143+
144+ mmdl [Mega Music Downloader] - A tool to easily download music.
145+
146+ ## List Section/Multiple Songs
147+ > Download multiple songs from a list.
148+
149+ Run 'mmdl download list "Term1" "Term2" --ask (or -a)'.
150+ > Write all songs search terms (comma seperated): Term3, Term 4
151+ > This will download Term1, Term2, Term3, Term4
152+
153+ """
154+ if ask :
155+ console .print ("[cyan][>][/] We'll be manually asking you for songs." )
156+ songs_list = questionary .text ("Write all songs search terms (comma seperated)" ).ask ()
157+ if not songs_list :
158+ quit ()
159+ songs_list = songs_list .split ("," )
160+ else :
161+ if len (songs ) < 1 :
162+ # 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 ()
164+ if not songs_list :
165+ quit ()
166+ songs_list = songs_list .split ("," )
167+ else :
168+ songs_list = []
169+ if isinstance (songs , tuple ):
170+ s = [song for song in songs ]+ songs_list
171+ songs_list = s
172+ if debug :
173+ console .log ("Songs: " , songs_list )
174+ console .log ("Verbose: " , verbose )
175+ console .log ("Debug: " , debug )
176+
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 )))
188+ # file, verbose, debug
189+ MusicDownloader (songs_list , verbose , debug ).download_songs ()
190+ return
191+
192+ @download .command (context_settings = CONTEXT_SETTINGS , cls = HelpColorsCommand , help_headers_color = 'red' , help_options_color = 'green' )
193+ @click .argument ("file" , type = click .File ("r" ), required = False )
194+ # @click.argument("seperator", type=str, required=True, nargs=1, default=",")
195+ @click .option ("-v" ,"--verbose" , help = "Verbose level" , type = int , required = False , default = 1 )
196+ @click .option ("-d" ,"--debug" , help = "Enable debug mode" , is_flag = True )
197+ @click .option ("-a" ,"--ask" , help = "Get songs via input (easy)" , is_flag = True )
198+ def ytmusic (file , verbose , debug , ask ):
199+ """
200+ Download multiple songs from YouTube Music liked songs playlist.
201+
202+ mmdl [Mega Music Downloader] - A tool to easily download music.
203+
204+ ## YTMusic Section
205+ > Download multiple songs from YTMusic liked songs (beta). [Done via parsing html.]
206+
207+ Run 'mmdl download ytmusic <filepath e.g. ~/Downloads/file.txt> (or --ask or -a for entering file via input)'.
208+
209+ """
210+ if not ask and not file :
211+ ask = True
212+ if ask :
213+ console .print ("[cyan][>][/] We'll be manually asking you for the file location." )
214+ console .print ("""
215+ [bold red]YT-Music[/bold red].
216+ - Go to your YTMusic liked songs playlist (https://music.youtube.com/playlist?list=LM)
217+ - Make sure you are logged in
218+ - Press Ctrl/Cmd + Shift + i and open the dev tools
219+ - Keep scrolling down until you reach the end of your playlist (Songs will stop loading)
220+ - Copy the all the html markup
221+ - 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 ()
225+ file = questionary .path ("Where is that file located?" ).ask ()
226+ with open (file , "r" , encoding = "utf-8" ) as f :
227+ 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 ()
234+ if not ask :
235+ if not file :
236+ console .log ("[red][-] You need to enter the file location or add the -a flag." )
237+ quit ()
238+ 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+ """ )
253+
254+
255+ if debug :
256+ console .log ("Songs: " , str (songs_list ))
257+ console .log ("Verbose: " , verbose )
258+ 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 ()
272+ # file, verbose, debug
273+ MusicDownloader (songs_list , verbose , debug ).download_songs ()
274+ return
275+
276+
277+ @download .command (context_settings = CONTEXT_SETTINGS , cls = HelpColorsCommand , help_headers_color = 'red' , help_options_color = 'green' )
278+ @click .argument ("song" , type = str , required = True , nargs = - 1 )
279+ @click .option ("-v" ,"--verbose" , help = "Verbose level" , type = int , required = False , default = 1 )
280+ @click .option ("-d" ,"--debug" , help = "Enable debug mode" , is_flag = True )
281+ def single (song , verbose , debug ):
282+ """
283+ Download a single song based on search query.
284+
285+ mmdl [Mega Music Downloader] - A tool to easily download music.
286+
287+ ## Single Song Section
288+ > Download a single song based on search query.
289+
290+ Run 'mmdl download single <songname>'.
291+ """
292+
293+ # print(type(file))
294+ song = " " .join (song )
295+
296+ # text_file = open(file ,encoding='utf-8')
297+ if debug :
298+ console .log ("File: " , song )
299+ console .log ("Songs: " , str (songs ))
300+ console .log ("Verbose: " , verbose )
301+ console .log ("Debug: " , debug )
302+
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+ """ )
313+ songs = [song ]
314+ console .print ("\n [cyan]> [/] Song: %s. \n " % (song ))
315+ # file, verbose, debug
316+ MusicDownloader (songs , verbose , debug ).download_songs ()
317+ return
318+
319+
320+ def runme ():
321+ main ()
322+ if __name__ == '__main__' :
323+ runme ()
324+ # :/
0 commit comments