惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

SecWiki News
SecWiki News
I
InfoQ
The Cloudflare Blog
人人都是产品经理
人人都是产品经理
博客园 - Franky
T
Tailwind CSS Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
量子位
博客园_首页
罗磊的独立博客
V
V2EX
李成银的技术随笔
大猫的无限游戏
大猫的无限游戏
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
True Tiger Recordings
Vercel News
Vercel News
Cyberwarzone
Cyberwarzone
Cisco Talos Blog
Cisco Talos Blog
F
Fox-IT International blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
M
Microsoft Research Blog - Microsoft Research
Know Your Adversary
Know Your Adversary
爱范儿
爱范儿
The Register - Security
The Register - Security
G
Google Developers Blog
The Hacker News
The Hacker News
Malwarebytes
Malwarebytes
S
Securelist
博客园 - 三生石上(FineUI控件)
Jina AI
Jina AI
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
S
SegmentFault 最新的问题
博客园 - 叶小钗
F
Fortinet All Blogs
Apple Machine Learning Research
Apple Machine Learning Research
宝玉的分享
宝玉的分享
博客园 - 聂微东
T
Threatpost
博客园 - 【当耐特】
D
Docker
P
Privacy & Cybersecurity Law Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
G
GRAHAM CLULEY
V
Visual Studio Blog
C
Cisco Blogs
IT之家
IT之家
S
Security Archives - TechRepublic
Latest news
Latest news
阮一峰的网络日志
阮一峰的网络日志

pseudoyu

