-
Notifications
You must be signed in to change notification settings - Fork 5
/
convert_notes.py
executable file
·154 lines (114 loc) · 5.55 KB
/
convert_notes.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
#!/usr/bin/env python3
import json
import os
import re
import sys
from datetime import datetime
from subprocess import call
# Path to the JSON file we'll read in:
INPUT_FILE = "./notes.json"
# Path to the directory where we'll save the converted notes:
OUTPUT_DIRECTORY = "./notes_converted/"
# Should the creation time of the created files be set to the creation
# time of the original notes?
# Will fail if you're not on a Mac, or don't have Xcode installed -
# in which case set this to False.
KEEP_ORIGINAL_CREATION_TIME = True
# Should the last-modified time of the created files be set to the
# last-modified time of the original notes?
KEEP_ORIGINAL_MODIFIED_TIME = True
def main():
###################################################################
# 1. Set-up and checking.
if not os.path.exists(INPUT_FILE):
sys.exit(f"There is no file at {INPUT_FILE}")
if not os.path.isfile(INPUT_FILE):
sys.exit(f"{INPUT_FILE} is not a file")
tag_position = input("\nWhere should tags be put? Either 'start' or 'end' (default is 'end'):")
if tag_position == "":
tag_position = "end"
if tag_position not in ["start", "end"]:
sys.exit("Enter either 'start' or 'end'.")
if not os.path.isdir(OUTPUT_DIRECTORY):
os.mkdir(OUTPUT_DIRECTORY)
###################################################################
# 2. Loop through all the notes and create new ones
# Empty line before next output
print("")
# The keys will be filenames, the values will be an integer -
# the number of times that filename was used.
filenames = {}
with open(INPUT_FILE, encoding="UTF-8") as json_file:
# Load the JSON data into a dict:
try:
data = json.load(json_file)
except json.decoder.JSONDecodeError as e:
sys.exit(f"Could not parse {INPUT_FILE}. Are you sure it's a JSON file?")
if not isinstance(data, dict):
sys.exit(f"The data from {INPUT_FILE} is not a dict, so it can't be used.")
if "activeNotes" not in data:
sys.exit(f"There is no 'activeNotes' element in the data found in {INPUT_FILE}")
for note in data["activeNotes"]:
# Get all the note's lines into a list:
lines = note["content"].splitlines()
if len(lines) == 0:
# We'll skip any empty notes
print(f"Skipping empty note with ID of {note['id']}")
else:
if "tags" in note:
# Deal with the tags
tags = note["tags"]
# Replace any non-word characters in each tag with a hyphen:
tags = [re.sub(r'\W+', '-', tag) for tag in tags]
# Prefix tags with # so obsidian recognises them as tags:
tags = ["#"+tag for tag in tags]
# Create the tag text we'll insert into the new note:
tag_text = " ".join(tags)
if tag_position == "start":
lines.insert(1, "")
lines.insert(2, tag_text)
else:
lines.append("")
lines.append(tag_text)
# Create the new filename/path based on the first line of the note:
# But trim it to 248 characters so we can keep the entire thing -
# with the possible extra digit(s) added below - under 255 characters.
filename_start = lines[0]
if len(filename_start) > 248:
filename = filename_start[0:248] + ".md"
else:
filename = filename_start + ".md"
# Need to remove any forward slashes or colons:
filename = filename.replace("/", "").replace(":", "")
filepath = os.path.join(OUTPUT_DIRECTORY, filename)
# Keep track of this filename and how many times it's been used:
if filename in filenames:
filenames[filename] += 1
else:
filenames[filename] = 1
if os.path.exists(filepath):
# Don't want to overwrite it!
# So, remove .md, and add the count of how many times this filename
# has been used to the end, to make it unique.
filename = f"{filename[:-3]} {filenames[filename]}.md"
filepath = os.path.join(OUTPUT_DIRECTORY, filename)
#print(f"Writing {note['id']} to '{filepath}'")
with open(filepath, "w", encoding="UTF-8") as outfile:
outfile.write("\n".join(lines))
if KEEP_ORIGINAL_CREATION_TIME:
creation_time = datetime.strptime(
note["creationDate"], "%Y-%m-%dT%H:%M:%S.%fZ"
).strftime("%m/%d/%Y %H:%M:%S %p")
call(["SetFile", "-d", creation_time, filepath])
if KEEP_ORIGINAL_MODIFIED_TIME:
# Set the file access and modified times:
modified_time = datetime.strptime(
note["lastModified"], "%Y-%m-%dT%H:%M:%S.%fZ"
)
modified_time = modified_time.timestamp()
os.utime(filepath, (modified_time, modified_time))
num_files = sum(filenames.values())
files_were = "file was" if num_files == 1 else "files were"
print(f"\n{num_files} .md {files_were} created in {OUTPUT_DIRECTORY}")
if __name__ == "__main__":
main()