Skip to content

Commit

Permalink
Merge pull request #1313 from DIYgod/master
Browse files Browse the repository at this point in the history
[pull] master from diygod:master
  • Loading branch information
pull[bot] authored Jan 2, 2024
2 parents aece4e3 + 3bf9dd2 commit 398269f
Show file tree
Hide file tree
Showing 19 changed files with 346 additions and 49 deletions.
44 changes: 44 additions & 0 deletions lib/v2/backlinko/blog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const { parseDate } = require('@/utils/parse-date');

module.exports = async (ctx) => {
const baseUrl = 'https://backlinko.com';
const { data: response, url: link } = await got(`${baseUrl}/blog`);

const $ = cheerio.load(response);
const nextData = JSON.parse($('#__NEXT_DATA__').text());
const {
buildId,
props: { pageProps },
} = nextData;

const posts = pageProps.posts.nodes.concat(pageProps.backlinkoLockedPosts.nodes).map((post) => ({
title: post.title,
link: `${baseUrl}/${post.slug}`,
pubDate: parseDate(post.modified),
author: post.author.node.name,
apiUrl: `${baseUrl}/_next/data/${buildId}/${post.slug}.json`,
}));

const items = await Promise.all(
posts.map((item) =>
ctx.cache.tryGet(item.link, async () => {
const { data } = await got(item.apiUrl);
const post = data.pageProps.post || data.pageProps.lockedPost;

item.description = post.content;

return item;
})
)
);

ctx.state.data = {
title: pageProps.page.seo.title,
description: pageProps.page.seo.metaDesc,
link,
language: 'en',
item: items,
};
};
3 changes: 3 additions & 0 deletions lib/v2/backlinko/maintainer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
'/blog': ['TonyRL'],
};
13 changes: 13 additions & 0 deletions lib/v2/backlinko/radar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module.exports = {
'backlinko.com': {
_name: 'Backlinko',
'.': [
{
title: 'Blog',
docs: 'https://docs.rsshub.app/routes/blog#backlinko',
source: ['/blog', '/'],
target: '/backlinko/blog',
},
],
},
};
3 changes: 3 additions & 0 deletions lib/v2/backlinko/router.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = (router) => {
router.get('/blog', require('./blog'));
};
103 changes: 55 additions & 48 deletions lib/v2/jiemian/lists.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,62 +15,69 @@ module.exports = async (ctx) => {

const $ = cheerio.load(response);

let items = $('a.logStore, a[aid], div.title a, div.news-header a')
let items = $('a')
.toArray()
.map((item) => {
.reduce((acc, item) => {
item = $(item);

return {
title: item.text(),
link: item.prop('href'),
};
})
.filter((item) => item.link && !item.link.startsWith(new URL('special', rootUrl).href));
const href = item.prop('href');
const link = href ? (href.startsWith('/') ? new URL(href, rootUrl).href : href) : undefined;

if (link && /\/(article|video)\/\w+\.html/.test(link)) {
acc[link] = {
title: item.text(),
link,
};
}
return acc;
}, {});

items = await Promise.all(
items.slice(0, limit).map((item) =>
ctx.cache.tryGet(item.link, async () => {
const { data: detailResponse } = await got(item.link);
Object.values(items)
.slice(0, limit)
.map((item) =>
ctx.cache.tryGet(item.link, async () => {
const { data: detailResponse } = await got(item.link);

const content = cheerio.load(detailResponse);
const image = content('div.article-img img').first();
const video = content('#video-player').first();
const content = cheerio.load(detailResponse);
const image = content('div.article-img img').first();
const video = content('#video-player').first();

item.title = content('div.article-header h1').text();
item.description = art(path.join(__dirname, 'templates/description.art'), {
image: image
? {
src: image.prop('src'),
alt: image.next('p').text() || item.title,
}
: undefined,
video: video
? {
src: video.prop('data-url'),
poster: video.prop('data-poster'),
width: video.prop('width'),
height: video.prop('height'),
}
: undefined,
intro: content('div.article-header p').text(),
description: content('div.article-content').html(),
});
item.author = content('span.author')
.first()
.find('a')
.toArray()
.map((a) => content(a).text())
.join('/');
item.category = content('meta.meta-container a')
.toArray()
.map((c) => content(c).text());
item.pubDate = parseDate(content('div.article-info span[data-article-publish-time]').prop('data-article-publish-time'), 'X');
item.upvotes = content('span.opt-praise__count').text() ? parseInt(content('span.opt-praise__count').text(), 10) : 0;
item.comments = content('span.opt-comment__count').text() ? parseInt(content('span.opt-comment__count').text(), 10) : 0;
item.title = content('div.article-header h1').text();
item.description = art(path.join(__dirname, 'templates/description.art'), {
image: image
? {
src: image.prop('src'),
alt: image.next('p').text() || item.title,
}
: undefined,
video: video
? {
src: video.prop('data-url'),
poster: video.prop('data-poster'),
width: video.prop('width'),
height: video.prop('height'),
}
: undefined,
intro: content('div.article-header p').text(),
description: content('div.article-content').html(),
});
item.author = content('span.author')
.first()
.find('a')
.toArray()
.map((a) => content(a).text())
.join('/');
item.category = content('meta.meta-container a')
.toArray()
.map((c) => content(c).text());
item.pubDate = parseDate(content('div.article-info span[data-article-publish-time]').prop('data-article-publish-time'), 'X');
item.upvotes = content('span.opt-praise__count').text() ? parseInt(content('span.opt-praise__count').text(), 10) : 0;
item.comments = content('span.opt-comment__count').text() ? parseInt(content('span.opt-comment__count').text(), 10) : 0;

return item;
})
)
return item;
})
)
);

const title = $('title').text();
Expand Down
29 changes: 29 additions & 0 deletions lib/v2/otobanana/cast.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const got = require('@/utils/got');
const { apiBase, baseUrl, getUserInfo, renderCast } = require('./utils');

module.exports = async (ctx) => {
const { id } = ctx.params;

const userInfo = await getUserInfo(id, ctx.cache.tryGet);
const { data: castData } = await got(`${apiBase}/users/${id}/casts/`);

const casts = castData.results.map((item) => renderCast(item));

ctx.state.data = {
title: `${userInfo.name} (@${userInfo.username}) - 音声投稿 | OTOBANANA`,
description: userInfo.bio.replace(/\n/g, ' '),
link: `${baseUrl}/user/${id}`,
image: userInfo.avatar_url,
icon: userInfo.avatar_url,
logo: userInfo.avatar_url,
language: 'ja',
author: userInfo.name,
itunes_author: userInfo.name,
item: casts,
};

ctx.state.json = {
userInfo,
castData,
};
};
29 changes: 29 additions & 0 deletions lib/v2/otobanana/livestream.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const got = require('@/utils/got');
const { apiBase, baseUrl, getUserInfo, renderLive } = require('./utils');

module.exports = async (ctx) => {
const { id } = ctx.params;

const userInfo = await getUserInfo(id, ctx.cache.tryGet);
const { data: liveData } = await got(`${apiBase}/users/${id}/livestreams/`);

const casts = liveData.results.map((item) => renderLive(item));

ctx.state.data = {
title: `${userInfo.name} (@${userInfo.username}) - ライブ配信 | OTOBANANA`,
description: userInfo.bio.replace(/\n/g, ' '),
link: `${baseUrl}/user/${id}`,
image: userInfo.avatar_url,
icon: userInfo.avatar_url,
logo: userInfo.avatar_url,
language: 'ja',
author: userInfo.name,
itunes_author: userInfo.name,
item: casts,
};

ctx.state.json = {
userInfo,
liveData,
};
};
5 changes: 5 additions & 0 deletions lib/v2/otobanana/maintainer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
'/user/:id': ['TonyRL'],
'/user/:id/cast': ['TonyRL'],
'/user/:id/livestream': ['TonyRL'],
};
25 changes: 25 additions & 0 deletions lib/v2/otobanana/radar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module.exports = {
'otobanana.com': {
_name: 'OTOBANANA',
'.': [
{
title: 'Timeline タイムライン',
docs: 'https://docs.rsshub.app/multimedia#otobanana',
source: ['/user/:id'],
target: '/otobanana/user/:id',
},
{
title: 'Cast 音声投稿',
docs: 'https://docs.rsshub.app/multimedia#otobanana',
source: ['/user/:id/cast', '/user/:id'],
target: '/otobanana/user/:id/cast',
},
{
title: 'Livestream ライブ配信',
docs: 'https://docs.rsshub.app/multimedia#otobanana',
source: ['/user/:id/livestream', '/user/:id'],
target: '/otobanana/user/:id/livestream',
},
],
},
};
5 changes: 5 additions & 0 deletions lib/v2/otobanana/router.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = (router) => {
router.get('/user/:id', require('./timeline'));
router.get('/user/:id/cast', require('./cast'));
router.get('/user/:id/livestream', require('./livestream'));
};
11 changes: 11 additions & 0 deletions lib/v2/otobanana/templates/description.art
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{{ if cast }}
<img src="{{ cast.thumbnail_url }}">
<br>
<audio controls>
<source src="{{ cast.audio_url }}" type="audio/x-m4a">
</audio>
<br>
💬 {{ cast.comment_count }} ❤️ {{ cast.like_count }} 🍌 {{ cast.gift_banana }} {{ cast.play_count }} 再生
<br>
{{@ cast.text.replace(/\n/g, '<br>') }}
{{ /if }}
29 changes: 29 additions & 0 deletions lib/v2/otobanana/timeline.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const got = require('@/utils/got');
const { apiBase, baseUrl, getUserInfo, renderPost } = require('./utils');

