diff options
| author | Romain Gonçalves <me@rgoncalves.se> | 2022-10-08 12:40:19 +0200 | 
|---|---|---|
| committer | Romain Gonçalves <me@rgoncalves.se> | 2022-10-08 12:40:19 +0200 | 
| commit | ce6be946d024aa55a15d576388d05f90be671cf2 (patch) | |
| tree | fa1053446a3fb06daee8438c1ff664cb36c0abcb /.bin/music | |
| parent | 703ed1915c69911a95cab6e1fb6524629c976800 (diff) | |
| download | dots-ce6be946d024aa55a15d576388d05f90be671cf2.tar.gz | |
Sat Oct  8 12:40:19 PM CEST 2022
Diffstat (limited to '.bin/music')
| -rwxr-xr-x | .bin/music | 174 | 
1 files changed, 104 insertions, 70 deletions
| @@ -1,70 +1,104 @@ -#!/bin/sh - - -MUSIC_DIR="${HOME}/music" -MUSIC_LIST= -MUSIC_FILE= -MUSIC_YT_OPTIONS= - -log() { -	echo "[${0}  ] ${@}" -} - -main() { -	# arguments -	while getopts "c:" arg; do -		case "${arg}" in -			c) -				MUSIC_FILE="${OPTARG}" -				;; -			h) -				exit 0 -				;; -		esac -	done - -	# ensure parameters are correct -	[ ! -f "${MUSIC_FILE}" ] && exit 1 - - -	while read -r line; do -		 -		# skip comments -		line=$(echo ${line} | grep -v -e "^$" -e "^#") -		[ -z "${line}" ] && continue - -		# retrieve playlist params -		url=$(echo "${line}" | cut -d " " -f 1) -		dir=$(echo "${line}" | cut -d " " -f 2) - -		dir="${MUSIC_DIR}/${dir}" - -		[ -d "${dir}" ] && -			log "${dir}: directory already exists" && -			continue - -		mkdir "${dir}" -		log "${dir} ${url}: download" - -		yt-dlp --rm-cache-dir >/dev/null -		yt-dlp \ -			--extract-audio \ -			--audio-format mp3 \ -			--prefer-ffmpeg \ -			--audio-quality 0 \ -			--embed-thumbnail \ -			--metadata-from-title "%(artist)s - %(title)s" \ -			--no-warnings \ -			--ignore-errors \ -			--no-overwrites \ -			--continue \ -			--add-metadata \ -			--user-agent "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" \ -			--output "${dir}/'%(title)s.%(ext)s'" \ -			"${url}" - - -	done < "${MUSIC_FILE}" -} - -main ${@} +#!/usr/bin/python3 + +import os +import sys +import yt_dlp +from dataclasses import dataclass + + +def _match_filter(info: dict, *, incomplete) -> str | None: +    _duration = info.get("duration") +    _duration_min = 60 + +    if _duration and int(_duration) < _duration_min: +        return "Duration too short: < _duration_min" + +    return None + + +@dataclass(frozen=True) +class Collection: +    """A music collection.""" + +    title: str +    links: frozenset[str] + +    def __eq__(self, other) -> bool: +        if isinstance(other, Collection): +            return self.title == other.title +        raise NotImplementedError + + +def parse_raw_to_collections(raw_data: list[str]) -> frozenset[Collection]: +    collections: set[Collection] = set() +    _collection_data: list[str] = [] + +    for index, line in enumerate(raw_data): +        if line.startswith("#"): +            continue +        elif line == "" or index + 1 == len(raw_data): +            if len(_collection_data) == 0: +                continue + +            collections.add( +                Collection(_collection_data[0], frozenset(_collection_data[1:])) +            ) +            _collection_data.clear() +        else: +            _collection_data.append(line) + +    return frozenset(collections) + + +def get_ytdlp_options(output_dir: str) -> dict: +    return { +        "format": "bestaudio/best", +        "match_filter": _match_filter, +        "postprocessors": [ +            { +                "key": "FFmpegExtractAudio", +                #"preferredcodec": "m4a", +            }, +            { +                "key": "FFmpegMetadata", +                "add_metadata": True, +            }, +            { +                "key": "EmbedThumbnail", +                "already_have_thumbnail": False, +            }, +        ], +        "outtmpl": f"{output_dir}/%(title)s.%(ext)s", +        "restrictfilenames": True, +        "ignoreerrors": True, +    } + + +def download_collection(collection: Collection, parent_dir: str) -> None: +    output_dir = os.path.join(parent_dir, collection.title) + +    if os.path.isdir(output_dir): +        return + +    os.makedirs(output_dir, exist_ok=True) + +    with yt_dlp.YoutubeDL(get_ytdlp_options(output_dir)) as downloader: +        downloader.download(collection.links) + + +def main() -> int: +    # input handling +    if len(sys.argv) != 2: +        return 1 + +    with open(sys.argv[1], "r") as file: +        filedata = file.read().splitlines() + +    for collection in parse_raw_to_collections(filedata): +        download_collection(collection, os.getcwd()) + +    return 0 + + +if __name__ == "__main__": +    exit(main()) |