#!/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(
' ("") 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
```
"""