module.exports = async (ctx) => {
const { id } = ctx.params;

const userInfo = await getUserInfo(id, ctx.cache.tryGet);
const { data: postData } = await got(`${apiBase}/users/${id}/posts/`);

const posts = postData.results.map((item) => renderPost(item));

ctx.state.data = {
title: `${userInfo.name} (@${userInfo.username}) - タイムライン | OTOBANANA`,
description: userInfo.bio.replace(/\n/g, ' '),
link: `${baseUrl}/user/${id}`,
image: userInfo.avatar_url,
icon: userInfo.avatar_url,
logo: userInfo.avatar_url,
language: 'ja',
author: userInfo.name,
itunes_author: userInfo.name,
item: posts,
};

ctx.state.json = {
userInfo,
postData,
};
};
67 changes: 67 additions & 0 deletions lib/v2/otobanana/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
const got = require('@/utils/got');
const { parseDate } = require('@/utils/parse-date');
const { art } = require('@/utils/render');
const { join } = require('path');

const domain = 'otobanana.com';
const apiBase = `https://api.${domain}`;
const baseUrl = `https://${domain}`;

const getUserInfo = (id, tryGet) =>
tryGet(`otobanana:user:${id}`, async () => {
const { data } = await got(`${apiBase}/users/${id}/`);
return data;
});

