Nazurin - 基于 Telegram, Heroku, MEGA 及 Firebase 的图片收藏自动工作流

Nazurin - 基于 Telegram, Heroku, MEGA 及 Firebase 的图片收藏自动工作流

English | Github

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/
Twitter 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

  1. 使用 ‘Deploy to Heroku’ 按钮:Deploy to Heroku

  2. 手动部署:
    根据根目录下和 sites 目录下各来源站点的 config.py 文件,在 Heroku 后台设置所需的环境变量,克隆 Git 仓库 并 push 到 Heroku 即可开始使用,关于 Heroku 的使用见 官方文档

Deploy on your own server

Tips: 安装之前可在 requirements.txt 中注释掉不用的依赖

  1. 安装所有依赖:pip install -r requirements.txt
  2. 设置所需的环境变量,或手动修改 config.py
  3. 启动: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 的所有功能仅限管理员使用

    提示:

    1. Telegram 的 User 和 Channel ID 可通过 @GetIDs Bot 获取
    2. 需要将机器人设置为 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:[email protected]: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 无法同步该文件,但网页端显示正常,解决方法为:

  1. 新建一个临时文件夹
  2. 设置该临时文件夹为 STORAGE_DIR
  3. 定期登录 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 设置为 Picturespics 为总归档文件夹,buffer 为临时缓冲区,主要是方便检查;操作时先将 Pictures 文件夹内所有内容复制到 buffer,用 Android 客户端查看无误后移动至 pics,可以确保万无一失。

pics 文件夹中大约有 3GB 文件是原先用 Pixiv 批量下载工具手动同步,其余均为自动工作流上传产生:

Issues & Roadmap

秉承开源精神,本项目现以 MIT 协议在 Github 开源,但仍有诸多不足之处:

  • 在桌面端的使用较为不便,未来可能考虑写个 Chrome 插件解决
  • 可灵活配置的选项较少
  • 图站 API 与 Bot 耦合过于紧密,正在构建一个插件系统来解耦(已完成)
  • 支持的存储方式和数据库类型较少(估计得引入插件系统才方便开发)(插件系统已完成)
  • 网络请求错误的处理还不够完善
  • 考虑集成智能以图搜图功能
  • 添加对 Pixiv 动图的支持(已完成)
  • 添加对 Pool 的支持

总而言之,PR is welcome

Credits

References

  1. Telegram Bot API
  2. Pricing | Heroku
  3. Dynos and the Dyno Manager - Heroku Dev Center
  4. Firebase Pricing
  5. Cloud Firestore | Firebase
  6. python-telegram-bot Wiki

Nazurin - 基于 Telegram, Heroku, MEGA 及 Firebase 的图片收藏自动工作流

https://blog.gpx.moe/2020/07/20/nazurin/

Author

Googleplex

Posted on

Jul 20, 2020

Updated on

Jan 24, 2021

Licensed under

Comments