From b1ec84833f38bda0258dd3c2767880e3f829b034 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Fri, 25 May 2018 01:06:34 +0800 Subject: [PATCH] rss: add telegram channel --- README.md | 4 +- config.js | 3 ++ docs/README.md | 20 +++++++++- docs/install/README.md | 4 ++ router.js | 7 ++++ routes/telegram/channel.js | 80 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 routes/telegram/channel.js diff --git a/README.md b/README.md index b35d37469e..a08e6055a1 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,9 @@ RSSHub 是一个轻量、易于扩展的 RSS 生成器,可以给任何奇奇 * 熊猫直播 * 直播间开播下播 * V2EX - * 最热主题/最新主题 + * 最热/最新主题 +* Telegram + * 频道 ## 鸣谢 diff --git a/config.js b/config.js index 70c2e11351..3ced7741d7 100644 --- a/config.js +++ b/config.js @@ -30,4 +30,7 @@ module.exports = { youtube: { key: process.env.YOUTUBE_KEY, }, + telegram: { + token: process.env.TELEGRAM_TOKEN, + }, }; diff --git a/docs/README.md b/docs/README.md index d0d267268d..fa1b9fb325 100644 --- a/docs/README.md +++ b/docs/README.md @@ -883,10 +883,26 @@ key: 产品密钥 ## V2EX -### 最热主题/最新主题 +### 最热/最新主题 举例: [https://rsshub.app/v2ex/topics/latest](https://rsshub.app/v2ex/topics/latest) 路由: `/v2ex/topics/:type` -参数: type,hot 或 latest 二者之一 +参数: type: hot 或 latest + +## Telegram + +### 频道 + +::: tip 提示 + +订阅要求:将机器人 [@RSSHub_bot](https://t.me/RSSHub_bot) 加为频道管理员,然后发一条消息后才可正常获取数据 + +::: + +举例: [https://rsshub.app/telegram/channel/awesomeDIYgod](https://rsshub.app/telegram/channel/awesomeDIYgod) + +路由: `/telegram/channel/:username` + +参数: username,频道 username diff --git a/docs/install/README.md b/docs/install/README.md index aadac25fde..5e050569ff 100644 --- a/docs/install/README.md +++ b/docs/install/README.md @@ -364,3 +364,7 @@ gcloud app deploy * `youtube`: [申请地址](https://console.developers.google.com/) * `YOUTUBE_KEY`: YouTube API Key + +* `telegram`: [Telegram 机器人](https://telegram.org/blog/bot-revolution) + + * `TELEGRAM_TOKEN`: Telegram 机器人 token diff --git a/router.js b/router.js index 027e109c14..affd64d4f1 100644 --- a/router.js +++ b/router.js @@ -226,4 +226,11 @@ router.get('/panda/room/:id', require('./routes/panda/room')); // v2ex router.get('/v2ex/topics/:type', require('./routes/v2ex/topics')); +// Telegram +if (config.telegram && config.telegram.token) { + router.get('/telegram/channel/:username', require('./routes/telegram/channel')); +} else { + logger.warn('Telegram RSS is disabled for lacking config.'); +} + module.exports = router; diff --git a/routes/telegram/channel.js b/routes/telegram/channel.js new file mode 100644 index 0000000000..af5b61d0a3 --- /dev/null +++ b/routes/telegram/channel.js @@ -0,0 +1,80 @@ +const axios = require('../../utils/axios'); +const config = require('../../config'); +const logger = require('../../utils/logger'); + +let botName = ''; +axios({ + method: 'get', + url: `https://api.telegram.org/bot${config.telegram.token}/getMe`, +}) + .then(function(response) { + botName = response.data.result.username; + }) + .catch(function(error) { + logger.error('Error in getting Telegram bot name: ' + error); + }); + +module.exports = async (ctx) => { + const username = ctx.params.username; + + const response = await axios({ + method: 'get', + url: `https://api.telegram.org/bot${config.telegram.token}/getUpdates?allowed_updates=[%22channel_post%22]`, + }); + + const data = response.data.result.filter((item) => item.channel_post && item.channel_post.chat && item.channel_post.chat.username === username).reverse(); + + ctx.state.data = { + title: data[0] ? `${data[0].channel_post.chat.title} - Telegram 频道` : `未获取到信息: 请将 Telegram 机器人 @${botName} 设为频道管理员后发一条或以上有效消息完成配置`, + link: `https://t.me/${username}`, + item: data.map((item) => { + item = item.channel_post; + let text = item.text || item.caption || ''; + const media = ['photo', 'audio', 'document', 'game', 'sticker', 'video', 'voice', 'contact', 'location', 'venue']; + media.forEach((me) => { + if (item[me]) { + text += ` [${me}]`; + } + }); + + let html = text; + + if (item.entities) { + const enter = []; + item.entities.forEach((entity) => { + switch (entity.type) { + case 'text_link': + enter.push([entity.offset, ``], [entity.offset + entity.length, '']); + break; + case 'bold': + enter.push([entity.offset, ''], [entity.offset + entity.length, '']); + break; + case 'hashtag': + case 'italic': + enter.push([entity.offset, ''], [entity.offset + entity.length, '']); + break; + } + }); + enter.sort((a, b) => a[0] - b[0]); + if (enter.length) { + text.slice(0, enter[0][0]) + enter[0][1] + text.slice(enter[0][0], enter[1][0]) + enter[1][1] + text.slice(enter[1][0], enter[2][0]) + enter[2][1] + text.slice(enter[2][0]); + html = text.slice(0, enter[0][0]); + enter.forEach((en, index) => { + if (index !== enter.length - 1) { + html += enter[index][1] + text.slice(enter[index][0], enter[index + 1][0]); + } else { + html += enter[index][1] + text.slice(enter[index][0]); + } + }); + } + } + + return { + title: text.length > 24 ? text.slice(0, 24) + '...' : text, + description: html, + pubDate: new Date(item.date * 1000).toUTCString(), + link: `https://t.me/${username}/${item.message_id}`, + }; + }), + }; +};