summaryrefslogtreecommitdiffstats
path: root/keep-to-markdown.py
blob: 1ebe58ea3a6cb7e900ec061698ea02d1b05c856c (plain)
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#!/bin/python

import os
import sys
import platform
import glob
import json
from datetime import datetime as dt
from shutil import copy2 as cp
import mimetypes
import argparse


def copy_file(file, path, notespath):
    try:
        cp(f'{path}{file}', os.path.join(notespath, 'resources'))
    except FileNotFoundError:
        print(f'File "{file}" not found in {path}')
        return False
    else:
        return True

# remove illegal chars for current OS
def clean_title(title) -> str:
    ostype = platform.system()
    if ostype == 'Linux':
        title = title.replace('/', '_')
    elif ostype == 'Darwin':
        title = title.replace(':', ' ')
        title = title.replace('\\', '_').replace('/', '_').replace('|', '_')
    elif ostype == 'Windows':
        title = title.replace('\\', '_').replace('/', '_').replace('|', '_')
        title = title.replace('<', '-').replace('>', '-').replace(':', ' ')
        title = title.replace('?', '').replace('"', '').replace('*', '')
        title = title.replace('\n', '')
    return title

def read_annotations(list) -> str:
    annotations_list = '*Weblinks:*'
    for entry in list:
        if entry['source'] == 'WEBLINK':
            title = entry['title']
            url = entry['url']
            annotations_list += f' [{title}]({url});'
    return annotations_list

def read_attachments(list, path, notespath) -> str:
    attachments_list = '*Attachments:*\n'
    for entry in list:
        if 'image' in entry['mimetype']:
            image = entry['filePath']
            if copy_file(image, path, notespath) is False:
                # If the file could not be found,
                # it will be checked if the file can be found
                # another file format.
                # Google used '.jpeg' instead of '.jpg'
                image_type = mimetypes.guess_type(f'{path}{image}')
                types = mimetypes.guess_all_extensions(image_type[0])
                for type in types:
                    if type in image:
                        image_name = image.replace(type, '')
                        for t in types:
                            if len(glob.glob(f'{path}{image_name}{t}')) > 0:
                                image = f'{image_name}{t}'
                                print(f'Found "{image}"')
                                copy_file(image, path, notespath)
            respath = os.path.join('resources','')
            attachments_list += f'![{image}]({respath}{image})\n'
    return attachments_list

def read_tasklist(list) -> str:
    content_list = '*Tasklist:*\n'
    for entry in list:
        text = entry['text']
        if entry['isChecked'] is True:
            content_list += f'- [x] {text}\n'
        else:
            content_list += f'- [ ] {text}\n'
    return content_list

def format_tags(tags) -> str:
    tag_list = 'tags:'
    for tag in tags:
        tag_list += f' {tag};'
    return tag_list

def read_write_notes(args):
    path = args.i
    conv_folders = args.t
    jsonpath = os.path.join(path, '')
    notes = glob.glob(f'{jsonpath}*.json')

    for note in notes:
        with open(note, 'r', encoding='utf-8') as jsonfile:
            data = json.load(jsonfile)
            timestamp = data['userEditedTimestampUsec']
            tags = []
            try:
                tags = [label['name'] for label in data['labels']]
            except KeyError:
                    print('No tags available.')

            if timestamp == 0:
                iso_datetime = dt.now().strftime('%Y%m%dT%H%M%S_edited')
            else:
                iso_datetime = dt.fromtimestamp(timestamp/1000000).strftime('%Y%m%dT%H%M%S')

            # get filename by title
            if data['title'] != '':
                title = str(data['title'])
                filename = clean_title(title)
                if len(filename) > 100:
                    filename = filename[0:99]
            else:
                title = iso_datetime
                filename = title

            # create folders by tags
            if conv_folders and len(tags):
                subfolder = tags[0]
            else:
                subfolder = ''
            notespath = os.path.join('notes', subfolder, '')

            # check if filename exists
            if os.path.exists(f'{notespath}{filename}.md'):
                print(f'Existing file found: {notespath}{filename}.md')
                # increment duplicate number, if already exists
                dup_num = 1
                while(os.path.exists(f'{notespath}{filename}({dup_num}).md')):
                    print(f'File "{notespath}{filename}({dup_num}).md" exists, increment number...')
                    dup_num = dup_num+1

                filename = f'{filename}({dup_num})'
                print(f'New filename: {filename}.md')

            # create path to notes
            if not os.path.exists(notespath):
                os.makedirs(notespath)
                os.makedirs(os.path.join(notespath, 'resources'))
                print(f'Create tag and resources subfolder: {subfolder}')

            # create Markdown file
            print(f'Convert "{title}" to markdown file.')
            with open(f'{notespath}{filename}.md', 'w', encoding='utf-8') as mdfile:
                mdfile.write(f'---\n')
                mdfile.write(f'title: {title}\n')
                if (title != iso_datetime):
                    mdfile.write(f'date: {iso_datetime}\n')
                # add tags
                if(tags and not conv_folders):
                    mdfile.write(f'{format_tags(tags)}\n')
                mdfile.write(f'---\n\n')
                # add text content
                try:
                    textContent = data['textContent']
                    mdfile.write(f'{textContent}\n\n')
                except KeyError:
                    print('No text content available.')
                # add tasklist
                try:
                    tasklist = read_tasklist(data['listContent'])
                    mdfile.write(f'{tasklist}\n\n')
                except KeyError:
                    print('No tasklist available.')
                # add annotations
                try:
                    annotations = read_annotations(data['annotations'])
                    mdfile.write(f'{annotations}')
                except KeyError:
                    print('No annotations available.')
                # add attachments
                try:
                    attachments = read_attachments(data['attachments'], path, notespath)
                    mdfile.write(f'{attachments}')
                except KeyError:
                    print('No attachments available.')

def create_folder():
    try:
        workpath = os.path.join('notes', 'resources')
        if not os.path.exists(workpath):
            os.makedirs(workpath)
            print('Create folder "notes" - home of markdown files.')
    except OSError:
        print('Creation of folders failed.')

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Converting Google Keep notes to markdown files.')
    parser.add_argument('-i', metavar='PATH', required=True, help='The path to the Takeout folder.')
    parser.add_argument('-t', action='store_true', help='Use folders instead of front-matter for tags.')
    args = parser.parse_args()

    create_folder()
    try:
        read_write_notes(args)
    except IndexError:
        print('Please enter a correct path!')