Nazurin - 基于 Telegram, Heroku, MEGA 及 Firebase 的图片收藏自动工作流
Background
对于大多数 ACG 爱好者来说,在网络上收集各种画师作品、壁纸、宣传图、插画等图片想必是一件乐此不疲的事情;然而近年来图片来源不断丰富,已从最原始的 Pixiv、Danbooru、Moebooru 类图站扩展至 Twitter、Telegram Channel、QQ 群,乃至酷安酷图(?)、网易云音乐动态(??),高效的多渠道自动收图工作流已成为必需。
此外,如何在多渠道来源中获取高质量的原始数据,如何管理和安全保存数据也至关重要。例如下图,Pixiv 上删除作品的情况已不再是少数,虽说仍可通过其他手段恢复,但恢复数据的成本显然高于即时归档的成本。数据丢失对于收集控来说是无法忍受的痛苦,所以去中心化刻不容缓(
Introduction
小さな小さな賢将,是一个能从多种来源收集 ACG 相关插画并完成自动化工作流的 Telegram 机器人。
(名字并不是 TYPO,只是为了避免重名)
其实这个项目 1 月份就在做了但咕到现在才写文章
Features
- 获取多种来源的图片
- 从支持的网站下载原图
- 将图片添加到收藏,完成自动化工作流
- 将图片保存在 Telegram Channel 中
- 将图片文件上传到 MEGA 云盘、Google Drive 或保存在本地
- 将图片的元信息(如名称、标签)保存至多种类型的数据库
Supported Sites
名称 | URL | Bot 命令 | 图片收藏功能 |
---|---|---|---|
Pixiv | https://www.pixiv.net/ | ✔ | ✔ |
Danbooru | https://danbooru.donmai.us/ | ✔ | ✔ |
Safebooru | https://safebooru.donmai.us/ | ✔ | |
yandere | https://yande.re/ | ✔ | ✔ |
Konachan | https://konachan.com/ | ✔ | ✔ |
Lolibooru | https://lolibooru.moe/ | ✔ | |
Zerochan | https://www.zerochan.net/ | ✔ | ✔ |
Gelbooru | https://gelbooru.com/ | ✔ | |
https://twitter.com/ | ✔ | ||
Bilibili 动态 | https://t.bilibili.com/ | ✔ |
Before
- Pixiv:收藏 & 定期使用工具批量下载收藏夹
- Danbooru & Moebooru 类图站:分别注册账号并收藏 / 直接添加书签
- Twitter:转推 / 直接下载 / 添加书签
- Telegram Channel:转发至私人频道
After
以上所有来源均分享 / 转发至 Telegram Bot,Bot 在云端完成以下工作:
- 将原消息转发至 Gallery Channel 以便后续查看
- 在来源站收藏图片(仅 Pixiv)
- 下载“原图”,即能够获取到的最高分辨率文件
- 将原图以文件形式发送至 Album Channel 作为备份点之一
- 上传原图文件至 MEGA 云盘
PS: 对于其他来源的图片如已知原始地址仍可按上述方法操作,搜图功能仍在计划中
Architecture
Telegram
项目初期设想用 Electron 构建 UI 界面,用 Python 运行后端服务器,藉此学习 Electron 和 Python 的使用,然而此架构在通讯和程序启动方面都存在一定不足;考虑到 Telegram 已成为收图的重要来源之一,且官方提供了丰富的 API 以供使用,故使用 Telegram Bot 功能、将聊天界面作为 UI 使用。
此外,Telegram 还提供了云端永久存储及多端同步功能,可作为原始文件的备份点之一。
Heroku
由于手上并没有现成的服务器,对于如此轻量的应用来说单独购买一台 VPS 又太过奢侈,于是几年前白嫖的 Heroku 平台便派上了用场。
Heroku 是基于容器的 PaaS 平台,在本地使用 Git 推送源码后,在云端完成构建,最终运行在一个轻量级的容器(Dyno)中。对于免费账户,Dyno 在闲置 30 分钟后会自动休眠,但受到网络请求后会自动启动,以节省资源。由于使用了 Webhook,这一特性对于本项目来说并无大碍;免费账户每个月 550 小时的运行时间也是绰绰有余。
MEGA
人人的隐私与家庭、住宅、通信不得被任意干涉……。 人人有权享受法律保护,不受这种干涉或攻击……。
图片收藏工作流中重要的一环便是文件的归档存储,云端备份需要一定的稳定性和存储空间,此外还有安全性等多方面因素。MEGA 作为一家主打安全性的公司,采用了端对端加密设计,提供 15GB 的免费存储空间,官方虽没有提供 Python SDK,但有开源库可用。
Firebase
由于 Dyno 的自动休眠机制及 PixivPy 的自身设计,Pixiv API 无法保持登录状态,一段时间后使用机器人时都会重新登录,然而 Pixiv 的异地登录邮件提醒并不能关闭,一个月内将会产生几十封垃圾邮件;此外,Pixiv 的 Access Token 有效期仅为 1 小时,若 Bot 运行时间过长则登录凭据失效无法正常工作。
Pixiv 使用的是 RESTful API,为解决这些问题需要保存 Access Token 及 Refresh Token,然而 Heroku Dyno 的 Ephemeral filesystem 直接否决了本地数据库的方案。鉴于 Heroku 自身的数据库服务存在诸多限制,转而使用 Firebase——Google 的 BaaS 服务。
Cloud Firestore 是 Firebase 平台中的云托管 NoSQL 数据库服务,以集合-文档的结构存储数据,免费方案数据总量限制为 1GB,每日读取及写入次数限制均在 1 万次以上,完全满足需求。
连接了 Firebase 以后便可将 Pixiv 的登录凭据缓存到 Firestore 数据库中,省去了登录时间,如 Access Token 过期则使用 Refresh Token 进行更新;针对 MEGA 网盘每次登录及查找文件夹耗时过长的问题,同样使用此方法进行解决。粗略估算,此次优化过后 Bot 的冷启动响应时间可降低至原来的一半左右。
Deploy
Deploy on Heroku
使用 ‘Deploy to Heroku’ 按钮:Deploy to Heroku
手动部署:
根据根目录下和sites
目录下各来源站点的config.py
文件,在 Heroku 后台设置所需的环境变量,克隆 Git 仓库 并 push 到 Heroku 即可开始使用,关于 Heroku 的使用见 官方文档。
Deploy on your own server
Tips: 安装之前可在
requirements.txt
中注释掉不用的依赖
- 安装所有依赖:
pip install -r requirements.txt
- 设置所需的环境变量,或手动修改
config.py
- 启动:
python bot.py
Configuration
ENV
默认为
production
,使用 Webhook;开发环境可设置为production
以使用轮询模式TOKEN
Telegram Bot 的 API token,可通过 @BotFather 获取
WEBHOOK_URL
提交给 Telegram 服务器的 Webhook URL,详见 python-telegram-bot 的文档
PORT
Webhook 端口,如果部署在 Heroku 上则无需手动设置
STORAGE
字符串,由
eval
转换为 list使用的存储方式,默认为
[]
,即仅使用DOWNLOAD_DIR
作为本地存储。设置为['Mega']
以使用 MEGA。可通过在
storage
下创建一个文件来实现其他存储方式,文件中的对象必须有一个名为store
的成员函数。DOWNLOAD_DIR
本地目录,用于存放下载的原图,如果不存在将自动创建
STORAGE_DIR
归档存储目录,如 MEGA 云盘的远程目录,原图将被存储到这里,如果不存在将自动创建
ALBUM_ID
用于存放原图文件的 Telegram Channel ID
GALLERY_ID
用于存放转发消息的 Telegram Channel ID,发送给 Bot 的消息中如果带有可被识别的图站链接,则视作图片收藏请求,消息将会被转发到这个 Channel
ADMIN_ID
管理员的 Telegram 用户 ID(不是用户名),Bot 的所有功能仅限管理员使用
提示:
- Telegram 的 User 和 Channel ID 可通过 @GetIDs Bot 获取
- 需要将机器人设置为 Channel 管理员
DATABASE
使用的数据库,支持的数据库类型如下:
驱动 | URL | 配置值 | 备注 |
---|---|---|---|
TinyDB | https://tinydb.readthedocs.io/en/stable/index.html | Local |
默认选项 |
Firestore | https://firebase.google.com/products/firestore | Firebase |
|
MongoDB | https://www.mongodb.com/ | Mongo |
支持 MongoDB Atlas |
Cloudant | https://www.ibm.com/cloud/cloudant | Cloudant |
也可依照 Firebase 的例子实现自己的数据库驱动,将文件放置在 database
目录下,将此选项设置为数据库驱动的类名即可。
GOOGLE_APPLICATION_CREDENTIALS
Firebase SDK 的登录凭据,详见 Firebase 文档
如果部署在 Heroku 上不希望上传
service-account-file.json
,可将文件路径以文件内容代替MONGO_URI
MongoDB connection string,必须指定数据库。
eg:
mongodb://username:password@localhost:27017/database
,默认为mongodb://localhost:27017/nazurin
。CLOUDANT_USER
&CLOUDANT_APIKEY
&CLOUDANT_DB
Cloudant 用户名、API key 和数据库名,使用 IAM 验证方式,默认数据库为
nazurin
。PIXIV_USER
&PIXIV_PASS
Pixiv 登录邮箱或用户名,以及密码(理论上如果在 Firebase 中已存有 Access Token 和 Refresh Token,删去此条配置也能正常工作)
MEGA_USER
&MEGA_PASS
MEGA 登录邮箱及密码(备注同上)
Usage
Commands
/pixiv <id>
- 浏览 Pixiv 画作/pixiv_download <id>
- 下载 Pixiv 画作/danbooru <id>
- 浏览 Danbooru Post/danbooru_download <id>
- 下载 Danbooru Post/yandere <id>
- 浏览 Yandere Post/yandere_download <id>
- 下载 Yandere Post/konachan <id>
- 浏览 Konachan Post/konachan_download <id>
- 下载 Konachan Post/zerochan <id>
- 浏览 Zerochan Post/zerochan_download <id>
- 下载 Zerochan Post/bookmark <id>
- 收藏 Pixiv 画作
Collection Update
向 Bot 发送或转发一条带有 支持的网站 链接的消息(一条消息暂时只能处理一条链接),此后这条消息将会被转发至 GALLERY
Channel,随后 Bot 将从图片来源站点下载最清晰的原图文件并发送至 ALBUM
Channel,最后文件会被上传至 MEGA 云盘作为备份。
Tips: 在手机上操作时可使用“分享”按钮,最后生成的分享信息带有链接即可。
MEGA Encoding Issues
猜测由于 Mega.py 的 API 方式和官方 SDK 略有不同,因此有时会出现编码问题,具体表现为文件名带有特殊字符时在 Android 和 iOS 客户端显示异常(如出现乱码或显示为 BLANK
),且 MEGASync 无法同步该文件,但网页端显示正常,解决方法为:
- 新建一个临时文件夹
- 设置该临时文件夹为
STORAGE_DIR
- 定期登录 MEGA 网页端,将临时文件夹中的文件复制到目标文件夹完成归档
(其实不定期登录也行,只在需要同步文件时操作一遍即可,注意不能使用“移动”操作)
当然也可在源码中修改文件名格式,如设置为 pid 则无此问题
Conclusion
优点:
完全白嫖完全使用免费 SaaS, PaaS 和 BaaS 服务,零成本- Telegram, Heroku, Firebase, MEGA 以及图片来源站点之间的网络连接稳定,不受用户本地网络影响
个人中度使用体验:
总之就是很爽、非常爽
执行命令的响应时间较短,图片收藏的平均冷启动响应时间(从发送链接到 Bot 执行完成返回)约为 20 秒,Bot 在线时平均响应时间为 10 秒;支持同时处理多个请求,但 Heroku 对线程数量有一定限制;大文件的处理与 Pixiv 下载与 MEGA 上传速度有关,如执行时间过长会被 Heroku 中断,20MB 以下的文件基本无问题;
各类云服务使用情况:
Heroku 每个月的 Dyno Usage 从未超过 100 小时,基本在 40 小时左右
Firebase 更是不用说了,Google 给的免费配额实在慷慨,后期考虑把图片收藏信息也同步过去
云盘的使用情况会因人而异,就算 MEGA 的 15GB 不够用也可以自己扩展其他存储方式,当然直接把 DOWLOAD_DIR
用作本地存储也没问题。
如下图所示,STORAGE_DIR
设置为 Pictures
,pics
为总归档文件夹,buffer
为临时缓冲区,主要是方便检查;操作时先将 Pictures
文件夹内所有内容复制到 buffer
,用 Android 客户端查看无误后移动至 pics
,可以确保万无一失。
pics
文件夹中大约有 3GB 文件是原先用 Pixiv 批量下载工具手动同步,其余均为自动工作流上传产生:
Issues & Roadmap
秉承开源精神,本项目现以 MIT 协议在 Github 开源,但仍有诸多不足之处:
- 在桌面端的使用较为不便,未来可能考虑写个 Chrome 插件解决
- 可灵活配置的选项较少
图站 API 与 Bot 耦合过于紧密,正在构建一个插件系统来解耦(已完成)支持的存储方式和数据库类型较少(估计得引入插件系统才方便开发)(插件系统已完成)- 网络请求错误的处理还不够完善
- 考虑集成
智能以图搜图功能 添加对 Pixiv 动图的支持(已完成)- 添加对 Pool 的支持
总而言之,PR is welcome
Credits
References
Nazurin - 基于 Telegram, Heroku, MEGA 及 Firebase 的图片收藏自动工作流