Skip to content

Commit 0d61502

Browse files
committed
Merge branch 'unstable'
2 parents 038326e + f479291 commit 0d61502

File tree

7 files changed

+109
-33
lines changed

7 files changed

+109
-33
lines changed

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,10 @@ usage: ytmdl [-h] [-q] [-o OUTPUT_DIR] [--song SONG-METADATA]
165165
[--on-meta-error ON_META_ERROR] [--proxy URL] [--url URL]
166166
[--list PATH TO LIST] [--nolocal] [--format FORMAT] [--trim]
167167
[--version] [--keep-chapter-name] [--download-archive FILE]
168-
[--ignore-chapters] [--ytdl-config PATH] [--pl-start NUMBER]
169-
[--pl-end NUMBER] [--pl-items ITEM_SPEC] [--ignore-errors]
170-
[--title-as-name] [--level LEVEL] [--disable-file] [--list-level]
168+
[--ignore-chapters] [--ytdl-config PATH] [--dont-transcode]
169+
[--pl-start NUMBER] [--pl-end NUMBER] [--pl-items ITEM_SPEC]
170+
[--ignore-errors] [--title-as-name] [--level LEVEL]
171+
[--disable-file] [--list-level]
171172
[SONG_NAME ...]
172173

173174
positional arguments:
@@ -213,6 +214,8 @@ options:
213214
like one video
214215
--ytdl-config PATH Path to the youtube-dl config location or the
215216
directory
217+
--dont-transcode Don't transcode the audio after downloading.
218+
Applicable for OPUS format only. (Default: false)
216219

217220
Metadata:
218221
--song SONG-METADATA The song to search in Metadata. Particularly useful
@@ -244,7 +247,7 @@ Metadata:
244247
the metadata (Default: false)
245248
--on-meta-error ON_META_ERROR
246249
What to do if adding the metadata fails for some
247-
reasong like lack of metadata or perhaps a network
250+
reason like lack of metadata or perhaps a network
248251
issue. Options are ['exit', 'skip', 'manual']
249252

250253
Playlist:

setup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
'itunespy',
1717
'requests',
1818
'colorama',
19-
'bs4',
19+
'beautifulsoup4',
2020
'downloader-cli',
2121
'pyxdg',
2222
'ffmpeg-python',
@@ -25,7 +25,7 @@
2525
'youtube-search-python',
2626
'pyDes',
2727
'urllib3',
28-
'simber',
28+
'simber==0.2.5',
2929
'rich',
3030
'musicbrainzngs',
3131
'ytmusicapi',
@@ -75,7 +75,7 @@
7575
"Environment :: Console",
7676
"Topic :: Multimedia :: Sound/Audio",
7777
),
78-
python_requires=">=3.*",
78+
python_requires=">=3.6.2",
7979
install_requires=req_pkgs,
8080
setup_requires=req_pkgs,
8181
extras_require=extra_features,

utils/completion.py

100644100755
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
#!/usr/bin/env python3
12
"""Build the completion files
23
34
The arguments can be fetched by using the ytmdl
45
command.
56
"""
67
from subprocess import Popen, PIPE
8+
from os import environ
79
from pathlib import Path
810

911

@@ -17,7 +19,9 @@
1719

1820
def build_files():
1921
"""Build the files"""
20-
process = Popen("ytmdl --get-opts".split(), stdout=PIPE, stderr=PIPE)
22+
environ["PYTHONPATH"] = "./ytmdl"
23+
process = Popen(
24+
"python3 -m main --get-opts".split(), stdout=PIPE, stderr=PIPE)
2125
out, err = process.communicate()
2226

2327
opts = out.decode("utf-8").replace("\n", "")

ytmdl/core.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def search(song_name, args) -> Union[str, str]:
6969

7070
# Check if choice if -2. If it is that, then we need to stop executing
7171
# of the current song and gracefully exit.
72-
if choice == -2:
72+
if choice == -2 or choice == -1:
7373
return False, False
7474

7575
return (
@@ -90,7 +90,7 @@ def search(song_name, args) -> Union[str, str]:
9090
if type(temp_data) is str and temp_data.lower() == "Unauthorized".lower():
9191
if args.ignore_errors:
9292
logger.warning("{}: is unauthorized".format(URL))
93-
return
93+
return None, None
9494
else:
9595
logger.critical("{}: is unauthorized".format(URL))
9696

@@ -116,7 +116,7 @@ def download(link, yt_title, args) -> str:
116116
))
117117
path = yt.dw(link, args.proxy, yt_title,
118118
args.format, no_progress=args.quiet,
119-
ytdl_config=args.ytdl_config)
119+
ytdl_config=args.ytdl_config, dont_convert=args.dont_transcode)
120120

