Naposledy aktivní 1741105227

melanie revidoval tento gist 1741105227. Přejít na revizi

Žádné změny

melanie revidoval tento gist 1741105203. Přejít na revizi

Žádné změny

melanie revidoval tento gist 1732922313. Přejít na revizi

Žádné změny

melanie revidoval tento gist 1732918400. Přejít na revizi

1 file changed, 131 insertions

lastfm-weekly-report.ts(vytvořil soubor)

@@ -0,0 +1,131 @@
1 + const LASTFM_API_KEY = process.env.FEED_LASTFM_API_KEY || "";
2 + const LASTFM_USERNAME = process.env.FEED_LASTFM_USERNAME || "";
3 + const LASTFM_API = "https://ws.audioscrobbler.com/2.0/";
4 +
5 + function formatItem({
6 + artist,
7 + image,
8 + name,
9 + playcount,
10 + url,
11 + }: {
12 + artist: { "#text": string };
13 + image?: { "#text": string }[];
14 + name: string;
15 + playcount: string;
16 + url: string;
17 + }) {
18 + return {
19 + name: artist ? `${name} by ${artist?.["#text"]}` : name,
20 + image: image ? image?.at(-1)?.["#text"] : undefined,
21 + playcount,
22 + url,
23 + };
24 + }
25 +
26 + function epochToIso(epoch: string) {
27 + const date = new Date(Number.parseInt(epoch) * 1000);
28 + return date?.toISOString();
29 + }
30 +
31 + function isoToYearAndWeek(iso: string) {
32 + const date = new Date(iso);
33 + const year = date.getFullYear();
34 + const firstOfYear = new Date(year, 0, 1);
35 + const daysSinceFirstOfYear = Math.floor(
36 + (+date - +firstOfYear) / (24 * 60 * 60 * 1000),
37 + );
38 + const week = Math.ceil((date.getDay() + 1 + daysSinceFirstOfYear) / 7);
39 + return {
40 + week,
41 + year,
42 + };
43 + }
44 +
45 + function listToHTML(
46 + arr: {
47 + name: string;
48 + playcount: string;
49 + url: string;
50 + }[],
51 + ) {
52 + return arr
53 + .map(
54 + ({ name, playcount, url }) =>
55 + `<li><a href="${url}">${name}</a> (${playcount} plays)</li>`,
56 + )
57 + .join("");
58 + }
59 +
60 + async function lastFm(method = "") {
61 + const data = await fetch(
62 + `${LASTFM_API}?method=${method}&api_key=${LASTFM_API_KEY}&format=json&user=${LASTFM_USERNAME}`,
63 + );
64 + return await data.json();
65 + }
66 +
67 + async function getWeeklyChartList(limit = 5) {
68 + const data = await lastFm("user.getWeeklyChartList");
69 + return data?.weeklychartlist?.chart?.slice(limit * -1);
70 + }
71 +
72 + async function getWeeklyTrackChart(to: string, from: string, limit = 5) {
73 + const data = await lastFm(`user.getWeeklyTrackChart&from=${from}&to=${to}`);
74 + return data?.weeklytrackchart?.track?.slice(0, limit)?.map(formatItem);
75 + }
76 +
77 + async function getWeeklyAlbumChart(to: string, from: string, limit = 5) {
78 + const data = await lastFm(`user.getWeeklyAlbumChart&from=${from}&to=${to}`);
79 + return data?.weeklyalbumchart?.album?.slice(0, limit)?.map(formatItem);
80 + }
81 +
82 + async function getWeeklyArtistChart(to: string, from: string, limit = 5) {
83 + const data = await lastFm(`user.getWeeklyArtistChart&from=${from}&to=${to}`);
84 + return data?.weeklyartistchart?.artist?.slice(0, limit)?.map(formatItem);
85 + }
86 +
87 + async function buildReport() {
88 + const output = [];
89 + const weeks = await getWeeklyChartList();
90 + for (const week of weeks) {
91 + output.push({
92 + to: week.to,
93 + from: week.from,
94 + tracks: await getWeeklyTrackChart(week.to, week.from),
95 + albums: await getWeeklyAlbumChart(week.to, week.from),
96 + artists: await getWeeklyArtistChart(week.to, week.from),
97 + });
98 + }
99 + return output;
100 + }
101 +
102 + export default async function buildFeedItems() {
103 + const data = await buildReport();
104 + return data
105 + .map(({ to, from, tracks, albums, artists }) => {
106 + const trackList = listToHTML(tracks);
107 + const albumList = listToHTML(albums);
108 + const artistList = listToHTML(artists);
109 + const toIso = epochToIso(to);
110 + const fromIso = epochToIso(from);
111 + const { week, year } = isoToYearAndWeek(fromIso);
112 +
113 + if (!trackList && !albumList && !artistList) {
114 + return;
115 + }
116 +
117 + return {
118 + content_html: [
119 + artistList ? `<h2>Top Artists</h2><ol>${artistList}</ol>` : "",
120 + albumList ? `<h2>Top Albums</h2><ol>${albumList}</ol>` : "",
121 + trackList ? `<h2>Top Tracks</h2><ol>${trackList}</ol>` : "",
122 + ].join(""),
123 + date_published: toIso,
124 + id: `last.fm-${from}-${to}`,
125 + title: "weekly last.fm report",
126 + url: `https://www.last.fm/user/ZicklePop/listening-report/year/${year}/week/${week}`,
127 + tags: ["last.fm"],
128 + };
129 + })
130 + .filter((o) => !!o);
131 + }
Novější Starší