forked from caseychu/spotify-backup
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjson2md.py
More file actions
90 lines (78 loc) · 3.71 KB
/
json2md.py
File metadata and controls
90 lines (78 loc) · 3.71 KB
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
import argparse, json, logging, sys, urllib.parse, os
logging.basicConfig(level=20, datefmt='%I:%M:%S', format='[%(asctime)s] %(message)s')
def _artist_link(name):
return f"{name}"
# return f"[{name}](./artists/{urllib.parse.quote(name.replace('/', '_'))}.md)"
def _write_playlist(f, playlist, header):
f.write(f"{header} {playlist.get('name', 'playlist')}\n\n")
f.write('|Titel|Artist(s)|Album|\n|---|---|---|\n')
for item in playlist.get('tracks', []):
tr = item.get('track') if isinstance(item, dict) else None
if not tr:
continue
artists = ', '.join(_artist_link(a['name']) for a in tr.get('artists', []))
f.write('|{name}|{artists}|{album}|\n'.format(
name=tr.get('name', ''),
artists=artists,
album=tr.get('album', {}).get('name', '')
))
f.write('\n')
def main():
# Parse arguments.
parser = argparse.ArgumentParser(description='Convert json from spotify-backup to a markdown we want')
parser.add_argument('-i', '--input', dest='input',
help='input JSON file (default: output.json, use "-" for stdin)',
default='output.json')
parser.add_argument('-o', '--output', dest='file',
help='output filename (required)',
default='output.md',
required=True)
parser.add_argument('-s', '--per-playlist', dest='per_playlist', action='store_true',
help='write each playlist to its own file named after the playlist (default: false)')
args = parser.parse_args()
# Load input JSON. Support '-' for stdin.
try:
if args.input == '-':
data = json.load(sys.stdin)
else:
with open(args.input, 'r', encoding='utf-8') as inf:
data = json.load(inf)
except FileNotFoundError:
logging.error(f"Input file not found: {args.input}")
sys.exit(2)
except json.JSONDecodeError as e:
logging.error(f"Could not parse JSON from {args.input}: {e}")
sys.exit(3)
# Expect the input JSON to contain 'playlists' and optionally 'albums' or 'liked_albums'
playlists = data.get('playlists', [])
liked_albums = data.get('albums', data.get('liked_albums', []))
# If they didn't give an output filename, then prompt them. (They probably just double-clicked.)
while not args.file:
args.file = input('Enter a file name (e.g. playlists.txt): ')
args.format = args.file.split('.')[-1]
# If format wasn't set by interactive prompt (i.e. user provided file), derive from extension if possible
if not hasattr(args, 'format'):
args.format = args.file.split('.')[-1]
# Write either a single file with all playlists (default) or one file per playlist.
output_dir = os.path.dirname(args.file)
if output_dir == '':
output_dir = ''
if args.per_playlist:
written_files = []
for playlist in playlists:
pname = playlist.get('name', 'playlist')
safe_name = urllib.parse.quote(pname.replace("/", "_"))
filename = f"{safe_name}.{args.format}"
path = os.path.join(output_dir, filename) if output_dir else filename
with open(path, 'w', encoding='utf-8') as f:
_write_playlist(f, playlist, '#')
written_files.append(path)
# make the final logging line reflect what was actually written
args.file = ','.join(written_files)
else:
with open(args.file, 'w', encoding='utf-8') as f:
for playlist in playlists:
_write_playlist(f, playlist, '#')
logging.info('Wrote file: ' + args.file)
if __name__ == '__main__':
main()