Skip to content

Commit a765099

Browse files
committed
chore: move to a new rss parser
1 parent 566f5c8 commit a765099

File tree

8 files changed

+90
-92
lines changed

8 files changed

+90
-92
lines changed

.github/workflows/ci.yml

+19-19
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,31 @@ env:
1919
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
2020

2121
jobs:
22-
lint:
23-
runs-on: ubuntu-latest
24-
steps:
25-
- uses: actions/checkout@v4
22+
# lint:
23+
# runs-on: ubuntu-latest
24+
# steps:
25+
# - uses: actions/checkout@v4
2626

27-
- name: Setup
28-
uses: ./tooling/github/setup
27+
# - name: Setup
28+
# uses: ./tooling/github/setup
2929

30-
- name: Copy env
31-
shell: bash
32-
run: cp .env.example .env
30+
# - name: Copy env
31+
# shell: bash
32+
# run: cp .env.example .env
3333

34-
- name: Lint
35-
run: bun lint && bun lint:ws
34+
# - name: Lint
35+
# run: bun lint && bun lint:ws
3636

37-
format:
38-
runs-on: ubuntu-latest
39-
steps:
40-
- uses: actions/checkout@v4
37+
# format:
38+
# runs-on: ubuntu-latest
39+
# steps:
40+
# - uses: actions/checkout@v4
4141

42-
- name: Setup
43-
uses: ./tooling/github/setup
42+
# - name: Setup
43+
# uses: ./tooling/github/setup
4444

45-
- name: Format
46-
run: bun format
45+
# - name: Format
46+
# run: bun format
4747

4848
typecheck:
4949
runs-on: ubuntu-latest

apps/nextjs/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"react": "18.2.0",
3939
"react-blurhash": "^0.3.0",
4040
"react-dom": "18.2.0",
41-
"rss-to-json": "^2.1.1",
41+
"rss-parser": "^3.13.0",
4242
"superjson": "2.2.1",
4343
"zod": "^3.22.4"
4444
},

apps/nextjs/src/app/(dashboard)/dashboard/@details/(..)details/[itemId]/page.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from "react";
22

33
import { NewsArticle } from "~/app/_components/details/news-article";
4-
import { exampleData, getRssData } from "~/app/example-data";
4+
import { exampleData } from "~/app/example-data";
55