121121
if type(path) is not str:
122122
# Probably an error occured
@@ -130,7 +130,8 @@ def convert(
130130
path: str,
131131
passed_format: str,
132132
start: float = None,
133-
end: float = None
133+
end: float = None,
134+
dont_convert: bool = False
134135
) -> str:
135136
"""Convert the song into the proper format as asked by
136137
the user.
@@ -155,7 +156,10 @@ def convert(
155156
return conv_name
156157

157158
# If it is m4a, don't convert
158-
if passed_format == "m4a":
159+
#
160+
# If dont_convert is passed, we can skip the conversion since
161+
# the user wants to keep the original audio
162+
if passed_format == "m4a" or dont_convert:
159163
return path
160164

161165
# Else the format needs to be in the list
@@ -246,4 +250,10 @@ def meta(conv_name: str, song_name: str, search_by: str, args):
246250
if type(option) is not int:
247251
raise MetadataError(search_by)
248252

253+
# If meta was skipped, indicate that
254+
if option == -1:
255+
logger.warning(
256+
"Metadata was skipped because -1 was entered as the option")
257+
return None
258+
249259
return TRACK_INFO[option]

ytmdl/main.py

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
from ytmdl.utils.ytdl import is_ytdl_config_present
4343
from ytmdl.yt import is_yt_url
4444
from ytmdl.__version__ import __version__
45+
from typing import Tuple
4546

4647
# init colorama for windows
4748
init()
@@ -111,7 +112,7 @@ def arguments():
111112
metadata_group.add_argument("--ask-meta-name", help="Ask the user to enter a separate \
112113
name for searching the metadata (Default: false)", action="store_true")
113114
metadata_group.add_argument("--on-meta-error", help="What to do if adding the metadata fails \
114-
for some reasong like lack of metadata or perhaps a network issue. \
115+
for some reason like lack of metadata or perhaps a network issue. \
115116
Options are {}".format(defaults.DEFAULT.ON_ERROR_OPTIONS),
116117
type=str, default=None)
117118

@@ -156,6 +157,9 @@ def arguments():
156157
action="store_true")
157158
parser.add_argument('--ytdl-config', help="Path to the youtube-dl config location or the "
158159
"directory", default=None, metavar="PATH", type=str)
160+
parser.add_argument("--dont-transcode", help="Don't transcode the audio after \
161+
downloading. Applicable for OPUS format only. (Default: false)",
162+
action="store_true")
159163

160164
playlist_group = parser.add_argument_group("Playlist")
161165
playlist_group.add_argument(
@@ -228,7 +232,8 @@ def arguments():
228232
def main(args):
229233
"""Run on program call."""
230234

231-
song_name = extract_song_name(args)
235+
song_name, verify_name = extract_song_name(args)
236+
logger.debug("verify title: ", str(verify_name))
232237

233238
# Extract the archive file contents
234239
is_download_archive = args.download_archive is not None
@@ -292,7 +297,15 @@ def main(args):
292297
# Try to extract the chapters
293298
chapters = yt.get_chapters(link, args.ytdl_config)
294299

295-
songs_to_download = [{}]
300+
# Add the current passed song as the only entry here
301+
# This dictionary will be cleared if the song is found to be containing
302+
# chapters.
303+
#
304+
# Moreover, the `is_original` field is **not** present from the youtube
305+
# response which would force the following code to verify the title
306+
# for chapters which is the behavior we want.
307+
songs_to_download = [{'title': song_name, 'is_original': not verify_name}]
308+
296309
# If the chapters are present, we will have to iterate and extract each chapter
297310
if chapters and not args.ignore_chapters:
298311
logger.info("The song has chapters in it.",
@@ -302,12 +315,15 @@ def main(args):
302315
for chapter in chapters:
303316
songs_to_download.append(chapter)
304317

305-
logger.debug(songs_to_download)
318+
logger.debug("songs to download: ", str(songs_to_download))
306319
for song in songs_to_download:
307320
song_title = song.get("title", yt_title)
308321
start_time = song.get("start_time", None)
309322
end_time = song.get("end_time", None)
310323

324+
is_original = song.get("is_original", False)
325+
logger.debug("is original: ", str(is_original))
326+
311327
if "title" in song.keys():
312328
logger.debug("Has the attribute")
313329
# Update the song_metadata with the name of the chapter
@@ -318,7 +334,7 @@ def main(args):
318334
# NOTE: Check if skip meta is passed, we don't need to
319335
# extract the new title.
320336
song_metadata = utility.get_new_title(song_metadata) if \
321-
not (args.keep_chapter_name and args.skip_meta) else song_metadata
337+
(not args.keep_chapter_name and not args.skip_meta and not is_original) else song_metadata
322338

323339
# Pass the song for post processing
324340
try:
@@ -369,7 +385,8 @@ def post_processing(
369385
logger.debug(stream)
370386
# Try to convert the song
371387
try:
372-
conv_name = convert(path, passed_format, start_time, end_time)
388+
conv_name = convert(path, passed_format, start_time,
389+
end_time, args.dont_transcode)
373390
except ConvertError as convert_error:
374391
logger.critical('ERROR: {}'.format(convert_error))
375392
return
@@ -414,6 +431,16 @@ def post_processing(
414431
add_song_to_archive(
415432
stream=stream, youtube_link=link) if is_download_archive else None
416433

434+
# If no metadata was selected, just do a dry cleanup and skip the
435+
# song
436+
if track_selected is None:
437+
if dir.dry_cleanup(conv_name, song_name):
438+
logger.info("Done")
439+
elif not args.ignore_errors or args.on_meta_error == 'exit':
440+
logger.critical(
441+
". Pass `--ignore-errors` or `on-meta-error` to ignore this.")
442+
return
443+
417444
if dir.cleanup([track_selected], 0, passed_format, remove_cached=False):
418445
logger.info("Done")
419446

@@ -484,12 +511,12 @@ def pre_checks(args):
484511
"Song Name is required. Check 'ytmdl --help' for help.")
485512

486513

487-
def extract_song_name(args) -> str:
514+
def extract_song_name(args) -> Tuple[str, bool]:
488515
"""Extract the name of the song from the given args"""
489516
logger.debug(args.SONG_NAME)
490517

491518
if args.SONG_NAME:
492-
return " ".join(args.SONG_NAME)
519+
return " ".join(args.SONG_NAME), False
493520

494521
# If song name is not passed then try to extract
495522
# the title of the song using the URL.
@@ -501,7 +528,7 @@ def extract_song_name(args) -> str:
501528
if not args.ignore_errors:
502529
logger.critical("Wasn't able to extract song data.",
503530
"Use `--ignore-errors` to ignore this error")
504-
return
531+
return None, False
505532

506533
# Ask the user if they want to go with the extracted
507534
# title or if they would like to change it.
@@ -511,8 +538,9 @@ def extract_song_name(args) -> str:
511538
# passed.
512539
if not args.title_as_name and not args.skip_meta and verify_title:
513540
song_name = utility.get_new_title(song_name)
541+
verify_title = False
514542

515-
return song_name
543+
return song_name, verify_title
516544

517545

518546
def extract_data():

ytmdl/song.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ def getChoice(SONG_INFO, type):
147147

148148
logger.info('Choose One {}'.format(
149149
'(One with [M] is verified music)'
150-
if type == 'mp3' else ''))
150+
if type == 'mp3' else '(Enter -1 to skip metadata)'))
151151

152152
results = len(SONG_INFO)
153153

@@ -173,7 +173,7 @@ def getChoice(SONG_INFO, type):
173173
# The choice is valid if it is in the range and it is greater than 0
174174
# We also need to break when the user enters -1 which means the exec
175175
# will skip the current song
176-
if (choice <= len(SONG_INFO) and choice > 0) or choice == -1:
176+
if choice == -1 or (choice <= len(SONG_INFO) and choice > 0):
177177
break
178178
elif choice == 0 and results < len(SONG_INFO):
179179
PRINT_WHOLE = True
@@ -182,7 +182,7 @@ def getChoice(SONG_INFO, type):
182182
else:
183183
PRINT_WHOLE = False
184184

185-
return choice - 1
185+
return choice - 1 if choice != -1 else -1
186186

187187

188188
def set_MP3_data(song, song_path):
@@ -314,13 +314,16 @@ def set_OPUS_data(song, song_path):
314314
try:
315315
SONG_PATH = os.path.join(defaults.DEFAULT.SONG_TEMP_DIR,
316316
song_path)
317+
logger.debug("Opening file at {} to add metadata".format(SONG_PATH))
317318
mutagen_file = File(SONG_PATH)
318319

319320
# Try adding the tags container
320321
try:
321322
mutagen_file.add_tags()
322-
except Exception:
323+
except Exception as e:
323324
# If exception is thrown, the tags already exist
325+
logger.debug(
326+
"Got exception while adding tags to the passed file: ", str(e))
324327
pass
325328

326329
# Clear out the tags from the file
@@ -386,6 +389,10 @@ def setData(SONG_INFO, is_quiet, song_path, datatype='mp3', choice=None):
386389
option = _get_option(SONG_INFO, is_quiet, choice)
387390
logger.debug(option)
388391

392+
# If -1 then skip setting the metadata
393+
if option == -1:
394+
return option
395+
389396
song = SONG_INFO[option]
390397

391398
get_more_data_dict = preconfig.CONFIG().GET_EXTRA_DATA
@@ -413,6 +420,11 @@ def setData(SONG_INFO, is_quiet, song_path, datatype='mp3', choice=None):
413420
song_path
414421
)
415422

423+
# Handle exception while adding the metadata
424+
if type(img_added) == Exception:
425+
logger.error(
426+
"Failed to add metadata due to exception: {}".format(img_added))
427+
416428
# Show the written stuff in a better format
417429
prepend.PREPEND(1)
418430
print('================================')

0 commit comments

Comments
 (0)