zhongfly / blog

https://blogsue.vercel.app/#/
9 stars 3 forks source link

订阅转换前端(sub-web)+后端(subconverter)自动更新 #3

Open zhongfly opened 4 years ago

zhongfly commented 4 years ago

先上成果:github项目链接 前端及转换接口


今年将代理应用从ssr换成了目前使用广泛并且分流更好用的Clash。熟悉了clash配置后,为了能自动将机场订阅转换成clash配置,并且快捷的自定义规则,就用了subconverter 来满足需求。

为什么要自己搭在线接口呢?

原因有:

  1. 在线接口方便移动设备使用,在手机上运行本地版太麻烦;
  2. 之前出现过在线接口的再开发者泄露网站数据库账号,导致请求的订阅转换链接泄露,自己搭建更安全;
  3. 很多在线接口的后端版本更新并不及时,一些bug的修复在github上已经完成,但却没被在线接口使用,或者会限制文件大小/规则行数导致订阅转换失败;
  4. 自己无聊

如何实现后端的自动编译更新?

一开始发现了T大自己部署到vercel(原now.sh)的项目 ,包含了vercel的部署配置文件,但是更新后端需要手动再部署(本地下载后端最新版,解压,修改配置文件,用vercel的命令行工具部署),很是麻烦。

又看到了有人做了用github action自动更新的项目 ,给予了我很大启示。

于是确定了用github action触发后端(subconverter)更新的方法,但是这个项目是每天定时更新,并且拉取的是最新release版本,而不是最新commit(subconverter只会在版本号更新时才发布release)。

到这里问题就有2个:

  1. 前者根据网络搜索知道每个github项目都有官方提供rss链接订阅commit,只需要找到一个网络服务(如ifttt) 能够在rss更新后触发github action就行

  2. 后者更为简单,因为在后端项目中本来就有用github action来编译测试版,复制粘贴下github action的workflow文件即可。

第一个问题其实并没有想象中的简单,ifttt并不能直接触发github action运行,官方提供的动作只有新建issue等3个。考虑到完全靠issue触发的话,可能出现被他人issue误触的情况,也不能让更新该项目的commit信息与原后端项目的相同(可能有办法在action中可以获取到新issue的信息,但我不知道)。

去翻github action的文档,自然也没有能根据他人项目自动触发自己项目的触发方式,但发现可以用workflow_dispatch方式(webhook接口)来触发,并且可以传入信息,可参见示例。同时,ifttt也提供了发送网络请求的动作。

这么看来,只要在ifttt里设置成每当commit的rss出现新内容(即有新commit)时,向我项目的webhook发送post请求让github action运行即可。

但是! 问题又出现了,webhook的请求需要认证(github access_token),请求头里也需要有user-agent,并且开始禁止将token直接附加到请求的params里(不安全),文档。推荐的方法是添加到请求头中Authorization项里,其值为token my_access_token,注意中间有空格,后面的my_access_token为有权限的github access token。

可是ifttt不支持自定义请求头

看起来又走不通的,突然想起来cloudflare worker中的反代项目 。同理我可以用cf worker建立一个特殊的反代,它可以修改请求头,为请求头加上Authorization。由于当时我不会js,到处查,到处抄示例,各种试,终于写了一个满足要求的cf worker,js代码 。它只允许请求api.github.com,会根据请求体(body)中的token参数添加请求头Authorization,并删除请求体中的token参数(因为github接口不允许有多余的参数),还会把ifttt一并发送来的commit message中多余的换行/空格去除。

再写好github action的workflow文件 ,配置好ifttt ,在vercel中导入GitHub项目。

关于ifttt的一些抱怨 1,ifttt更新频率不确定,理论上是15分钟到半小时延迟。由于这个我一直想找ifttt的替代者,也试了integromat 还有 microsoft flow。前者能准确定时运行,但免费计划限制运行次数,算了一下也就能每小时运行一次,实际还不如ifttt;后者的rss更新时间也不确定,当然也可以用定时任务触发,不过最重要的“发送网络请求”动作还是需要高级版付费计划… 不过现在ifttt有pro付费计划了 2,最坑爹的地方,给github webhook发送请求需要带有token和user-agent,文档中要求是加在请求的header里,然而ifttt不支持自定义请求头……这里就得表扬integromat和Microsoft flow都可以对请求做自定义…
关于该项目中workflow的一些细节 1,subconverter编译后,删掉多余文件时需要用chattr命令改变文件属性。 2,subconverter编译后,应对可执行文件用chmod +x添加权限,否则部署会报错。 3,subconverter编译后修改配置文件并没有采用原项目用预先写好的配置文件进行覆盖的方法,而是用sed -i替换修改特定行,这是为了应对版本更新增删配置项,保证配置文件一定与版本对应。

前端自动编译更新

这一部分直接fork前端的项目即可,我使用的是acl4ssr修改的前端,然后合并上游的最新代码。为了加入自己的后端,修改.env相关参数和src/views/Subconverter.vue中的配置。

值得注意的是,我并没有将它直接导入到自动部署的项目(now-subconverter)中,而是在独立的前端项目中,每次更新时会向now-subconverter项目的webhook发送请求触发它拉取新的前端代码 ,具体实现参考这里,然后打包,推送到master分支上的/sub-web文件夹。

前后端部署在同一项目

主要是通过合适的vercel部署文件(now.json)达成的,在配置文件中正确定义路由,路由书写规则和clash一样,上面的优先级更高。因此安排的路由是先前端,除了请求前端的,其余全部给subconverter。 详见官方文档

另一条道路

为了实现这个项目,我在subconverter的telegram群向开发者tindyx请教了不少问题,于是他给subconverter增加了简单的网页服务器功能,见commit。可以在程序目录下的文件夹内放好已打包的前端网页,在配置文件里serve_file_root: ""写上相对目录。

不过,前端项目要修改打包输出路径,我不会,就不折腾了,实际效果也没有区别,主要是now.json可以写的简单点