import { Controller, Get, Res } from '@nestjs/common'; import { Response } from 'express'; import * as xml from 'xml'; import { InjectMetric } from '@willsoto/nestjs-prometheus'; import { Gauge, Histogram } from 'prom-client'; import { ApiTags } from '@nestjs/swagger'; const episodeFiles: [number, string][] = [ [27544345, '01-Into-the-Big-Wet.mp3'], [30724178, '02-Ocean-Rumours.mp3'], [30752181, '03-Step-Two.mp3'], [28793207, '04-Red-Ladder-Revelations.mp3'], [29684714, '05-What-to-do-with-a-Problem-Like-Daveda.mp3'], [29387545, '06-Hair-Bussy.mp3'], [30789798, '07-Monkey-Monkey-Cock-a-Roach.mp3'], [29449403, '08-SS-Jungle-and-Blood.mp3'], [29554728, '09-A-Bad-Day-in-Sogland.mp3'], [31728952, '10-A-Loathed-Trip-Down-Memory-Lane.mp3'], [29711881, '11-Dog-Egg-Consumption.mp3'], [31212772, '12-Meg-and-Bobs-Wedding-Bussy.mp3'], [30951548, '13-100-Genuine-Pussy-Hound.mp3'], [33766503, '14-One-Perfect-Answer.mp3'], [29643754, '15-Succulent-Pig-Excitement.mp3'], [29797145, '16-Welcome-to-Jackson-Island.mp3'], [37926451, '17-Infinite-Meat.mp3'], [33863888, '18-The-Jackson-Triumvirate.mp3'], [30256482, '19-A-Lucky-Day-to-be-a-Jackson.mp3'], [40947042, '20-The-Joels-Triumphant.mp3'], ]; const startDate = new Date('2023-10-16'); type Episode = { filename: string; length: number; url: string; title: string; description: string; fakeReleaseDate: Date; }; const dinosaurImage = 'https://imaginary.apps.hooli.co/enlarge?height=1400&width=1400&url=https://www.sanspantsradio.com/wp-content/uploads/2023/03/Dino-Wet-600x600.jpg'; const episodes: Episode[] = episodeFiles.map((file, i) => { const [length, filename] = file; return { filename, length, url: `https://s3.apps.hnl.byoi.net/dinosaurpark/DinosaurWet/${filename}`, title: filename.replace('.mp3', '').replace(/-/g, ' ').trim(), description: 'A bootleg-ish of Dinosar Wet, making the downloaded files more like and RSS feed', fakeReleaseDate: new Date( new Date(startDate).setDate(startDate.getDate() + i * 7), ), }; }); const buildFeeds = ( title: string, episodes: Episode[], pubDateFn: (index: number) => Date = () => startDate, ) => { const episodeItems = episodes .filter((episode: Episode, index: number) => pubDateFn(index) <= new Date()) .map(({ title, url, length, fakeReleaseDate }, index) => ({ item: [ { title }, { guid: url }, { pubDate: pubDateFn(index).toUTCString() }, { 'itunes:image': { _attr: { href: dinosaurImage, }, }, }, { 'itunes:episode': index + 1 }, { enclosure: [ { _attr: { url, type: 'audio/mpeg', length, }, }, ], }, ], })); const feedObject = { rss: [ { _attr: { version: '2.0', 'xmlns:atom': 'http://www.w3.org/2005/Atom', 'xmlns:itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd', 'xmlns:content': 'http://purl.org/rss/1.0/modules/content/', 'xmlns:podcast': 'https://podcastindex.org/namespace/1.0', }, }, { channel: [ { 'atom:link': { _attr: { href: 'https://api.us.dev/dinosaurwet', rel: 'self', type: 'application/rss+xml', }, }, }, { title, }, { link: 'https://sanspantsradio.com', }, { 'itunes:image': { _attr: { href: dinosaurImage, }, }, }, { description: 'A recreation of Dinosaur Wet as an RSS feed for listeners-with-licenses enjoyment.', }, { language: 'en-US' }, ...episodeItems, ], }, ], }; const feed = '' + xml(feedObject); return { feed, episodeItems }; }; @ApiTags('dinosaurwet') @Controller('dinosaurwet') export class DinosaurwetController { constructor( @InjectMetric('weekly_count') public weeklyCount: Gauge, @InjectMetric('daily_count') public dailyCount: Gauge, @InjectMetric('rss_query_count') public queryCount: Gauge, ) { } @Get('') getAllAtOnce(@Res() response: Response) { this.queryCount.inc(); response.header('Content-Type', 'application/xml'); const feed = buildFeeds('Dinosaur Wet - All At Once', episodes); return response.send(feed); } @Get('daily') getDaily(@Res() response: Response) { this.queryCount.inc(); response.header('Content-Type', 'application/xml'); const feed = buildFeeds( 'Dinosaur Wet - Daily', episodes, (index: number) => new Date(new Date(startDate).setDate(startDate.getDate() + index)), ); this.dailyCount.set(feed.episodeItems.length); return response.send(feed.feed); } @Get('weekly') getWeekly(@Res() response: Response) { this.queryCount.inc(); response.header('Content-Type', 'application/xml'); const feed = buildFeeds( 'Dinosaur Wet - Weekly', episodes, (index: number) => new Date(new Date(startDate).setDate(startDate.getDate() + index * 7)), ); this.weeklyCount.set(feed.episodeItems.length); return response.send(feed.feed); } }