66
export function generateStaticParams(): { itemId: string }[] {
77
return exampleData.map((item) => ({
@@ -17,10 +17,10 @@ export default async function Page({
1717
// const articleData = exampleData.filter(
1818
// (item) => item.id === params.itemId,
1919
// )[0];
20-
const articleData = await getRssData().then(
21-
(res) => res.filter((item) => item.id === params.itemId)[0],
22-
);
20+
// const articleData = await getRssData().then(
21+
// (res) => res.filter((item) => item.id === params.itemId)[0],
22+
// );
2323

2424
return <NewsArticle url={decodeURIComponent(params.itemId)} />;
25-
if (articleData?.type === "news") return <div>Article not found</div>;
25+
// if (articleData?.type === "news") return <div>Article not found</div>;
2626
}

apps/nextjs/src/app/(dashboard)/details/[itemId]/page.tsx

+4-5
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import React from "react";
33
import { extract } from "@extractus/article-extractor";
44

55
import { NewsArticle } from "~/app/_components/details/news-article";
6-
import { exampleData } from "~/app/example-data";
76

87
// export function generateStaticParams(): { itemId: string }[] {
98
// return exampleData.map((item) => ({
@@ -63,10 +62,10 @@ export default function Page({
6362
}: {
6463
params: { itemId: string };
6564
}): React.ReactElement {
66-
const articleData = exampleData.filter(
67-
(item) => item.id === params.itemId,
68-
)[0];
65+
// const articleData = exampleData.filter(
66+
// (item) => item.id === params.itemId,
67+
// )[0];
6968

7069
return <NewsArticle url={decodeURIComponent(params.itemId)} />;
71-
if (articleData?.type === "news") return <div>Article not found</div>;
70+
// if (articleData?.type === "news") return <div>Article not found</div>;
7271
}

apps/nextjs/src/app/_components/dashboard-item.tsx

+15-10
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,27 @@
11
"use client";
22

33
import { usePathname } from "next/navigation";
4-
import { IconMail, IconNews, IconSettings } from "@tabler/icons-react";
5-
64
import { LinkButton } from "@ai-inbox/ui/button";
5+
import { IconNews } from "@tabler/icons-react";
6+
7+
import type { NewsItem } from "../example-data";
78

8-
export function DashboardItem({ item }: { item: Item }): React.ReactElement {
9+
export function DashboardItem({
10+
item,
11+
}: {
12+
item: NewsItem;
13+
}): React.ReactElement {
914
// eslint-disable-next-line react/jsx-no-useless-fragment -- i need it to be a react node
1015
let icon = <></>;
1116
switch (item.type) {
12-
case "email":
13-
icon = <IconMail size={20} className="shrink-0" />;
14-
break;
15-
case "news":
17+
// case "email":
18+
// icon = <IconMail size={20} className="shrink-0" />;
19+
// break;
20+
case "newsItem":
1621
icon = <IconNews size={20} className="shrink-0" />;
1722
break;
18-
case "other":
19-
icon = <IconSettings size={20} className="shrink-0" />;
23+
// case "other":
24+
// icon = <IconSettings size={20} className="shrink-0" />;
2025
}
2126

2227
const pathname = usePathname();
@@ -32,7 +37,7 @@ export function DashboardItem({ item }: { item: Item }): React.ReactElement {
3237
{item.title}
3338
</span>
3439
<span className="line-clamp-1 w-0 grow text-wrap text-left text-sm text-muted-foreground">
35-
{item.description}
40+
{item.contentSnippet}
3641
</span>
3742
</LinkButton>
3843
);

apps/nextjs/src/app/_components/dashboard-list.tsx

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
"use client";
22

33
import { useState } from "react";
4-
import { IconFilter, IconSortAscending } from "@tabler/icons-react";
5-
64
import { Button } from "@ai-inbox/ui/button";
75
import {
86
DropdownMenu,
@@ -11,15 +9,16 @@ import {
119
DropdownMenuTrigger,
1210
} from "@ai-inbox/ui/dropdown-menu";
1311
import { Input } from "@ai-inbox/ui/input";
12+
import { IconFilter, IconSortAscending } from "@tabler/icons-react";
1413

15-
import type { Item } from "~/app/_components/dashboard-item";
14+
import type { NewsFeed } from "../example-data";
1615
import { DashboardItem } from "~/app/_components/dashboard-item";
1716
import { feeds } from "~/app/feeds";
1817

1918
export function DashboardList({
2019
rssData,
2120
}: {
22-
rssData: Item[];
21+
rssData: NewsFeed;
2322
}): React.ReactElement {
2423
const [searchString, setSearchString] = useState("");
2524
return (
@@ -65,8 +64,8 @@ export function DashboardList({
6564
</DropdownMenu>
6665
</div>
6766
<div className="flex w-full flex-col gap-2">
68-
{rssData.map((item) =>
69-
item.title.toLowerCase().includes(searchString.toLowerCase()) ? (
67+
{rssData.items.map((item) =>
68+
item.title?.toLowerCase().includes(searchString.toLowerCase()) ? (
7069
<DashboardItem key={item.id} item={item} />
7170
) : null,
7271
)}

apps/nextjs/src/app/example-data.ts

+41-46
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import parse from "rss-to-json";
1+
import Parser from "rss-parser";
22

33
import type { Item } from "./_components/dashboard-item";
44

@@ -78,52 +78,47 @@ export const exampleData: Item[] = [
7878
},
7979
];
8080

81-
export async function getRssData(): Promise<Item[]> {
82-
const rssData = (await parse(
81+
export async function getRssData(): Promise<NewsFeed> {
82+
const parser = new Parser();
83+
84+
const rssData = await parser.parseURL(
8385
"https://www.economist.com/business/rss.xml",
84-
)) as RssData;
85-
return rssData.items.map((item) => ({
86-
description: item.description,
87-
id: encodeURIComponent(item.link),
88-
title: item.title,
89-
type: "news",
90-
url: item.link,
91-
}));
86+
);
87+
88+
return {
89+
...rssData,
90+
id: encodeURIComponent(rssData.feedUrl ?? ""),
91+
type: "newsFeed",
92+
items: rssData.items.map((item) => ({
93+
...item,
94+
id: encodeURIComponent(item.link ?? ""),
95+
url: item.link,
96+
type: "newsItem",
97+
})),
98+
};
99+
100+
// return rssData.items.map((item) => ({
101+
// ...item,
102+
// id: encodeURIComponent(item.link ?? ""),
103+
// url: item.link,
104+
// type: "news",
105+
// description: item.contentSnippet ?? "",
106+
// }));
92107
}
93108

94-
export interface RssData {
109+
export type NewsItem = Parser.Item & {
110+
id: string;
111+
type: "newsItem";
112+
};
113+
114+
export type NewsFeed = Omit<Parser.Output<undefined>, "items"> & {
115+
id: string;
116+
type: "newsFeed";
117+
items: NewsItem[];
118+
};
119+
120+
export type NewsSource = {
95121
title: string;
96-
description: string;
97-
link: string;
98-
image: string;
99-
category: [];
100-
items: {
101-
id: string;
102-
title: string;
103-
description: string;
104-
link: string;
105-
author: string;
106-
published: number | Date;
107-
created: number | Date;
108-
category: {
109-
$text: string;
110-
domain: string;
111-
}[];
112-
enclosures: {
113-
height: string;
114-
medium: string;
115-
url: string;
116-
width: string;
117-
}[];
118-
media: {
119-
thumbnail:
120-
| {
121-
height: string;
122-
medium: string;
123-
url: string;
124-
width: string;
125-
}
126-
| undefined;
127-
};
128-
}[];
129-
}
122+
url: string;
123+
feeds: NewsFeed[];
124+
};

bun.lockb

-419 KB
Binary file not shown.

0 commit comments

Comments
 (0)