-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathSubsonicTools.py
156 lines (118 loc) · 5.62 KB
/
SubsonicTools.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
'''
Subsonic Tools | Command line tools for Subsonic Music Streamer
@author: Jan Jonas, http://janjonas.net
@copyright: 2013
@license: GPLv2 (http://www.gnu.org/licenses/gpl-2.0.html)
@contact: [email protected]
'''
import sys
import os
import re
import requests
import xml.etree.ElementTree as ET
import urllib
from argparse import ArgumentParser
from argparse import RawDescriptionHelpFormatter
VERSION = 0.1
DEBUG = 0
verbose = 0;
subsonic_namespace = "http://subsonic.org/restapi"
subsonic_client = "Subsonic-Tools"
subsonic_apiVersion = "1.8.0"
subsonic_url = ""
subsonic_trustServerCert = 0
subsonic_user = ""
subsonic_password = ""
def subsonic_call(command, params = []):
url = "%s/rest/%s.view?v=%s&c=%s&%s" % (subsonic_url, command, subsonic_apiVersion, subsonic_client, urllib.urlencode(params))
if verbose > 0: print "Call Subsonic API %s" % (url)
response = requests.get(url, verify= (subsonic_trustServerCert == 0), auth = (subsonic_user,subsonic_password))
if response.status_code != 200:
raise Exception("Subsonic REST API returned status code %s" % {response.status_code})
root = ET.fromstring(response.text)
error = (root.find("{%(ns)s}error" % {"ns": subsonic_namespace }))
if error is not None:
raise Exception("Error (Code: %(code)s, Text: %(text)s)" % {"code": error.get("code"), "text": error.get("message")})
else:
return root[0]; # First child is response object
def exportPlaylists(args):
out = args.out
prefix = ""
if args.prefix is not None:
prefix = args.prefix
out = out + os.sep
print "Exporting playlists to %s..." % out
# Export playlists
playlists = subsonic_call("getPlaylists")
for playlist in playlists.iter("{%(ns)s}playlist" % {"ns": subsonic_namespace}):
playlist = subsonic_call("getPlaylist", {"id": playlist.get("id")})
filename = "%s%s.m3u" % (out, re.sub('[:|*\\\/\?"]', '_', playlist.get("name")))
print " Save playlist '%s' as %s" % (playlist.get("name"), filename)
file = open(filename, "w")
for entry in playlist.iter("{%(ns)s}entry" % {"ns": subsonic_namespace }):
file.write("%s%s\n" % (prefix, entry.get("path").encode("utf-8")))
file.close()
print "Done."
def main(argv=None): # IGNORE:C0111
if argv is None:
argv = sys.argv
else:
sys.argv.extend(argv)
program_name = os.path.basename(sys.argv[0])
program_shortdesc = __import__('__main__').__doc__.split("\n")[1]
program_license = '''%s
Licensed under the GPLv2
http://www.gnu.org/licenses/gpl-2.0.html
Distributed on an "AS IS" basis without warranties
or conditions of any kind, either express or implied.
USAGE
''' % (program_shortdesc)
try:
# Setup argument parser
# ---------------------
# Parent parser
parser_parent = ArgumentParser(description=program_license, formatter_class=RawDescriptionHelpFormatter)
parser_parent.add_argument('--version', action='version', version="Subsonic-Tools %s" % (VERSION))
subparsers = parser_parent.add_subparsers(title='Commands', description='Please specify one of the following commands')
# Base command parser
parser_commandBase = ArgumentParser(description=program_license, formatter_class=RawDescriptionHelpFormatter, add_help=False)
parser_commandBase.add_argument("--url", dest="url", help="Subsonic server URL", required=True)
parser_commandBase.add_argument("--trust-server-cert", dest="trustServerCert", action="count", help="Accept SSL server certificates from unknown certificate authorities")
parser_commandBase.add_argument("-u", "--user", dest="user", help="Subsonic user", required=True)
parser_commandBase.add_argument("-p", "--password", dest="password", help="Subsonic password", required=True)
parser_commandBase.add_argument("-v", "--verbose", dest="verbose", action="count", help="Run in verbose level")
# ExportPlaylists command parser
parser_exportPlaylists = subparsers.add_parser('ExportPlaylists', parents=[parser_commandBase], help='Export playlists to a specific directory.')
parser_exportPlaylists.add_argument("--out", dest="out", help="Output path", required=True)
parser_exportPlaylists.add_argument("--prefix", dest="prefix", help="Relative or absolute path prefix that is added to all files in the playlists")
parser_exportPlaylists.set_defaults(func=exportPlaylists)
args = parser_parent.parse_args()
# Set up global parameters
global verbose
global subsonic_url
global subsonic_user
global subsonic_password
global subsonic_trustServerCert
verbose = args.verbose
subsonic_url = args.url
subsonic_user = args.user
subsonic_password = args.password
subsonic_trustServerCert = args.trustServerCert
# Call command
args.func(args);
return 0
except KeyboardInterrupt:
### handle keyboard interrupt ###
return 0
except Exception, e:
if DEBUG:
raise(e)
indent = len(program_name) * " "
sys.stderr.write(program_name + ": " + repr(e) + "\n")
sys.stderr.write(indent + " for help use --help")
return 2
if __name__ == "__main__":
if DEBUG:
sys.argv.append("-h")
sys.argv.append("-v")
sys.exit(main())