const renderCast = (cast) => ({
title: cast.title,
description: art(join(__dirname, 'templates/description.art'), { cast }),
pubDate: parseDate(cast.created_at),
link: `https://otobanana.com/cast/${cast.id}`,
author: `${cast.user.name} (@${cast.user.username})`,
itunes_item_image: cast.thumbnail_url,
itunes_duration: cast.duration_time,
enclosure_url: cast.audio_url,
enclosure_type: 'audio/x-m4a',
upvotes: cast.like_count,
comments: cast.comment_count,
});

const renderLive = (live) => ({
title: live.title,
description: live.is_open ? '配信中のライブ' : '終了しました',
pubDate: parseDate(live.created_at),
link: live.room_url,
guid: `${live.room_url}#${live.id}`,
author: `${live.user.name} (@${live.user.username})`,
upvotes: live.like_count,
comments: live.comment_count,
});

const renderPost = ({ id, type_label: type, cast, /** livestream */ message /** , event */ }) => {
switch (type) {
case 'cast':
return renderCast(cast);
case 'message':
return {
title: message.text.split('\n')[0],
description: message.text.replace(/\n/g, '<br>'),
pubDate: parseDate(message.created_at),
link: `https://otobanana.com/${type}/${id}`,
author: `${message.user.name} (@${message.user.username})`,
upvotes: message.like_count,
comments: message.comment_count,
};
default:
throw Error(`Unknown post type: ${type}`);
}
};

module.exports = {
apiBase,
baseUrl,
getUserInfo,
renderCast,
renderLive,
renderPost,
};
Loading

0 comments on commit 398269f

Please sign in to comment.