周报 #109 - Be a whole person 周报 #108 - AI 与创作的困境 周报 #107 - 基于 Multica 与 Impeccable 的开发/设计工作流 周报 #106 - OpenClaw 实践、搬家与生活的能量 周报 #105 - 打破无聊的社会 2025 年末回顾 - Anything different is good 周报 #104 - 被遗忘的生活一隅 周报 #103 - 工作随想与被吞噬的生活 周报 #102 - 我是如何使用 AI 的 周报 #101 - 消失了三个月,我的生活发生了什么变化 周报 #100 - 过去这十年 周报 #99 - 离开 RSS3,迷茫与重启人生 周报 #98 - 生活之书与 Agentic Coding 周报 #97 - 日本旅行小记 28 岁的自白:去找寻自己 周报 #96 - 基于 Roo Code/Cursor 的 iOS 开发工作流 周报 #95 - All AI 与 No AI 周报 #94 - 生活的界限与真实感 周报 #93 - 婚礼纪录片与失落的电影院 周报 #92 - 数码产品 Porn 与断舍离 周报 #91 - 一席、消失的时代与自由意志 周报 #90 - OVH 服务器、Coolify 与对 AI Coding 的思考 周报 #89 - 博客改版与 TheWan App 发布 周报 #88 - 方大同、《回留》与人生清单 周报 #87 - 我们主持了自己的宝可梦婚礼,还为它办了一个展 周报 #86 - 用影像打败时间 周报 #85 - 京华烟云 Moment in Peking 周报 #84 - 想起他们 Echos of Reverie 周报 #83 - 年初收纳(房间、设备、服务、软件) 周报 #82 - Brand New Year 与写日记 2024 年末回顾 - 不完美的日子 周报 #81 - Engaged -> Married 与时间的尺度 周报 #80 - 关于求婚、爱情与婚姻 求婚誓言 | 爱的本质是被看见 周报 #79 - 清迈旅居、曼谷之行与 Follow Follow —— 信息获取的另一种形态 周报 #78 - NAS、Chromebook 与 Zeabur 折腾小记 周报 #77 - 一间只属于自己的房间(对亲密关系的思考) 周报 #76 - 关于 Adulting 的思考 周报 #75 - 回答 Dayu 关于独立博客的 9 个问题 周报 #74 - 清迈异闻录 周报 #73 - 《社交网络》、Ego 与中秋的现充生活 周报 #72 - 滑板体验、Rust Conf 与 Follow 公测(含邀请码) 周报 #71 - Indie App 体验计划 周报 #70 - 消失的附近,Burnout 与 Boreout 周报 #69 - AI Coding 体验与学习的源动力 周报 #68 - 关于写博客这件事与我生活的色彩 使用 GoatCounter 与 Zeabur 搭建网站数据统计系统 周报 #67 - 使用 follow 重塑我的信息输入系统 周报 #66 - 10x 工程师、技术热情与个人工具箱 从零开始搭建你的免费博客评论系统(Remark42 + fly.io) 周报 #65 - Adventure X 体验、Apple Notes 笔记实践与 EpubKit 周报 #64 - 生活在此处(《斯通纳》与《Normal People》) 使用 WebP Cloud 与 Cloudflare WAF 为你的图床添加隐私和版权保护 当云服务器崩溃时,我是如何救援重要数据的 周报 #63 - 不愉快的订花经历、商家和消费者与日渐 AI 化的人 从零开始搭建你的免费图床系统(Cloudflare R2 + WebP Cloud) 2024 年了,我的博客有了什么变化 周报 #62 - 香港之行、5am club 计划与 Rust 学习 周报 #61 - 好朋友的婚礼与对婚姻的思考 27 岁的自白:成长是一件很扫兴的事 周报 #60 - 虫子旁、教育理念与 EpubKit 周报 #59 - 沙漠之行、家庭与家人 周报 #58 - 远程工作这一年 周报 #57 - 生活在别处(巴厘岛之行) 周报 #56 - 面基 Randy 与考科目二 周报 #55 - 油画体验、博客系统升级与对 self-hosting 的思考 周报 #54 - 漂流计划、钱包被盗与 Home Server 周报 #53 - 空白的三个月、生活漂流与春节 周报 #52 - 自谦型人格与感情的另一个视角 周报 #51 - 追星小鹿 Lawrence 与生病 周报 #50 - 天坛漫步、重拾阅读和费曼学习法 周报 #49 - 烧焦的键盘、庞贝神话展、健康调整与神奇的梦 周报 #48 - 内蒙之行、清迈游民、重启的周报与生活 周报 #47 - 采访、拳击与工作状态 周报 #46 - 告别长发、周报初心与合约开发 个人信息获取与知识管理系统(Heptabase + Logseq + Readwise) 周报 #45 - 读书笔记、知识管理与双城生活 周报 #44 - 静寂工人、xLog 与日常 周报 #43 - In the Mood for Love 周报 #42 - 感情观、生活状态与自我 周报 #41 - 生日的仪式感、时间管理与北京之行 26 岁的自白:推石头的人 周报 #40 - 开源之夏、代码之外与流逝的睡眠 周报 #39 - 初患新冠、过去的心绪与失而复得的分享欲 周报 #38 - Foundry、Logseq 与 Surge Ponte 周报 #37 - 浮生半月闲( 武汉 | 香港 | 五月天) 周报 #36 - 肠胃炎、捏捏近况与新的旅途 周报 #35 - 登报、搬家和生病的捏捏 周报 #34 - Don't Stop the Clocks 周报 #33 - 北京 x 故事 x 离别 周报 #32 - 武汉、久别重逢与流动的心绪 周报 #31 - 开源、前端开发与 ChatGPT 实践 周报 #30 - 开源预算、写作初心与对技术的谦卑 Cosmos 区块链架构与 Tendermint 共识机制 周报 #29 - 日语学习经验、Steam Deck 与居酒屋 周报 #28 - Mastodon、故乡与捉迷藏的猫 周报 #27 - 何以为家 周报 #26 - 博客、客制化键盘和新服务器 周报 #25 - 基于 Crossbell 的个人信息输出与同步系统(重构)
RSSHub 开发实践 #01:Telegram 频道 RSS 订阅实现与部署方案
pseudoyu@connect.hku.hk (pseudoyu) · 2024-11-18 · via pseudoyu

前言

最近在参与 Follow 以及 RSSHub 这两个开源项目的一些开发维护工作,因为牵扯到与很多订阅源的“斗智斗勇”,有一些很有意思的开发实践,于是开了这个新坑系列记录下来。

本篇是这几周使用 Telegram 官方 API 与 MTProxy 来实现对 TG 频道更新的开发实践与完整配置部署教程。

follow_telegram_channel

Follow 中提供了一种便捷的订阅信息源的方式,例如用户可以输入对应的 Telegram 频道名称(如 pseudoyulife)来订阅某个频道的更新,这样就无须跳转到各个频道里去逐个查看,这一部分特性依赖的是背后 RSSHub 的实现。

rsshub_homepage

RSS (Really Simple Syndication) 是一个古早的信息聚合标准,它通过统一的数据格式,让用户能够便捷地订阅和获取网站更新。然而,随着社交媒体和移动互联网的兴起,原生支持 RSS 的网站正在减少。

而 RSSHub 秉持着"万物皆可 RSS"的理念,通过开源社区的力量将包括 Telegram、YouTube、播客在内的众多现代内容平台转换为标准的 RSS 格式,让用户能够重新掌控自己的信息获取方式,远离算法推荐的干扰。

RSSHub 中现在包含了上千个平台,针对不同平台和类别也都有着包括但不限于网页爬虫、官方接口、逆向 API 调用等多种处理方式,能够涵盖绝大多数我们日常使用到的信息源,也非常适合作为对平台的一些加密算法和反爬机制学习的实践,例如下文所要介绍的 Telegram 频道 RSS 订阅的实现。

Telegram 网页预览

yu_channel_online_preview

Telegram 提供了频道的网页预览功能,例如可以通过 t.me/s/pseudoyulife 这一链接直接查看我频道的更新,因此 RSSHub 很早之前就实现了通过抓取网页上的内容并转换为 RSS 格式的方式集成了对 Telegram 频道更新的订阅。

telegram_channel_reorx_preview

然而后来许多用户反馈说部分频道抓不到,去测试了一下,发现 Telegram 用一种黑盒的机制来限制了部分频道的网页预览功能,例如我一直在订阅的「Reorx’s Forge」以及「Newlearnerの自留地」等频道,当使用 /s 来访问页面时会被强制重定向,提示需要打开客户端来查看内容,因此对于这类频道我们没办法直接抓取到内容并转化为 RSS。

Telegram APIs

为了解决这一问题, 我又去查了 Telegram 的官方文档,发现他们将 API 分为以下几种:

其中 Telegram API 中的有一个 channels.getMessages 方法可以返回某个频道的消息,可以满足我们的需求,具体的实现逻辑在 RSSHub 代码仓库 —— lib/routes/telegram/channel.tslib/routes/telegram/tglib 这两部分,有兴趣的朋友可以看一下代码。

创建 Telegram App

manage_telegram_application

使用 Telegram API 需要访问 telegram core,通过手机号登录。

api_development_config

点击 API development tools 模块,创建一个 Telegram Application(详见「Creating your Telegram Application」)。

telegram_api_id_hash

在 App configuration 模块,我们能够获取到 api_idapi_hash 两个参数,记录下值,后续会用到。

获取 Telegram Session

使用 Telegram API 新建一个 client 的流程比较严格,需要通过 SMS 验证手机号登录,在代码中交互获取使用并不现实,因此我们需要预先创建 client 并且获取其 session,后续直接通过 session 来使用 api。

get_telegram_session

拉取脚本「pseudoyu/telegram-api-scripts」后,先运行 npm ipnpm i 安装依赖,然后运行 npm run startnode index.js,按照提示输入 api_idapi_hash 和手机号(需要和申请 Telegram App 时的手机号一致),通过短信或 Telegram App 获取验证码后即可在命令行输出获取 session。

需要注意的是,由于我们后续需要在 RSSHub 服务中使用这个 session,尽量在 RSSHub 服务部署的同一服务器上运行脚本获取 session,这样能避免 Telegram 对于 IP、设备的一些限制。

注:如果 RSSHub 是使用的 Serverless 平台或其他方式,则也可以通过额外配置 MTProxy 的方式来保持 IP 一致,后文会详细说明。

