前言

花费半天时间,将之前的一个小开发想法落地,作为本月博文分享给大家下

本篇博文仅适用于Eagle用户,非Eagle用户可以直接退出了
但好像更适用于Eagle+开发用户?😑,得,估计Eagle用户看也懵

先了解下前因后果

Eagle软件本身支持文件外链,例如:eagle://item/LT119HK340IHU
通过外链可以直接快速从其他使用Eagle打开指定文件

例如,我有张莲花山的图

image-20240726195824579

复制链接,外链是eagle://item/LT119HK30UGE3,如果在Obsidian或者其他地方点击这个超链接
那么就能迅速打开Eagle跳转到这张图片

Egale外链示例

这种外链在引用文件的时候非常非常便捷,尤其是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

可以发现就是将%1也就是外链eagle://item/LT119HK30UGE3传递给Eagle.exe进行打开而已

那么我的思路就是我直接开发个脚本,替换掉注册表中的Eagle.exe
这样每次点击外链,则运行的是我开发的脚本

脚本中实现的逻辑

  1. 接受参数(文件外链)
  2. 去查找这个文件是处于哪个资源库
  3. 使用 API 切换成对应资源库
  4. 模拟系统命令,向Eagle软件发送外链,实现直达文件

想法如上,开始落地

参考资料

  1. # Eagle - 图片收集及管理必备工具:Eagle 软件,这里安利一波,五星好评😘😘
  2. # Eagle API 官方文档:Eagle 官方的 API 文档,好的软件必备👍👍
  3. # Eagle 媒体资源包:图标资源,用于打包时候使用

代码讲解

接受参数

使用sys.argv接受外链参数即可

1
url = sys.argv[1]

查找文件

原先使用Eagle的 API查找,但发现效率不如直接使用 os 模块的路径判断,所以改用 os

Eagle一个资源库的所有文件是在其资源库下的images文件夹中,每个文件有个对应id的文件夹

image-20240726202509878

直接使用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格式的字符串
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模块运行系统命令

1
2
3
4
5
6
7
8
9
10
11
# 定义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)

完整代码

将上面的所有功能拼凑起来,实现完整的代码逻辑
注:目前仅适用于个人使用,仅供参考,不要直接运行,是无效果的

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格式的字符串
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多

1
pyinstaller -F -w -i "D:\systemLibrary\Desktop\Eagle\4.ico" Eagle_enhance.pyw

为了防止不小心删除,可以将打包后的Eagle_enhance.exe跟Eagle放一起

image-20240726204839703

使用方法

  1. 运行中输入regedit,打开注册表
  2. 定位:\HKEY_CLASSES_ROOT\eagle\shell\open\command
  3. 将项改成打包好的程序位置+空格+%1
    image-20240726204934424
  4. 点击外链,愉快玩耍~

后话

目前仅仅是一个适用个人的版本,会编程的直接改改就能用了
博客看的人还是少,博客+Eagle可能遇到的更加少,所以没有想浪费时间开发通用版的念头,虽然实际可能用不了多少时间

看看吧,如果有需要的朋友也可以留言,可以开发个适用全部人的通用版本程序,直接一键运行完成部署

吐槽个无语的,其实难度不大,开发应该非常快可以完成的,但中途陷入了无限死循环,搞的有点懵,算了,无力吐槽,有这时间刷视频不香吗


Eagle外链增强
https://linguoguang.com/2024/07/26/2024.07.26/
作者
linguoguang
发布于
2024年7月26日
许可协议