Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add podcast-partytime 4.0.0-beta.4 #307

Merged
merged 5 commits into from Oct 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions package.json
@@ -1,6 +1,6 @@
{
"name": "podverse-api",
"version": "3.2.7",
"version": "3.3.0",
"description": "Data API, database migration scripts, and backend services for all Podverse models.",
"contributors": [
"Mitch Downey"
Expand Down Expand Up @@ -117,7 +117,6 @@
},
"dependencies": {
"@koa/cors": "3.0.0",
"@podverse/podcast-feed-parser": "^1.1.0",
"@types/crypto-js": "^3.1.47",
"@types/jest": "26.0.3",
"@typescript-eslint/eslint-plugin": "2.x",
Expand Down Expand Up @@ -146,6 +145,7 @@
"googleapis": "45.0.0",
"http-errors": "1.7.3",
"husky": "3.1.0",
"isomorphic-fetch": "^3.0.0",
"jest": "26.1.0",
"joi": "14.3.1",
"koa": "2.11.0",
Expand All @@ -167,6 +167,7 @@
"password-validator": "5.0.3",
"paypal-rest-sdk": "2.0.0-rc.2",
"pg": "7.14.0",
"podcast-partytime": "4.0.0-beta.5",
"podverse-shared": "^3.0.0",
"reflect-metadata": "0.1.13",
"request-promise-native": "1.0.8",
Expand Down
8 changes: 4 additions & 4 deletions src/entities/podcast.ts
Expand Up @@ -8,14 +8,14 @@ import { generateShortId } from '~/lib/utility'

type Funding = {
url: string
value: string
value?: string
}

type Value = {
export type Value = {
method: string
suggested: string
suggested?: string
type: string
valueRecipients: ValueRecipient[]
recipients: ValueRecipient[]
}

type ValueRecipient = {
Expand Down
100 changes: 89 additions & 11 deletions src/services/parser.ts
@@ -1,14 +1,18 @@
import * as _fetch from 'isomorphic-fetch'
import { parseFeed } from 'podcast-partytime'
import type { FeedObject, Episode as EpisodeObject, Phase1Funding, Phase4Value } from 'podcast-partytime'
import { Funding } from 'podverse-shared'
import { getRepository, In, Not } from 'typeorm'
import { config } from '~/config'
import { updateSoundBites } from '~/controllers/mediaRef'
import { getPodcast } from '~/controllers/podcast'
import { Author, Category, Episode, FeedUrl, Podcast } from '~/entities'
import type { Value } from '~/entities/podcast'
import { _logEnd, _logStart, convertToSlug, convertToSortableTitle,
isValidDate, logPerformance } from '~/lib/utility'
import { deleteMessage, receiveMessageFromQueue, sendMessageToQueue } from '~/services/queue'
import { getFeedUrls, getFeedUrlsByPodcastIndexIds } from '~/controllers/feedUrl'
import { shrinkImage } from './imageShrinker'
const podcastFeedParser = require('@podverse/podcast-feed-parser')
const { awsConfig, userAgent } = config
const { queueUrls, s3ImageLimitUpdateDays } = awsConfig

Expand All @@ -17,14 +21,88 @@ export const parseFeedUrl = async (feedUrl, forceReparsing = false) => {
logPerformance('parseFeedUrl', _logStart, 'feedUrl.url ' + feedUrl.url)

try {
logPerformance('podcastFeedParser.getPodcastFromURL', _logStart)
const result = await podcastFeedParser.getPodcastFromURL({
url: feedUrl.url,
headers: { 'User-Agent': userAgent },
timeout: 20000
})
logPerformance('podcastFeedParser.getPodcastFromURL', _logEnd)
const { episodes, meta } = result
logPerformance("podcastFetchAndParse", _logStart)
const xml = await _fetch(feedUrl.url, {
headers: { "User-Agent": userAgent },
}).then((resp) => resp.text())
const parsedFeed = parseFeed(xml)
logPerformance("podcastFetchAndParse", _logEnd)

if (!parsedFeed) {
throw new Error('parseFeedUrl invalid partytime parser response')
}

const fundingCompat = (funding: Phase1Funding): Funding => {
return {
value: funding.message,
url: funding.url
}
}

const valueCompat = (val: Phase4Value): Value => {
return {
type: val.type,
method: val.method,
suggested: val.suggested,
recipients: val.recipients.map((r) => {
return {
name: r.name,
type: r.type,
address: r.address,
split: r.split.toString(),
fee: r.fee
}
})
}
}

// Convert the podcast-partytime schema to a podverse compatible schema.
const feedCompat = (feed: FeedObject) => {
return {
author: [feed.author],
blocked: feed.itunesBlock,
categories: feed.itunesCategory,
description: feed.description,
explicit: feed.explicit,
funding: Array.isArray(feed.podcastFunding) ? feed.podcastFunding?.map((f) => fundingCompat(f)) : [],
generator: feed.generator,
guid: feed.guid,
imageURL: feed.itunesImage,
language: feed.language,
lastBuildDate: feed.lastBuildDate,
link: feed.link,
owner: feed.owner,
pubDate: feed.pubDate,
subtitle: feed.subtitle,
summary: feed.summary,
title: feed.title,
type: feed.itunesType,
value: feed.value ? [valueCompat(feed.value)] : []
mitchdowney marked this conversation as resolved.
Show resolved Hide resolved
}
}

// Convert the podcast-partytime schema to a podverse compatible schema.
const itemCompat = (episode: EpisodeObject) => {
return {
author: [episode.author],
description: episode.description,
duration: episode.duration,
enclosure: episode.enclosure,
explicit: episode.explicit,
guid: episode.guid,
imageURL: episode.image,
link: episode.link,
pubDate: episode.pubDate,
soundbite: episode.podcastSoundbites ?? [],
summary: episode.summary,
title: episode.title,
transcript: episode.podcastTranscripts ?? [],
value: episode.value ? [valueCompat(episode.value)] : []
mitchdowney marked this conversation as resolved.
Show resolved Hide resolved
}
}

const meta = feedCompat(parsedFeed)
const episodes = parsedFeed.items.map(itemCompat)

let podcast = new Podcast()
if (feedUrl.podcast) {
Expand Down Expand Up @@ -65,7 +143,7 @@ export const parseFeedUrl = async (feedUrl, forceReparsing = false) => {

let categories: Category[] = []
if (Array.isArray(meta.categories) && meta.categories.length > 0) {
logPerformance('findCategoreis', _logStart)
logPerformance('findCategories', _logStart)
categories = await findCategories(meta.categories)
logPerformance('findCategories', _logEnd)
}
Expand All @@ -78,7 +156,7 @@ export const parseFeedUrl = async (feedUrl, forceReparsing = false) => {
podcast.description = meta.description
podcast.feedLastParseFailed = false

const feedLastUpdated = new Date(mostRecentDateFromFeed || meta.lastBuildDate || meta.pubDate)
const feedLastUpdated = new Date(mostRecentDateFromFeed || meta.lastBuildDate || meta.pubDate || '')
podcast.feedLastUpdated = isValidDate(feedLastUpdated) ? feedLastUpdated : new Date()

podcast.funding = meta.funding
Expand Down