-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMusicMove.py
executable file
·179 lines (139 loc) · 6.8 KB
/
MusicMove.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
__author__ = 'GirlLunarExplorer'
import argparse
from string import capwords
import discogs_client as discogs
import os
import shutil
import string
consumer_key = 'rAjSgwbCPsRVZbJoyvmt'
consumer_secret = 'fNTLMBiFlLerIgIuyKIytckvOrqqcOpv'
request_token_url = 'http://api.discogs.com/oauth/request_token'
authorize_url = 'http://www.discogs.com/oauth/authorize'
access_token_url = 'http://api.discogs.com/oauth/access_token'
discogs.user_agent = 'MyMusicPythonProject'
def set_destination():
default = '/Users/username/Music/iTunes/iTunes Media/Music/'
itunes_path = raw_input("Please enter destination path. Default is {0} \n".format(default))
if not itunes_path:
itunes_path = default
return itunes_path
def check_file_tag(song):
if song.endswith(".m4a"):
return ".m4a"
elif song.endswith(".mp3"):
return ".mp3"
elif song.endswith(".m4p"):
return ".m4p"
else:
return ".flac"
def check_unwanted_chars(song):
import re
# gets rid of (featuring artist) and (ft. artist) from file name
feat_pattern = re.compile(r'.feat.+')
ft_pattern = re.compile(r'(ft.+)')
patterns = [feat_pattern, ft_pattern]
for pattern in patterns:
match = re.search(pattern, song)
if match:
song = pattern.sub("", song)[:-1]
# forces capitalization after a parentheses
pattern = re.compile(r"\(")
p_match = re.finditer(pattern, song)
if p_match:
i = 0
for item in p_match:
i = item.start()+1
song = song[:i]+ song[i:].capitalize()
return song
class Music_paths(object):
def __init__(self, album_path, album_name, album_type, artist_name):
super(Music_paths,self).__init__()
self.album_path = album_path
self.album_name = album_name
self.album_type = album_type
self.artist_name = artist_name
self.itunes_path = set_destination()
self.target_album = None
self.client = discogs.Client('test client') #discogs limits tokens to 100 a day so keys cannot be kept as permanent variables
self.client.set_consumer_key(consumer_key, consumer_secret)
print "follow this url to authorize the client"
print self.client.get_authorize_url()[2]
new_key = raw_input()
self.client.get_access_token(new_key)
def get_target_album(self):
# Goes through all of the releases that match that album,
# prints each track and asks if it is the correct album.
# This is done because discogs allows users to upload different versions of the same release
# so it is possible to have several different versions of the same album in the database
# with slight variations in tracks and so on.
releases = [x for x in self.client.search(self.album_name, artist = self.artist_name)]
while releases and not self.target_album:
releases.reverse() # I've noticed the most accurate matches tend to be at the end of the release list
current = releases.pop()
for track in current.tracklist:
print track
answer = raw_input("does this look correct?\n")
if answer.lower() =="yes":
self.target_album = current
else: pass
print "going to use", self.target_album
return self.target_album
def standard_album(self):
self.target_album = self.get_target_album()
possible_paths =[self.artist_name, self.album_name]
for path in possible_paths:
#creates a separate folder for the artist and then the album if it does not exist
if not os.path.exists(self.itunes_path+path):
os.mkdir(self.itunes_path+path)
self.itunes_path += path +"/"
for track in self.target_album.tracklist:
for song in os.listdir(self.album_path):
if track.title.lower() in song.lower():
file_tag = check_file_tag(song)
title = check_unwanted_chars(capwords(track.title))
source = "{0}/{1}".format(self.album_path, song)
dest = "{0}{1}{2}".format(self.itunes_path,title,file_tag)
shutil.copyfile(source, dest)
print "Moving to {0}".format(dest)
def non_standard_album(self,):
self.target_album = self.get_target_album()
self.album_type = string.capwords(self.album_type)+"s"
# creates a separate compilations/soundtrack/singles folder
possible_paths =[self.album_type, self.album_name]
for path in possible_paths:
if not os.path.exists(self.itunes_path+path):
os.mkdir(self.itunes_path+path)
self.itunes_path += path +"/"
#asks for artists names for songs in order to make a "artistname - songname.mp3" format
for track in self.target_album.tracklist:
compilation_artist = raw_input("who is the artist for {}\n".format(track.title))
for song in os.listdir(self.album_path):
if track.title.lower() in song.lower():
file_tag = check_file_tag(song)
title = check_unwanted_chars(capwords(track.title))
source = "{0}/{1}".format(self.album_path, song)
dest = "{0}{1} - {2}{3}".format(self.itunes_path,compilation_artist,title,file_tag)
try:
shutil.copyfile(source, dest)
print "Moving to {0}".format(dest)
break
except Exception as error:
print error
print "Will not accept foreign characters, including characters with accent marks on them"
def main(album_path, album_name, album_type, artist_name):
album = Music_paths(album_path, album_name, album_type, artist_name)
known_types = ["standard", "soundtrack", "compilation", "single"]
if album.album_type.lower() == "standard":
album.standard_album()
elif album.album_type.lower() not in known_types:
print album_type + " is not a known type"
else:
album.non_standard_album()
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Searches discogs DB and moves mp3 files to an iTunes folder")
parser.add_argument("path", help="Argument must include full path to album, surrounded by double quotes")
parser.add_argument("album", help="Argument must include album name, surrounded by double quotes")
parser.add_argument("type", help="Valid arguments for album type are: standard, compilation, soundtrack, or single")
parser.add_argument("--artist", default="Various", help="Argument must include artist name, surrounded by double quotes")
args = parser.parse_args()
main(args.path, args.album, args.type, args.artist)