Skip to content

Instantly share code, notes, and snippets.

@nWestie
Last active March 7, 2024 20:34
Show Gist options
  • Save nWestie/224d14a6efd00661b5c93040c7511816 to your computer and use it in GitHub Desktop.
Save nWestie/224d14a6efd00661b5c93040c7511816 to your computer and use it in GitHub Desktop.
Transforms a notally backup file into a quillPad one. use at your own risk, it worked for my backup, but I others may differ. Does not deal with note color
import sqlite3
import json
import shutil
import os
tags = []
joins = []
# Tested with Notally v5.2 and QuillPad v1.4.9
# will not preserve note color
def main():
tmpFolder = ".tmp"
quillpadJSON = {"version": "13",
"notes": [], "tags": []}
# Open a database File
shutil.unpack_archive('notally.zip', tmpFolder)
db = sqlite3.connect(tmpFolder + '/NotallyDatabase')
dbCursor = db.cursor()
headers = ["ID", "type", "folder", "color", "title", "pinned",
"timestamp", "labels", "body", "spans", "items"]
for row in dbCursor.execute("SELECT * FROM BaseNote"):
note = parseNotallyNote(dict(zip(headers, row)))
quillpadJSON["notes"].append(note)
db.close()
quillpadJSON["tags"] = tags
quillpadJSON["joins"] = joins
if not os.path.exists(tmpFolder):
os.makedirs(tmpFolder)
with open(tmpFolder + '/backup.json', 'w') as jsonOut:
json.dump(quillpadJSON, jsonOut)
os.remove(tmpFolder + '/NotallyDatabase')
shutil.make_archive(
"QuillPadFromNotally", "zip", root_dir=tmpFolder, base_dir=".")
shutil.rmtree(tmpFolder)
def parseNotallyNote(note):
noteDict = {}
noteDict['id'] = note['ID']
noteDict['title'] = note['title']
timeStamp = (int)(note['timestamp']/1000)
noteDict['modifiedDate'] = timeStamp
noteDict['creationDate'] = timeStamp
if (note['pinned'] == 1):
noteDict['isPinned'] = True
if (note['type'] == "NOTE"):
noteDict['content'] = note['body']
noteDict['isMarkdownEnabled'] = False
elif (note['type'] == "LIST"):
# body, checked
lst = json.loads(note['items'])
outlist = []
for i, item in enumerate(lst):
outlist.append(
{"id": i, "content": item["body"], "isDone": item['checked']})
noteDict['isList'] = True
noteDict['taskList'] = outlist
if (note['folder'] == "DELETED"):
noteDict['isDeleted'] = True
elif (note['folder'] == "ARCHIVED"):
noteDict['isArchived'] = True
labels = json.loads(note['labels'])
if len(labels) == 0:
return noteDict
noteDict['tags'] = []
for l in labels:
hasTag = [t for t in tags if t['name'] == l]
if len(hasTag) > 0:
tag = hasTag[0]
else:
tag = {"id": len(tags)+1, "name": l}
tags.append(tag)
noteDict['tags'].append(tag)
joins.append(
{"noteId": noteDict["id"], "tagId": tag['id']})
return noteDict
if __name__ == "__main__":
exit(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment