#!/usr/bin/env python3 """ # Script ob-eagle ## Metadata **Kind**: #obsidian/ob-script **Language**: #python **Parent**:: [[Obsidian Chore Scripts]], [[Eagle App]], [[Executable Markdown File]] ## Synopsis Export Eagle Library into Obsidian. Example:: [[Eagle Assets - Fonts]] ![[eagle-assets-fonts-snapshot.png]] ## Script ```python # """ import tempfile import os import filecmp import json from pathlib import Path from contextlib import contextmanager from urllib.request import urlopen, Request, HTTPError from urllib.parse import urlparse, quote def walk_folder(folder, parent, collected_folders): collected_folders.append(folder) folder['path'] = parent / folder['name'] folder['md_name'] = 'Eagle ' + ' - '.join(folder['path'].parts) for child in folder['children']: walk_folder(child, folder['path'], collected_folders) @contextmanager def markdown_writer(file_path): md_fd, tmp_path = tempfile.mkstemp(suffix='.md', text=True) tmp_path = Path(tmp_path) try: md_io = os.fdopen(md_fd, 'w', newline="\n") try: yield md_io finally: md_io.close() if not file_path.exists() or not filecmp.cmp(tmp_path, file_path, shallow=False): print('New: {}'.format(file_path.name)) os.replace(tmp_path, file_path) finally: if tmp_path.exists(): tmp_path.unlink() def get_thumbnail(file_path, thumbnail_path): if file_path.exists(): for line in file_path.read_text().splitlines(): if line.startswith('**Thumbnail**:: '): cached_link = line[len('**Thumbnail**:: '):].strip() return cached_link bearer = "Bearer " + os.environ['DROPBOX_ACCESS_TOKEN'] thumbnail_relative_path = thumbnail_path.relative_to( Path.home() / 'Dropbox') print("Get Dropbox Link to: /{}".format(thumbnail_relative_path)) create_req = Request( "https://api.dropboxapi.com/2/sharing/create_shared_link_with_settings", headers={ "Authorization": bearer, "Content-Type": "application/json", }, data=json.dumps({ "path": f"/{thumbnail_relative_path}", "settings": { "allow_download": True, "audience": "public", "access": "viewer" } }).encode('utf-8') ) try: with urlopen(create_req) as create_res: create_res_json = json.loads(create_res.read().decode('utf-8')) return get_dropbox_raw_url(create_res_json['url']) except HTTPError as error: if error.code != 409: raise error return get_thumbnail_shared_link(thumbnail_relative_path, bearer) def get_thumbnail_shared_link(thumbnail_relative_path, bearer): req = Request( "https://api.dropboxapi.com/2/sharing/list_shared_links", headers={ "Authorization": bearer, "Content-Type": "application/json", }, data=json.dumps({ "path": f"/{thumbnail_relative_path}", }).encode('utf-8') ) with urlopen(req) as res: res_json = json.loads(res.read().decode('utf-8')) return get_dropbox_raw_url(res_json['links'][0]['url']) def get_dropbox_raw_url(dl_url): return urlparse(dl_url)._replace(query='raw=1').geturl() def auto_color(r, g, b): brightness = 0.2126 * r + 0.7152 * g + 0.0722 * b if brightness > 144: return 'black' return 'white' THUMBNAIL_EXTS = ['.png', '.jpg', '.jpeg', '.gif', '.bmp', '.svg'] def export_image(parent_path, metadata, indexed_folders): asset_path = parent_path / (metadata['name'] + "." + metadata['ext']) thumbnail_path = parent_path / (metadata['name'] + "_thumbnail.png") if not asset_path.exists(): raise Exception('Asset not found: {}'.format(asset_path)) if not thumbnail_path.exists(): thumbnail_path = asset_path if thumbnail_path.suffix.lower() not in THUMBNAIL_EXTS: thumbnail_path = None md_name = 'Eagle ' + metadata['id'] file_path = export_dir / 'images' / f'{md_name}.md' with markdown_writer(export_dir / 'images' / f'{md_name}.md') as md_io: print('---', file=md_io) print(f'aliases: "Eagle {metadata["name"]}"', file=md_io) if 'private' in metadata['tags']: print('publish: false', file=md_io) print('---', file=md_io) print(f'# {metadata["name"]}\n', file=md_io) print('## Metadata\n', file=md_io) print('**Kind**:: #eagle/image', file=md_io) print('**Generated by**:: [[ob-eagle]]', file=md_io) print(f'**Name**:: {metadata["name"]}', file=md_io) print(f'**Ext**:: {metadata["ext"]}', file=md_io) if len(metadata['tags']) > 0: print(f'**Tags**:: #{", #".join(metadata["tags"])}', file=md_io) folders = [ f'[[{indexed_folders[id]["md_name"]}]]' for id in metadata['folders']] print(f'**Parent**:: {", ".join(folders)}', file=md_io) dropbox_path = parent_path.relative_to(Path.home() / 'Dropbox') print('**Dropbox Directory**:: [Open Directory in Dropbox](https://www.dropbox.com/home/{})'.format( quote(str(dropbox_path.as_posix()))), file=md_io) if thumbnail_path is not None: preview_link = get_thumbnail(file_path, thumbnail_path) print(f'**Thumbnail**:: {preview_link}', file=md_io) print('\n## Thumbnail\n', file=md_io) print(f'![{metadata["name"]}]({preview_link})', file=md_io) if len(metadata['palettes']) > 0: print('\n## Palette\n', file=md_io) print('\n| Ratio | Color |\n| --- | --- |', file=md_io) for color in metadata['palettes']: hex_color = ''.join(f'{c:0>2X}' for c in color['color']) colorized_rgb = f'<code style="color:{auto_color(*color["color"])}; background:#{hex_color}"> {hex_color} </code>' print( f'| {color["ratio"]} | {colorized_rgb} |', file=md_io) export_dir = Path.home() / 'Dropbox' / 'Brain' / 'robot' / 'Eagle Library' (export_dir / 'images').mkdir(parents=True, exist_ok=True) (export_dir / 'folders').mkdir(parents=True, exist_ok=True) eagle_library = Path.home() / 'Dropbox' / 'Eagle.library' metadata = json.load((eagle_library / 'metadata.json').open()) collected_folders = [] for folder in metadata['folders']: walk_folder(folder, Path(), collected_folders) # create root folder with markdown_writer(export_dir / 'folders' / 'Eagle Roots.md') as md_io: print('# Eagle Roots\n', file=md_io) print('## Metadata\n', file=md_io) print('**Kind**:: #eagle/folder', file=md_io) print('**Generated by**:: [[ob-eagle]]\n', file=md_io) print('## Children\n', file=md_io) for folder in collected_folders: if len(folder['path'].parts) == 1: print(f'- [[{folder["md_name"]}]]', file=md_io) for folder in collected_folders: with markdown_writer(export_dir / 'folders' / f'{folder["md_name"]}.md') as md_io: print('---', file=md_io) print('cssclasses: ["max", "cards", "cards-cols-6"]', file=md_io) print('---', file=md_io) print(f'# {folder["md_name"]}\n', file=md_io) print('## Metadata\n', file=md_io) print(f'**ID**:: {folder["id"]}', file=md_io) print('**Kind**:: #eagle/folder', file=md_io) print('**Generated by**:: [[ob-eagle]]', file=md_io) parent = folder['path'].parent if len(parent.parts) == 0: print('**Parent**:: [[Eagle Roots]]', file=md_io) else: print( f'**Parent**:: [[Eagle {" - ".join(parent.parts)}]]', file=md_io) if len(folder['tags']) > 0: print(f'**Tags**:: #{", #".join(folder["tags"])}', file=md_io) if folder["description"] != "": print('\n## Description\n', file=md_io) print(folder['description'], file=md_io) children = [ f for f in collected_folders if f['path'].parent == folder['path']] if len(children) > 0: print('\n## Children\n', file=md_io) for child in children: print(f'- [[{child["md_name"]}]]', file=md_io) print('\n## Images\n', file=md_io) print('```dataview', file=md_io) print('table without id', file=md_io) print(' link(file.link, Name + "." + Ext) as Image,', file=md_io) print( ' ("![" + Name + "](" + Thumbnail + ")") as Thumbnail,', file=md_io) print(' default(Tags, "") as Tags', file=md_io) print('from "robot/Eagle Library/images"', file=md_io) print('where contains(Parent, [[]])', file=md_io) print('```', file=md_io) indexed_folders = {} for f in collected_folders: indexed_folders[f['id']] = f for root, dirs, files in os.walk(eagle_library / 'images'): for file in filter(lambda f: f == 'metadata.json', files): file_path = Path(root) / file try: metadata = json.load(file_path.open()) if "isDeleted" in metadata and metadata["isDeleted"]: continue export_image(file_path.parent, metadata, indexed_folders) except json.decoder.JSONDecodeError: print('Skip: Eagle {}'.format(file_path.parent.stem)) continue """ # vim: ft=python ``` """