前言※
之前在做微信机器人的时候(见: 制作一个微信机器人 ),突然想到能不能在微信上发送一条消息就可以将笔记记录到 trilium 中,毕竟手机浏览 web 端的体验实在是有些别扭。
摸索一番后发现 trilium 有相应的 API 可供调用而且还支持自定义 API,于是打算在微信机器人中增加与 trilium 的联动。
目前实现的功能※
- 记录灵感 - 记录突然想到的事情
- 记录日记 - 记录今日的想法
- 在日程表上记录重要事件
- 查看重要事件倒数日
- 查看待办任务
- 新建待办任务
准备工作※
导入 python 包 trilium-py,这个库中封装了部分 trilium 的常用方法。使用前需要初始化自己的笔记地址和 token。
def __init__(self) -> None:
server_url = 'https://domain:8080'
token = 'mytoken'
self.ea = ETAPI(server_url, token)
记录灵感※
我的习惯是在今日日记下方建立子笔记方便日后回溯,首先建立一个方法,用于处理事件。
def sendInspiration(self,title="新灵感",content=""):
pass
所以首先需要做的是获取今日日记笔记的 id。
today = str(datetime.today().date())
todayNoteId = self.ea.get_day_note_id(today)
在笔记下方建立子笔记,传入标题和内容,并且设置前缀【灵感】。
res = self.ea.create_note(parentNoteId=todayNoteId,type="text",title=title,content=content,prefix="灵感")
此外,我还习惯在【灵感】笔记上打标签,一个是【#灵感】方便查找,另一个是【#createdDate=<创建日期>】,方便使用 Trilium-collection-views.进行布局。
self.ea.create_attribute(attributeId="",noteId=res["note"]["noteId"],name="灵感",type="label",value="",isInheritable=False)
self.ea.create_attribute(attributeId="",noteId=res["note"]["noteId"],name="createdDate",type="label",value=today,isInheritable=False)
至此微信机器人可以通过调用sendInspiration
方法记录灵感,在微信机器人的监听方法中加入判断:
记录重要事件 elif "灵感" == newMsg[1][0:2]:
content = newMsg[1][3:]
title = loopTips("请输入标题")
res = triliumtools.sendInspiration(title,content)
wechat.SendMsg(res)
效果如下图:
记录日记也是同理,在此不做赘述。
记录重要日程※
这里需要一个 trilium 插件: trilium-scripts.,这是一个更好的日历视图,可以直观的显示某天的日程安排和重要事项,效果如下图所示:
这个插件通过在日记笔记中增加设定的标签,可以在视图中显示相应的事件,比如在 1 月 10 日的日记笔记中增加标签:#Event=理发
,就会在日历的相应位置显示事件。
所以我们需要做的就是接受相应的参数,在指定的日记笔记中添加标签即可。
创建方法:
def setEvent(self,type,date,name):
dateId = self.ea.get_day_note_id(date)
self.ea.create_attribute(attributeId="",noteId=dateId,name=type,type="label",value=name,isInheritable=False)
return "记录成功!"
在微信机器人的监听方法中增加新的判断:
elif "Event" in newMsg[1] or "Holiday" in newMsg[1] or "Birthday" in newMsg[1]:
res = newMsg[1].split(" ")
if re.search(r'\d{1,2}-\d{1,2}-\d{1,2}',res[1]) == None:
wechat.SendMsg("日期有误!")
else:
anser = triliumtools.setEvent(res[0],res[1],res[2])
wechat.SendMsg(anser)
这里我只设定了Event
、Holiday
、Birthday
三个事件,之后只需要在与机器人对话的时候传入相应的关键词、日期和事件即可记录到 trilium 中,效果如下图:
获取倒数日※
倒数日是我在上一步中的插件上进行的魔改,在日历下方增加了倒数日功能,效果图如下:
它会根据我们设立的事件标签,动态生成事件并且自动算出距离事件的日期。
现在我需要实现的是向微信机器人发送【倒数日】三个字,然后微信机器人将倒数日推送给我。
显然 trilium-py 无法实现我的需求,这时候需要自己定义一个 API 接口,说到这里我又不得不感叹 trilium 真是一个神级软件,可拓展性也太强了。
新建一个后端 js 代码笔记,添加一个标签#customRequestHandler=daysMatter
,代码如下:
const {req,res} = api;
api.log('获取倒数日 api 调用');
function putHTML (type,eventName,date) {
var nowDate = new Date();
var lastDate = new Date(date);
if ((type == "Birthday" || type == "Holiday") && (nowDate > lastDate)) {
return
}
if (nowDate >= lastDate){
var days = parseInt((nowDate - lastDate)/(1000*3600*24))
var infoText = "⋆ "+eventName+"已经:"+days+"天"
}else {
var days = parseInt((lastDate - nowDate)/(1000*3600*24))+1
var infoText = "⋆ "+eventName+"还有:"+days+"天"
}
return infoText
}
if (req.method == 'GET' ) {
var types=["Event","Birthday","Holiday"]
var newArr =[]
for (const type of types) {
var attrs = api.sql.getColumn(`SELECT DISTINCT value FROM attributes WHERE name='`+type+`' AND isDeleted =0`)
for (attr of attrs) {
notes = api.getNotesWithLabel(type,attr)
targetNote = notes[[notes.length-1]]
noteTitle = targetNote.title.substring(0,11)
templist = [type,attr,noteTitle]
newArr.push(templist)
}
}
var msgs = []
for (const note of newArr) {
msgs.push(putHTML(note[0],note[1],note[2]))
}
res.status(201).json(msgs);
}
else {
api.log("请求参数错误, 返回 400");
res.send(400);
}
之后即可通过https://域名/custom/daysMatter
进行访问,如此一来即可使用 requests 获取返回值,代码如下:
def daysMatter():
wechat = WeChat()
wechat.ChatWith("东东")
msgs = []
url = "https://domain:8080/custom/countdown"
headers = {
'Accept': "application/json, text/plain, */*",
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
'Connection':'close'
}
requests.DEFAULT_RETRIES = 5 # 增加重试连接次数
s = requests.session()
s.keep_alive = False # 关闭多余连接
try:
res = requests.get(url,headers=headers)
for event in res.json():
if event !=None:
msgs.append(event)
wechat.SendWrapMsg(msgs)
except:
wechat.SendMsg("trilium 连接失败……")
最终实现的效果如下图:
任务管理※
之前在这篇文章中介绍过 trilium 的任务管理功能:改进 trilium 的任务管理功能 。
因为平时不方便使用电脑的时候有查看当前待办事项的需求,所以使用微信机器人快速查看任务是个不错的方法,调用 trilium-py 可以很方便的实现这一功能,代码如下:
def findTask(self,type):
msgs = []
boxNoteId = "HDjVNjIYU3iI"
doingNoteId = "WgDRTZpY7StM"
serchId = (type == "盒子") and boxNoteId or doingNoteId
try:
childsNoteId = self.ea.get_note(serchId)["childNoteIds"]
for childNoteId in childsNoteId:
title = self.ea.get_note(childNoteId)["title"]
msgs.append(title)
except:
msgs.append("连接失败……")
return msgs
新建任务的方法与上文类似,不过多赘述, 但是有一点需要注意的是,我的任务是由模板创建的,类似下图:
所以在建立任务笔记的时候需要增加一个关系标签,将template
指向任务模板:
create_attribute(attributeId="",noteId=res["note"]["noteId"],name="template",type="relation",value="任务模板",isInheritable=False)
结语※
经过这么一番折腾之后,我可以在微信中实现与云端笔记的交互。