Eagle外链增强
前言
花费半天时间,将之前的一个小开发想法落地,作为本月博文分享给大家下
本篇博文仅适用于Eagle用户,非Eagle用户可以直接退出了
但好像更适用于Eagle+开发用户?😑,得,估计Eagle用户看也懵
先了解下前因后果
Eagle软件本身支持文件外链,例如:eagle://item/LT119HK340IHU
通过外链可以直接快速从其他使用Eagle打开指定文件
例如,我有张莲花山的图
复制链接,外链是eagle://item/LT119HK30UGE3
,如果在Obsidian或者其他地方点击这个超链接
那么就能迅速打开Eagle跳转到这张图片
这种外链在引用文件的时候非常非常便捷,尤其是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
可以发现就是将%1
也就是外链eagle://item/LT119HK30UGE3
传递给Eagle.exe
进行打开而已
那么我的思路就是我直接开发个脚本,替换掉注册表中的Eagle.exe
这样每次点击外链,则运行的是我开发的脚本
脚本中实现的逻辑
- 接受参数(文件外链)
- 去查找这个文件是处于哪个资源库
- 使用 API 切换成对应资源库
- 模拟系统命令,向Eagle软件发送外链,实现直达文件
想法如上,开始落地
参考资料
- # Eagle - 图片收集及管理必备工具:Eagle 软件,这里安利一波,五星好评😘😘
- # Eagle API 官方文档:Eagle 官方的 API 文档,好的软件必备👍👍
- # Eagle 媒体资源包:图标资源,用于打包时候使用
代码讲解
接受参数
使用sys.argv
接受外链参数即可
url = sys.argv[1]
查找文件
原先使用Eagle的 API查找,但发现效率不如直接使用 os
模块的路径判断,所以改用 os
Eagle一个资源库的所有文件是在其资源库下的images
文件夹中,每个文件有个对应id的文件夹
直接使用os.path.exist()
进行判断文件是否在这个资源库即可
举例:
外链是eagle://item/LT119HK30UGE3
,提取文件id(LT119HK30UGE3
)
那么使用os.path.exist()
判断该资源库下是否有这个文件夹,就可以知道是处于哪个资源库中了
我个人是所有资源库放在D盘,直接提取所有资源库的名称,进行遍历所有资源库即可
示例代码
# 读取所有资源库名称
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文档具体看参考资料
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格式的字符串
json_data = json.dumps(data)
# 发送POST请求
response = requests.post(url, headers=headers, data=json_data)
# 检查请求是否成功
if response.ok:
# 解析JSON响应
result = response.json()
print(result)
else:
print(f"Request failed with status code: {response.status_code}")
# 处理可能发生的异常
try:
# 可以尝试再次解析JSON响应
result = response.json()
print(result)
except json.JSONDecodeError as error:
print(f"Error decoding JSON: {error}")
直达
模拟Eagle注册表中的写法,也就是将外链发送给Eagle即可
这里使用subprocess
模块运行系统命令
# 定义Eagle执行文件的路径
eagle_exe = "D:/Software/Eagle/Eagle.exe"
# 定义要打开的Eagle链接
eagle_link = "eagle://item/LT119HK340IHU"
# 构建命令
command = f'"{eagle_exe}" --allow-file-access-from-files "{eagle_link}"'
# 使用subprocess.run执行命令
subprocess.run(command, shell=True)
完整代码
将上面的所有功能拼凑起来,实现完整的代码逻辑
注:目前仅适用于个人使用,仅供参考,不要直接运行,是无效果的
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格式的字符串
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:
# 尝试再次解析JSON响应
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执行文件的路径
eagle_link = sys.argv[1] # 定义要打开的Eagle链接
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 增强插件", "未找到文件")
# print("未找到文件")
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多
pyinstaller -F -w -i "D:\systemLibrary\Desktop\Eagle\4.ico" Eagle_enhance.pyw
为了防止不小心删除,可以将打包后的Eagle_enhance.exe
跟Eagle放一起
使用方法
- 运行中输入
regedit
,打开注册表 - 定位:
\HKEY_CLASSES_ROOT\eagle\shell\open\command
- 将项改成打包好的程序位置+空格+
%1
- 点击外链,愉快玩耍~
后话
目前仅仅是一个适用个人的版本,会编程的直接改改就能用了
博客看的人还是少,博客+Eagle可能遇到的更加少,所以没有想浪费时间开发通用版的念头,虽然实际可能用不了多少时间
看看吧,如果有需要的朋友也可以留言,可以开发个适用全部人的通用版本程序,直接一键运行完成部署
吐槽个无语的,其实难度不大,开发应该非常快可以完成的,但中途陷入了无限死循环,搞的有点懵,算了,无力吐槽,有这时间刷视频不香吗