some progress with musicbrainz
This commit is contained in:
parent
7fa9a55a1e
commit
9d9c7960c9
8
.idea/.gitignore
vendored
Normal file
8
.idea/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
6
.idea/inspectionProfiles/profiles_settings.xml
Normal file
6
.idea/inspectionProfiles/profiles_settings.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
4
.idea/misc.xml
Normal file
4
.idea/misc.xml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (music-downloader)" project-jdk-type="Python SDK" />
|
||||||
|
</project>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/music-downloader.iml" filepath="$PROJECT_DIR$/.idea/music-downloader.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
10
.idea/music-downloader.iml
Normal file
10
.idea/music-downloader.iml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="jdk" jdkName="Python 3.10 (music-downloader)" jdkType="Python SDK" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -1,2 +1,6 @@
|
|||||||
# music-downloader
|
# music-downloader
|
||||||
This programm will first get the metadata of various songs from metadata provider like musicbrainz, and then search for download links on pages like bandcamp. Then it will download the song and edit the metadata according.
|
This programm will first get the metadata of various songs from metadata provider like musicbrainz, and then search for download links on pages like bandcamp. Then it will download the song and edit the metadata according.
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
![Musicbrainz Data Scheme](https://wiki.musicbrainz.org/-/images/9/9e/pymb3-model-core.png)
|
||||||
|
|
||||||
|
BIN
src/__pycache__/metadata.cpython-310.pyc
Normal file
BIN
src/__pycache__/metadata.cpython-310.pyc
Normal file
Binary file not shown.
155
src/metadata.py
Normal file
155
src/metadata.py
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
import musicbrainzngs
|
||||||
|
|
||||||
|
musicbrainzngs.set_useragent("metadata receiver", "0.1", "https://github.com/HeIIow2/music-downloader")
|
||||||
|
|
||||||
|
KNOWN_KIND_OF_OPTIONS = ["artist", "release", "track"]
|
||||||
|
|
||||||
|
class Search:
|
||||||
|
def __init__(self, query: str = None, artist: str = None):
|
||||||
|
if query is None and artist is None:
|
||||||
|
raise ValueError("no query provided")
|
||||||
|
|
||||||
|
self.options_history = []
|
||||||
|
self.current_options = None
|
||||||
|
self.current_chosen_option = None
|
||||||
|
|
||||||
|
# initial search
|
||||||
|
if query is not None:
|
||||||
|
self.set_options([musicbrainzngs.search_artists(query), musicbrainzngs.search_release_groups(query), musicbrainzngs.search_releases(query)])
|
||||||
|
elif artist is not None:
|
||||||
|
self.set_options([musicbrainzngs.search_artists(artist=artist)])
|
||||||
|
|
||||||
|
def browse_artist(self, artist):
|
||||||
|
return
|
||||||
|
|
||||||
|
def browse_option(self, option, index: int):
|
||||||
|
if not option.choose(index):
|
||||||
|
return False
|
||||||
|
|
||||||
|
self.current_chosen_option = option.get_current_option()
|
||||||
|
option_kind = self.current_chosen_option['kind']
|
||||||
|
if option_kind == "artist":
|
||||||
|
return self.browse_artist(self.current_chosen_option)
|
||||||
|
|
||||||
|
def choose(self, index):
|
||||||
|
if not self.current_options.choose(index):
|
||||||
|
return self.current_options
|
||||||
|
|
||||||
|
|
||||||
|
def get_options(self):
|
||||||
|
return self.current_options
|
||||||
|
|
||||||
|
def set_options(self, results):
|
||||||
|
option_instance = self.Options(results=results)
|
||||||
|
self.options_history.append(option_instance)
|
||||||
|
self.current_options = option_instance
|
||||||
|
|
||||||
|
return option_instance
|
||||||
|
|
||||||
|
options = property(fget=get_options)
|
||||||
|
|
||||||
|
class Options:
|
||||||
|
def __init__(self, results: list):
|
||||||
|
self.results = results
|
||||||
|
|
||||||
|
self.headers = {
|
||||||
|
"artist": "found {count} artists:\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
self.artist_count = 0
|
||||||
|
self.release_count = 0
|
||||||
|
self.track_count = 0
|
||||||
|
self.result_list = []
|
||||||
|
self.set_options_values()
|
||||||
|
|
||||||
|
self.current_option_ind = None
|
||||||
|
|
||||||
|
def get_current_option(self):
|
||||||
|
if self.current_option_ind is None:
|
||||||
|
raise Exception("It must first be chosen, which option to get, before getting it")
|
||||||
|
|
||||||
|
return self.result_list[self.current_option_ind]
|
||||||
|
|
||||||
|
def choose(self, index: int) -> bool:
|
||||||
|
if len(self.result_list) <= index -1:
|
||||||
|
return False
|
||||||
|
self.current_option_ind = index
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_string_for_artist(self, artist: dict) -> str:
|
||||||
|
string = f"'{artist['name']}'"
|
||||||
|
if "country" in artist:
|
||||||
|
string += f" from {artist['country']}"
|
||||||
|
if 'disambiguation' in artist:
|
||||||
|
string += f", '{artist['disambiguation']}'"
|
||||||
|
return string + "\n"
|
||||||
|
|
||||||
|
def get_string_for_release(self, release: dict) -> str:
|
||||||
|
string = ""
|
||||||
|
print(release)
|
||||||
|
if "type" in release:
|
||||||
|
string += f"the {release['type']} titled "
|
||||||
|
string += f"'{release['title']}'"
|
||||||
|
if "artist-credit-phrase" in release:
|
||||||
|
string += f" by: {release['artist-credit-phrase']}"
|
||||||
|
|
||||||
|
return string + "\n"
|
||||||
|
|
||||||
|
def get_string_for_tracks(self, tracks: dict) -> str:
|
||||||
|
# I know it's not the best practice but whatever
|
||||||
|
return self.get_string_for_release(tracks)
|
||||||
|
|
||||||
|
def get_string_for_option(self, option: dict) -> str:
|
||||||
|
kind = option['kind']
|
||||||
|
if kind == "artist":
|
||||||
|
return self.get_string_for_artist(option)
|
||||||
|
if kind == "release":
|
||||||
|
return self.get_string_for_release(option)
|
||||||
|
if kind == "track":
|
||||||
|
return self.get_string_for_tracks(option)
|
||||||
|
return "Error\n"
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
string = f"artists: {self.artist_count}; releases {self.release_count}; tracks {self.track_count}\n"
|
||||||
|
for i, option in enumerate(self.result_list):
|
||||||
|
string += f"{i})\t{option['kind']}:\t" + self.get_string_for_option(option)
|
||||||
|
return string
|
||||||
|
|
||||||
|
def set_options_values(self):
|
||||||
|
for option_set in self.results:
|
||||||
|
if "artist-list" in option_set:
|
||||||
|
self.set_artist_values(option_set)
|
||||||
|
continue
|
||||||
|
if "release-group-list" in option_set:
|
||||||
|
self.set_release_values(option_set)
|
||||||
|
continue
|
||||||
|
if "release-list" in option_set:
|
||||||
|
self.set_track_values(option_set)
|
||||||
|
continue
|
||||||
|
print(option_set)
|
||||||
|
|
||||||
|
def set_artist_values(self, option_set: dict):
|
||||||
|
self.artist_count += option_set['artist-count']
|
||||||
|
for artist in option_set['artist-list']:
|
||||||
|
artist['kind'] = "artist"
|
||||||
|
self.result_list.append(artist)
|
||||||
|
|
||||||
|
def set_release_values(self, option_set: dict):
|
||||||
|
self.release_count += option_set['release-group-count']
|
||||||
|
for release in option_set['release-group-list']:
|
||||||
|
release['kind'] = "release"
|
||||||
|
self.result_list.append(release)
|
||||||
|
|
||||||
|
def set_track_values(self, option_set: dict):
|
||||||
|
self.artist_count += option_set['release-count']
|
||||||
|
for track in option_set['release-list']:
|
||||||
|
track['kind'] = "track"
|
||||||
|
self.result_list.append(track)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
search = Search(query="psychonaut 4")
|
||||||
|
print(search.options)
|
||||||
|
search.choose(0)
|
24
src/test.py
Normal file
24
src/test.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import metadata
|
||||||
|
|
||||||
|
|
||||||
|
def test():
|
||||||
|
passed = 0
|
||||||
|
failed = 0
|
||||||
|
|
||||||
|
# testing search
|
||||||
|
metadata.Search(artist="Psychonaut")
|
||||||
|
passed += 1
|
||||||
|
metadata.Search(query="Psychonaut")
|
||||||
|
passed += 1
|
||||||
|
try:
|
||||||
|
metadata.Search()
|
||||||
|
failed += 1
|
||||||
|
except ValueError:
|
||||||
|
print("throwing error on not giving metadata search a query works")
|
||||||
|
passed += 1
|
||||||
|
|
||||||
|
return passed, failed
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
p,f = test()
|
||||||
|
print(f"{p}-{f}")
|
Loading…
Reference in New Issue
Block a user