Add: tg channel photo (#1714)

- 目前只处理了非私有频道的图片(不包括图片文件)显示
- Closes #903
This commit is contained in:
凉凉
2019-03-11 11:02:35 +08:00
committed by DIYgod
parent 412d54967f
commit 08ae33635a
+70 -43
View File
@@ -1,6 +1,7 @@
const axios = require('../../utils/axios');
const config = require('../../config');
const logger = require('../../utils/logger');
const cheerio = require('cheerio');
let botName = '';
axios({
@@ -18,6 +19,22 @@ module.exports = async (ctx) => {
const username = ctx.params.username;
const cacheDays = 30;
const cacheLength = 5;
const fomatPhoto = async (link) => {
const imgList = [];
const { data } = await axios.get(link + '?embed=1&single=1');
const $ = cheerio.load(data);
$('.tgme_widget_message_photo_wrap').each(function() {
const bg = $(this).css('background-image');
imgList.push(bg.match(/url\('(.+)'\)/)[1]);
});
return imgList.reduce((acc, img) => {
if (img) {
acc += `<img referrerpolicy="no-referrer" src="${img}">`;
}
return acc;
}, '');
};
let response = await axios({
method: 'get',
@@ -41,54 +58,64 @@ module.exports = async (ctx) => {
ctx.cache.set(`RSSHubTelegramChannelName${username}`, data[0].channel_post.chat.title, cacheDays * 24 * 60 * 60);
// cache post
post = 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, `<a href="${entity.url}">`], [entity.offset + entity.length, '</a>']);
break;
case 'bold':
enter.push([entity.offset, '<b>'], [entity.offset + entity.length, '</b>']);
break;
case 'hashtag':
case 'italic':
enter.push([entity.offset, '<i>'], [entity.offset + entity.length, '</i>']);
break;
post = await Promise.all(
data.map(async (item) => {
item = item.channel_post;
let text = item.text || item.caption || '';
let html = text;
const link = `https://t.me/${username}/${item.message_id}`;
const media = ['photo', 'audio', 'document', 'game', 'sticker', 'video', 'voice', 'contact', 'location', 'venue'];
// https://css-tricks.com/why-using-reduce-to-sequentially-resolve-promises-works/
await media.reduce(async (acc, me) => {
if (item[me]) {
if (item.chat.username && me === 'photo') {
// 暂时只处理非私有频道的图片
const photos = await fomatPhoto(link);
html += ` ${photos}`;
}
text += ` [${me}]`;
}
});
enter.sort((a, b) => a[0] - b[0]);
if (enter.length) {
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 acc;
}, Promise.resolve());
if (item.entities) {
const enter = [];
item.entities.forEach((entity) => {
switch (entity.type) {
case 'text_link':
enter.push([entity.offset, `<a href="${entity.url}">`], [entity.offset + entity.length, '</a>']);
break;
case 'bold':
enter.push([entity.offset, '<b>'], [entity.offset + entity.length, '</b>']);
break;
case 'hashtag':
case 'italic':
enter.push([entity.offset, '<i>'], [entity.offset + entity.length, '</i>']);
break;
}
});
enter.sort((a, b) => a[0] - b[0]);
if (enter.length) {
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,
description: html,
pubDate: new Date(item.date * 1000).toUTCString(),
link: `https://t.me/${username}/${item.message_id}`,
};
});
return Promise.resolve({
title: text,
description: html,
pubDate: new Date(item.date * 1000).toUTCString(),
link,
});
})
);
if (post.length >= cacheLength) {
ctx.cache.set(`RSSHubTelegramChannelPost${username}`, post.slice(0, cacheLength), cacheDays * 24 * 60 * 60);
} else {