124 lines
4.7 KiB
TypeScript
124 lines
4.7 KiB
TypeScript
import MarkdownIt from 'markdown-it';
|
|
|
|
import { config } from '@/config';
|
|
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
|
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
|
import type { Route } from '@/types';
|
|
import cache from '@/utils/cache';
|
|
import got from '@/utils/got';
|
|
import { parseDate } from '@/utils/parse-date';
|
|
|
|
const md = MarkdownIt({ html: true });
|
|
|
|
export const route: Route = {
|
|
path: '/:community/:sort?',
|
|
categories: ['social-media'],
|
|
example: '/lemmy/technology@lemmy.world/Hot',
|
|
parameters: {
|
|
community: 'Lemmmy community, for example technology@lemmy.world',
|
|
sort: {
|
|
description: 'Sort by',
|
|
options: [
|
|
{ value: 'Active', label: 'Active' },
|
|
{ value: 'Hot', label: 'Hot' },
|
|
{ value: 'New', label: 'New' },
|
|
{ value: 'Old', label: 'Old' },
|
|
{ value: 'TopDay', label: 'TopDay' },
|
|
{ value: 'TopWeek', label: 'TopWeek' },
|
|
{ value: 'TopMonth', label: 'TopMonth' },
|
|
{ value: 'TopYear', label: 'TopYear' },
|
|
{ value: 'TopAll', label: 'TopAll' },
|
|
{ value: 'MostComments', label: 'MostComments' },
|
|
{ value: 'NewComments', label: 'NewComments' },
|
|
{ value: 'TopHour', label: 'TopHour' },
|
|
{ value: 'TopSixHour', label: 'TopSixHour' },
|
|
{ value: 'TopTwelveHour', label: 'TopTwelveHour' },
|
|
{ value: 'TopThreeMonths', label: 'TopThreeMonths' },
|
|
{ value: 'TopSixMonths', label: 'TopSixMonths' },
|
|
{ value: 'TopNineMonths', label: 'TopNineMonths' },
|
|
{ value: 'Controversial', label: 'Controversial' },
|
|
{ value: 'Scaled', label: 'Scaled' },
|
|
],
|
|
default: 'Active',
|
|
},
|
|
},
|
|
features: {
|
|
requireConfig: [
|
|
{
|
|
name: 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN',
|
|
description: '',
|
|
},
|
|
],
|
|
requirePuppeteer: false,
|
|
antiCrawler: false,
|
|
supportBT: false,
|
|
supportPodcast: false,
|
|
supportScihub: false,
|
|
},
|
|
name: 'Community',
|
|
maintainers: ['wb14123', 'pseudoyu'],
|
|
handler,
|
|
};
|
|
|
|
async function handler(ctx) {
|
|
const sort = ctx.req.param('sort') ?? 'Active';
|
|
const community = ctx.req.param('community');
|
|
const communitySlices = community.split('@');
|
|
if (communitySlices.length !== 2) {
|
|
throw new InvalidParameterError(`Invalid community: ${community}`);
|
|
}
|
|
const instance = community.split('@')[1];
|
|
const allowedDomain = ['lemmy.world', 'lemm.ee', 'lemmy.ml', 'sh.itjust.works', 'feddit.de', 'hexbear.net', 'beehaw.org', 'lemmynsfw.com', 'lemmy.ca', 'programming.dev'];
|
|
if (!config.feature.allow_user_supply_unsafe_domain && !allowedDomain.includes(new URL(`http://${instance}/`).hostname)) {
|
|
throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
|
}
|
|
|
|
const communityUrl = `https://${instance}/api/v3/community?name=${community}`;
|
|
const communityData = await cache.tryGet(communityUrl, async () => {
|
|
const result = await got({ method: 'get', url: communityUrl, headers: { 'Content-Type': 'application/json' } });
|
|
return result.data.community_view.community;
|
|
});
|
|
|
|
const postUrl = `https://${instance}/api/v3/post/list?type_=All&sort=${sort}&community_name=${community}&limit=50`;
|
|
const postData = await cache.tryGet(
|
|
postUrl,
|
|
async () => {
|
|
const result = await got({ method: 'get', url: postUrl, headers: { 'Content-Type': 'application/json' } });
|
|
return result.data;
|
|
},
|
|
config.cache.routeExpire,
|
|
false
|
|
);
|
|
|
|
const items = postData.posts.map((e) => {
|
|
const post = e.post;
|
|
const creator = e.creator;
|
|
const counts = e.counts;
|
|
const item = {
|
|
title: post.name,
|
|
author: creator.name,
|
|
pubDate: parseDate(post.published),
|
|
link: post.ap_id,
|
|
description: '',
|
|
comments: 0,
|
|
upvotes: 0,
|
|
downvotes: 0,
|
|
};
|
|
const url = post.url;
|
|
const urlContent = url ? `<p><a href="${url}">${url}</a></p>` : '';
|
|
const body = post.body ? md.render(post.body) : '';
|
|
item.description = urlContent + body;
|
|
item.comments = counts.comments;
|
|
item.upvotes = counts.upvotes;
|
|
item.downvotes = counts.downvotes;
|
|
return item;
|
|
});
|
|
|
|
return {
|
|
title: `${community} - ${sort} posts`,
|
|
description: communityData.description,
|
|
link: communityData.actor_id,
|
|
item: items,
|
|
};
|
|
}
|