(可选) 使用 MTProxy 保持 IP 一致

之前在 Follow 的 RSSHub 实例上添加了 Telegram API 相关逻辑和配置后,过一会儿就会报一个 AuthKeyDuplicatedError 错误,查看了一下很多开发者也遇到过 —— 「AuthKeyDuplicatedError Eror problem #1488」,猜测是由于我们的 RSSHub 实例是 k8s 集群部署的,会从不同的机器调用 Telegram API,因而受到了一些限制。

于是又开始找针对这一情况的解决方案,发现 Telegram 提供了一种叫 MTProxy 的专属代理协议,可以通过部署一个 MTProxy Server 来代理所有的 API 请求,这样能够确保不同机器发送的请求都来自同一个 IP。

找到了「Dofamin/MTProxy-Docker」这个项目,拉取仓库后,新建一个 .env 文件,添加 MTPROTO_REPO_URL 这一环境变量(默认的官方代码已经不怎么维护,这个版本添加了一些补丁):

MTPROTO_REPO_URL=https://github.com/GetPageSpeed/MTProxy

SECRET 默认值为 ec4dd80983dbf12d6b354cf7bcfe9a48,也可以选择自定义的值;IP 不填写则会自动通过 curl ifconfig.co 获取本机 IP;其他环境变量可以查看仓库的 README.md 文件自行修改。

配置完成后,运行 docker compose up -d 启动,代理服务则运行在 <IP>:8443 上。

注:如果 RSSHub 是通过 Docker、Docker Compose 等方式单实例进行部署,且能够保障在同一台部署机器上运行脚本获取 Session,则可以跳过这个代理步骤。

经过了上述的服务部署,我们获取了以下信息:

  • Telegram API 的 api_idapi_hash
  • Telegram 的 session 字符串
  • MTProxy 的 SECRETIPPORT

这时可以开始部署/更新我们的 RSSHub 实例了,具体可以根据文档选择不同的方式,例如 Docker、Docker Compose、Serverless 等。

推荐通过 Docker Compose 的方式来部署,比较便于维护,需要在 docker-compose.yml 的 RSSHub 服务中添加如下变量:

environment:
  - TELEGRAM_API_ID=<Telegram API ID>
  - TELEGRAM_API_HASH=<Telegram API Hash>
  - TELEGRAM_SESSION=<Telegram Session>
  - TELEGRAM_PROXY_HOST=<MTProxy IP,如 123.123.123.123>
  - TELEGRAM_PROXY_PORT=8443
  - TELEGRAM_PROXY_SECRET=<MTProxy SECRET>

我是通过自己维护的模板部署在 Zeabur 平台上的,可视化部署,比较易用,只需要在部署完成后在 RSSHub 服务的 Variables 模块中添加以下变量并重启服务即可生效:

TELEGRAM_API_ID=<Telegram API ID>
TELEGRAM_API_HASH=<Telegram API Hash>
TELEGRAM_SESSION=<Telegram Session>
TELEGRAM_PROXY_HOST=<MTProxy IP,如 123.123.123.123>
TELEGRAM_PROXY_PORT=8443
TELEGRAM_PROXY_SECRET=<MTProxy SECRET>

测试

yu_rsshub_homepage

经过上述步骤后,我们拥有了自己添加了 Telegram 相关配置的 RSSHub 实例,访问主页显示如上页面即部署成功,可以通过 <RSSHub URL>/telegram/channel/<Channel Name> 来订阅 Telegram 频道。

例如可以通过我的公开实例 https://rsshub.pseudoyu.com/telegram/channel/NewlearnerChannel 来订阅「Newlearnerの自留地」频道。

总结

本篇记录了通过 Telegram API 在 RSSHub 中实现对部分受限制频道的更新订阅的开发实践与部署方案,受限于平台,方案可能会在未来某个时刻失效,我们也会持续研究更稳定的解决方案,使用中有任何问题可以留言或在 RSSHub 仓库中提 Issue 反馈/交流。