利用 Cloudflare Worker 搭建自定义的 Memos WebHook Service
4 min read

利用 Cloudflare Worker 搭建自定义的 Memos WebHook Service

利用 Cloudflare Workers 自定义 Memos 的 WebHook Service,从而实现 memo 记录创建之后能够利用 Telegram bot 转发自定义格式的 memo 到 Telegram Channel/Group
利用 Cloudflare Worker 搭建自定义的 Memos WebHook Service
Photo by Josh Sorenson

Memos WebHook 引入的新场景

之前写过一篇文章解释 WebHook 基本原理和应用场景的:理解 WebHook,对于 WebHook 的应用场景抽象描述就是:现在有系统 A 和系统 B,B 系统关心 A 系统内部的某些事件 E,B 系统会根据事件 E 的具体状态或数据进行其业务逻辑。

在 Memos 应用的场景下又出现了新问题:如果 A 和 B 系统都是黑盒,如何利用 WebHook 技术来实现关于事件 E 的自定义处理?更具体的问题描述:Memos 应用在创建 memo 记录的时候希望在 Telegram Channel/Group 中发送对应 memo 的格式化预览,前提条件是我无法修改 Memos 的 WebHook 逻辑,同时也不能修改 Telegram Channel/Group 发送消息的逻辑,只能使用双方提供的 RESTful API

在没有办法修改系统 A 和系统 B 的情况下,我们只能从 Event 处理着手考虑方案:

Cloudflare Workers

Cloudflare Workers 是一个平台,用于使 severless 功能尽可能接近最终用户运行。本质上,serverless 代码本身是“缓存”在网络上的,并在收到正确类型的请求时运行。Cloudflare Workers 是根据 service workers API 用 JavaScript 编写的,这意味着它们可以使用 service workers 提供的所有功能。它们利用 Chrome V8 引擎执行。Cloudflare Workers 代码托管在 Cloudflare 遍布全球的庞大数据中心网络中。Cloudflare Workers 在 Cloudflare 网络的边缘运行,介于用户和 Internet 的其余部分之间,有效地在网络内部运行。

如下图所示 Cloudflare Workers 运行在 Edge Server 上,它更加靠近用户:

Cloudflare Workers 处理 HTTP 请求的逻辑:

系统 A 在 Event 发生时出发 POST HTTP 请求(此时它就是 client),将请求发送给 Cloudflare Worker 就可以自定义 Event 相关的请求将其转发给系统 B。

Memos WebHook Worker

1. Cloudflare 新建 worker application

如下图所示点击 Create application 即可

2. 初始化 worker project

  1. 安装 nodejs,参考文档Installing Node.js via package manager
  2. 安装 wrangler 工具,npm install -g wrangler
  3. 利用 Cloudflare 账户对 wrangler 进行认证,wrangler login(注意:这里需要浏览器跳转)
  4. 初始化 worker project 代码库,wrangler init --from-dash ${your worker application name}

3. worker project 开发

Memos WebHook 对应的 worker 逻辑比较简单,代码如下:

export default {
	async fetch(request: WorkerRequest, env: Env, ctx: ExecutionContext): Promise<Response> {
		const url = new URL(request.url)
		console.log(request)
		const TOKEN = env.ENV_BOT_TOKEN
		const SECRET = env.ENV_BOT_SECRET

		if (url.pathname === '/') {
			const memo: Memo = await request.json()
			// Deal with response asynchronously
			let query = '?' + new URLSearchParams({
				chat_id: env.CHAT_ID,
				text: memo.memo.content,
			}).toString()

			const res = (await fetch(`https://api.telegram.org/bot${TOKEN}/sendMessage${query}`)).json()
			return new Response(JSON.stringify(res, null, 2))
		} else {
			return new Response('Not supported url request!');
		}
	},
};

4. 部署 worker

开发测试完成之后,就可以发布 worker 了,wrangler deploy 即可。部署成功之后可以在 worker overview 中找到对应的 worker URL,如下图所示。

5. Memos WebHook 配置

如下图所示,在 Memos -> Settings -> Preferences -> Webhooks 中添加 worker URL 即可。

后续思考

Telegram Bot 转发属于比较简单 worker 处理,其实 memos 原生就可以转发到 Telegram(参考Integration with Telegram Bot - Memos),上文的 worker 更多的是出于测试和练习的目的,有了这个基础之后其实有很多事情就可以做了:

  • 借助 worker 可以利用 Github Actions 自动备份 memos 到 Obsidian
  • 支持转发到 mastodon 等其他平台
  • ……

References

  1. 无服务器 JavaScript 的工作原理| Service Workers 和 Cloudflare Workers | Cloudflare
  2. Webhook - Memos

Public discussion