Happy TS proof-of-concept
This commit is contained in:
parent
d207f805ab
commit
b09146a7a0
3 changed files with 28 additions and 16 deletions
13
src/@types/bubo.d.ts
vendored
13
src/@types/bubo.d.ts
vendored
|
|
@ -7,5 +7,14 @@ export interface Feeds {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FeedItem {
|
export interface FeedItem {
|
||||||
[key: string]: string | FeedItem[];
|
[key: string]: string | number | Date | FeedItem[];
|
||||||
}
|
items: FeedItem[]
|
||||||
|
}
|
||||||
|
|
||||||
|
//NEW WAY
|
||||||
|
export type JSONValue =
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| { [x: string]: JSONValue }
|
||||||
|
| Array<JSONValue>;
|
||||||
|
|
@ -39,16 +39,17 @@ for (const [group, feeds] of Object.entries(feedList)) {
|
||||||
// skip to the next one if this didn't work out
|
// skip to the next one if this didn't work out
|
||||||
if (!body) continue;
|
if (!body) continue;
|
||||||
|
|
||||||
const contents: any =
|
const contents: FeedItem =
|
||||||
typeof body === "string" ? await parser.parseString(body) : body as { [key: string]: string };
|
(typeof body === "string" ? (await parser.parseString(body)) : body) as FeedItem;
|
||||||
|
|
||||||
|
|
||||||
contents.feed = feed;
|
contents.feed = feed;
|
||||||
contents.title = getTitle(contents);
|
contents.title = getTitle(contents);
|
||||||
contents.link = getLink(contents);
|
contents.link = getLink(contents);
|
||||||
contentFromAllFeeds[group].push(contents);
|
contentFromAllFeeds[group].push(contents as object);
|
||||||
|
|
||||||
// try to normalize date attribute naming
|
// try to normalize date attribute naming
|
||||||
contents?.items?.forEach((item: { [key: string]: string }) => {
|
contents?.items?.forEach((item) => {
|
||||||
item.timestamp = getTimestamp(item);
|
item.timestamp = getTimestamp(item);
|
||||||
item.title = getTitle(item);
|
item.title = getTitle(item);
|
||||||
item.link = getLink(item);
|
item.link = getLink(item);
|
||||||
|
|
|
||||||
|
|
@ -8,32 +8,34 @@
|
||||||
|
|
||||||
import { Response } from "node-fetch";
|
import { Response } from "node-fetch";
|
||||||
import { readFile } from "fs/promises";
|
import { readFile } from "fs/promises";
|
||||||
|
import { FeedItem, JSONValue } from "./@types/bubo";
|
||||||
|
|
||||||
export const getLink = (obj: { [key: string]: string }): string => {
|
export const getLink = (obj: FeedItem): string => {
|
||||||
const link_values: string[] = ["link", "url", "guid", "home_page_url"];
|
const link_values: string[] = ["link", "url", "guid", "home_page_url"];
|
||||||
const keys: string[] = Object.keys(obj);
|
const keys: string[] = Object.keys(obj);
|
||||||
const link_property: string | undefined = link_values.find(link_value => keys.includes(link_value));
|
const link_property: string | undefined = link_values.find(link_value => keys.includes(link_value));
|
||||||
return link_property ? obj[link_property] : "";
|
return link_property ? obj[link_property] as string : "";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// fallback to URL for the title if not present (coupled to my template)
|
// fallback to URL for the title if not present (coupled to my template)
|
||||||
export const getTitle = (obj: { [key: string]: string }): string => {
|
export const getTitle = (obj: FeedItem): string => {
|
||||||
const title_values: string[] = ["title", "url", "link"]; // fallback to url/link as title if omitted
|
const title_values: string[] = ["title", "url", "link"]; // fallback to url/link as title if omitted
|
||||||
const keys: string[] = Object.keys(obj);
|
const keys: string[] = Object.keys(obj);
|
||||||
const title_property: string | undefined = title_values.find(title_value => keys.includes(title_value));
|
const title_property: string | undefined = title_values.find(title_value => keys.includes(title_value));
|
||||||
return title_property ? obj[title_property] : "";
|
return title_property ? obj[title_property] as string : "";
|
||||||
};
|
};
|
||||||
|
|
||||||
// More dependable way to get timestamps
|
// More dependable way to get timestamps
|
||||||
export const getTimestamp = (obj: { [key: string]: string }): string => {
|
export const getTimestamp = (obj: FeedItem): string => {
|
||||||
const timestamp: number = new Date(obj.pubDate || obj.isoDate || obj.date || obj.date_published).getTime();
|
const dateString: string = (obj.pubDate || obj.isoDate || obj.date || obj.date_published).toString();
|
||||||
return isNaN(timestamp) ? (obj.pubDate || obj.isoDate || obj.date || obj.date_published) : timestamp.toString();
|
const timestamp: number = new Date(dateString).getTime();
|
||||||
|
return isNaN(timestamp) ? dateString : timestamp.toString();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// parse RSS/XML or JSON feeds
|
// parse RSS/XML or JSON feeds
|
||||||
export async function parseFeed(response: Response): Promise<{ [key: string]: string } | unknown> {
|
export async function parseFeed(response: Response): Promise<JSONValue> {
|
||||||
const contentType = response.headers.get("content-type")?.split(";")[0];
|
const contentType = response.headers.get("content-type")?.split(";")[0];
|
||||||
|
|
||||||
if (!contentType) return {};
|
if (!contentType) return {};
|
||||||
|
|
@ -54,7 +56,7 @@ export async function parseFeed(response: Response): Promise<{ [key: string]: st
|
||||||
|
|
||||||
const jsonFeed = [contentType]
|
const jsonFeed = [contentType]
|
||||||
.map(item =>
|
.map(item =>
|
||||||
["application/json", "application/feed+json"].includes(item) ? response.json() : false
|
["application/json", "application/feed+json"].includes(item) ? response.json() as Promise<JSONValue> : false
|
||||||
)
|
)
|
||||||
.filter(_ => _)[0];
|
.filter(_ => _)[0];
|
||||||
|
|
||||||
|
|
@ -62,7 +64,7 @@ export async function parseFeed(response: Response): Promise<{ [key: string]: st
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const getFeedList = async (): Promise<string> => {
|
export const getFeedList = async (): Promise<JSONValue> => {
|
||||||
return JSON.parse(
|
return JSON.parse(
|
||||||
(await readFile(
|
(await readFile(
|
||||||
new URL("../config/feeds.json", import.meta.url)
|
new URL("../config/feeds.json", import.meta.url)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue