前言
花费半天时间,将之前的一个小开发想法落地,作为本月博文分享给大家下
本篇博文仅适用于Eagle用户,非Eagle用户可以直接退出了
但好像更适用于Eagle+开发用户?😑,得,估计Eagle用户看也懵
先了解下前因后果
Eagle软件本身支持文件外链,例如:eagle://item/LT119HK340IHU
通过外链可以直接快速从其他使用Eagle打开指定文件
例如,我有张莲花山的图
![image-20240726195824579](/../images/image-20240726195824579.png)
复制链接,外链是eagle://item/LT119HK30UGE3
,如果在Obsidian或者其他地方点击这个超链接
那么就能迅速打开Eagle跳转到这张图片
![Egale外链示例](/../images/Egale%E5%A4%96%E9%93%BE%E7%A4%BA%E4%BE%8B.gif)
这种外链在引用文件的时候非常非常便捷,尤其是Eagle2.0之后增加更多的格式支持后,可以说就是个万能的资源管理器
我通常使用Eagle作为Obsidian的外部资源拓展,例如视频笔记,例如书签管理
但是其中有个痛点,外链是没办法跨资源库的
Eagle可以创建多个资源库,例如我网站书签放一个资源库,音乐放一个资源库,图片放一个….
我在A资源库复制了文件外链,Eagle处于其他资源库(B、C、D等)的时候,这个文件外链是没办法达成上面效果(直达文件),外链只能打开Eagle而已,失去了直达的效果
这种只能自己手动先切换Eagle资源库成这个文件所在的资源库,再点击链接才有效
可以说是很难受,这个就是外链使用过程中遇到的痛点😕
毕竟多个资源库是不可避免的,于是就想到替代协议,想法落地,就有了本篇
思路
Eagle的外链eagle://item/LT119HK30UGE3
是自定义协议,那么就是通过注册表注册的
打开注册表,在HKEY_CLASSES_ROOT
下搜索Eagle,果然有
定位:\HKEY_CLASSES_ROOT\eagle\shell\open\command
![image-20240726201338625](/../images/image-20240726201338625.png)
可以发现就是将%1
也就是外链eagle://item/LT119HK30UGE3
传递给Eagle.exe
进行打开而已
那么我的思路就是我直接开发个脚本,替换掉注册表中的Eagle.exe
这样每次点击外链,则运行的是我开发的脚本
脚本中实现的逻辑
- 接受参数(文件外链)
- 去查找这个文件是处于哪个资源库
- 使用 API 切换成对应资源库
- 模拟系统命令,向Eagle软件发送外链,实现直达文件
想法如上,开始落地
参考资料
- # Eagle - 图片收集及管理必备工具:Eagle 软件,这里安利一波,五星好评😘😘
- # Eagle API 官方文档:Eagle 官方的 API 文档,好的软件必备👍👍
- # Eagle 媒体资源包:图标资源,用于打包时候使用
代码讲解
接受参数
使用sys.argv
接受外链参数即可
查找文件
原先使用Eagle的 API查找,但发现效率不如直接使用 os
模块的路径判断,所以改用 os
Eagle一个资源库的所有文件是在其资源库下的images
文件夹中,每个文件有个对应id的文件夹
![image-20240726202509878](/../images/image-20240726202509878.png)
直接使用os.path.exist()
进行判断文件是否在这个资源库即可
举例:
外链是eagle://item/LT119HK30UGE3
,提取文件id(LT119HK30UGE3
)
那么使用os.path.exist()
判断该资源库下是否有这个文件夹,就可以知道是处于哪个资源库中了
我个人是所有资源库放在D盘,直接提取所有资源库的名称,进行遍历所有资源库即可
示例代码
1 2 3 4 5 6 7
| library_list = [i for i in os.listdir("D:/Software") if i.endswith(".library")]
for library in library_list: path = f"D:/Software/{library}/images/{item}.info" if os.path.exists(path): pass
|
切换对应资源库
使用Eagle的API就能将Eagle软件切换到对应资源库,API文档具体看参考资料
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
| def switch_library(library_name): data = { "libraryPath": f"D:/Software/{library_name}", }
url = "http://localhost:41595/api/library/switch" headers = { "Content-Type": "application/json", "Accept": "application/json", }
json_data = json.dumps(data)
response = requests.post(url, headers=headers, data=json_data)
if response.ok: result = response.json() print(result) else: print(f"Request failed with status code: {response.status_code}")
try: result = response.json() print(result) except json.JSONDecodeError as error: print(f"Error decoding JSON: {error}")
|
直达
模拟Eagle注册表中的写法,也就是将外链发送给Eagle即可
这里使用subprocess
模块运行系统命令
1 2 3 4 5 6 7 8 9 10 11
| eagle_exe = "D:/Software/Eagle/Eagle.exe"
eagle_link = "eagle://item/LT119HK340IHU"
command = f'"{eagle_exe}" --allow-file-access-from-files "{eagle_link}"'
subprocess.run(command, shell=True)
|
完整代码
将上面的所有功能拼凑起来,实现完整的代码逻辑
注:目前仅适用于个人使用,仅供参考,不要直接运行,是无效果的
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
| import json import os import subprocess import sys
import requests from win10toast import ToastNotifier
def switch_library(library_name): """切换资源库 @param str library_name: 资源库名称 """ data = { "libraryPath": f"D:/Software/{library_name}", } url = "http://localhost:41595/api/library/switch" headers = { "Content-Type": "application/json", "Accept": "application/json", }
json_data = json.dumps(data) response = requests.post(url, headers=headers, data=json_data)
if response.ok: result = response.json() print(result) else: print(f"Request failed with status code: {response.status_code}")
try: result = response.json() print(result) except json.JSONDecodeError as error: print(f"Error decoding JSON: {error}")
def send_notification(title, message): """弹窗提示 @param str title: 弹窗标题 @param str message: 弹窗备注 """ toaster = ToastNotifier() toaster.show_toast(title, message, duration=3)
def main(): """主函数"""
if len(sys.argv) > 1:
eagle_exe = "D:/Software/Eagle/Eagle.exe" eagle_link = sys.argv[1] command = f'"{eagle_exe}" --allow-file-access-from-files "{eagle_link}"'
item = eagle_link.replace("eagle://item/", "") result_lib = None
library_list = [i for i in os.listdir("D:/Software") if i.endswith(".library")]
for library in library_list: path = f"D:/Software/{library}/images/{item}.info" if os.path.exists(path): result_lib = library break
if result_lib: switch_library(result_lib) subprocess.run(command, shell=True)
sys.exit(0) else: send_notification("Eagle 增强插件", "未找到文件")
if __name__ == "__main__": main()
|
打包
注册表中是不能使用脚本的,只能是可执行文件.exe
,所以我们需要将脚本打包成exe
emmm…,也许也可以?将脚本作为参数传递,再将%1
作为参数传递给脚本
像这样"c:\Users\Lin-BLACKBOOK\AppData\Local\Programs\Python\Python310\python.exe" "D:\develop\Python\demo.py" "%1"
,也许可以,没尝试过
我这里是先打包,再使用
使用pyinstaller
打包成单文件Eagle_enhance.exe
想要文件更小,可以使用pipenv
创建个虚拟环境,能使文件小N多
1
| pyinstaller -F -w -i "D:\systemLibrary\Desktop\Eagle\4.ico" Eagle_enhance.pyw
|
为了防止不小心删除,可以将打包后的Eagle_enhance.exe
跟Eagle放一起
![image-20240726204839703](/../images/image-20240726204839703.png)
使用方法
- 运行中输入
regedit
,打开注册表
- 定位:
\HKEY_CLASSES_ROOT\eagle\shell\open\command
- 将项改成打包好的程序位置+空格+
%1
![image-20240726204934424](/../images/image-20240726204934424.png)
- 点击外链,愉快玩耍~
后话
目前仅仅是一个适用个人的版本,会编程的直接改改就能用了
博客看的人还是少,博客+Eagle可能遇到的更加少,所以没有想浪费时间开发通用版的念头,虽然实际可能用不了多少时间
看看吧,如果有需要的朋友也可以留言,可以开发个适用全部人的通用版本程序,直接一键运行完成部署
吐槽个无语的,其实难度不大,开发应该非常快可以完成的,但中途陷入了无限死循环,搞的有点懵,算了,无力吐槽,有这时间刷视频不香吗