mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2024-12-20 19:06:06 +01:00
Merge pull request #3692 from mikiher/rss-remove-server-address
Remove serverAddress from Feeds and FeedEpisodes URLs
This commit is contained in:
commit
726adbb3bf
@ -10,9 +10,9 @@
|
||||
<p class="text-lg font-semibold mb-4">{{ $strings.HeaderRSSFeedIsOpen }}</p>
|
||||
|
||||
<div class="w-full relative">
|
||||
<ui-text-input v-model="currentFeed.feedUrl" readonly />
|
||||
<ui-text-input :value="feedUrl" readonly />
|
||||
|
||||
<span class="material-symbols absolute right-2 bottom-2 p-0.5 text-base transition-transform duration-100 text-gray-300 hover:text-white transform hover:scale-125 cursor-pointer" @click="copyToClipboard(currentFeed.feedUrl)">content_copy</span>
|
||||
<span class="material-symbols absolute right-2 bottom-2 p-0.5 text-base transition-transform duration-100 text-gray-300 hover:text-white transform hover:scale-125 cursor-pointer" @click="copyToClipboard(feedUrl)">content_copy</span>
|
||||
</div>
|
||||
|
||||
<div v-if="currentFeed.meta" class="mt-5">
|
||||
@ -111,8 +111,11 @@ export default {
|
||||
userIsAdminOrUp() {
|
||||
return this.$store.getters['user/getIsAdminOrUp']
|
||||
},
|
||||
feedUrl() {
|
||||
return this.currentFeed ? `${window.origin}${this.$config.routerBasePath}${this.currentFeed.feedUrl}` : ''
|
||||
},
|
||||
demoFeedUrl() {
|
||||
return `${window.origin}/feed/${this.newFeedSlug}`
|
||||
return `${window.origin}${this.$config.routerBasePath}/feed/${this.newFeedSlug}`
|
||||
},
|
||||
isHttp() {
|
||||
return window.origin.startsWith('http://')
|
||||
|
@ -5,8 +5,8 @@
|
||||
<p class="text-lg font-semibold mb-4">{{ $strings.HeaderRSSFeedGeneral }}</p>
|
||||
|
||||
<div class="w-full relative">
|
||||
<ui-text-input v-model="feed.feedUrl" readonly />
|
||||
<span class="material-symbols absolute right-2 bottom-2 p-0.5 text-base transition-transform duration-100 text-gray-300 hover:text-white transform hover:scale-125 cursor-pointer" @click="copyToClipboard(feed.feedUrl)">content_copy</span>
|
||||
<ui-text-input :value="feedUrl" readonly />
|
||||
<span class="material-symbols absolute right-2 bottom-2 p-0.5 text-base transition-transform duration-100 text-gray-300 hover:text-white transform hover:scale-125 cursor-pointer" @click="copyToClipboard(feedUrl)">content_copy</span>
|
||||
</div>
|
||||
|
||||
<div v-if="feed.meta" class="mt-5">
|
||||
@ -70,6 +70,9 @@ export default {
|
||||
},
|
||||
_feed() {
|
||||
return this.feed || {}
|
||||
},
|
||||
feedUrl() {
|
||||
return this.feed ? `${window.origin}${this.$config.routerBasePath}${this.feed.feedUrl}` : ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -126,7 +126,7 @@ export default {
|
||||
},
|
||||
coverUrl(feed) {
|
||||
if (!feed.coverPath) return `${this.$config.routerBasePath}/Logo.png`
|
||||
return `${feed.feedUrl}/cover`
|
||||
return `${this.$config.routerBasePath}${feed.feedUrl}/cover`
|
||||
},
|
||||
async loadFeeds() {
|
||||
const data = await this.$axios.$get(`/api/feeds`).catch((err) => {
|
||||
|
@ -251,14 +251,17 @@ class Server {
|
||||
|
||||
const router = express.Router()
|
||||
// if RouterBasePath is set, modify all requests to include the base path
|
||||
if (global.RouterBasePath) {
|
||||
app.use((req, res, next) => {
|
||||
if (!req.url.startsWith(global.RouterBasePath)) {
|
||||
req.url = `${global.RouterBasePath}${req.url}`
|
||||
}
|
||||
next()
|
||||
})
|
||||
}
|
||||
app.use((req, res, next) => {
|
||||
const urlStartsWithRouterBasePath = req.url.startsWith(global.RouterBasePath)
|
||||
const host = req.get('host')
|
||||
const protocol = req.secure || req.get('x-forwarded-proto') === 'https' ? 'https' : 'http'
|
||||
const prefix = urlStartsWithRouterBasePath ? global.RouterBasePath : ''
|
||||
req.originalHostPrefix = `${protocol}://${host}${prefix}`
|
||||
if (!urlStartsWithRouterBasePath) {
|
||||
req.url = `${global.RouterBasePath}${req.url}`
|
||||
}
|
||||
next()
|
||||
})
|
||||
app.use(global.RouterBasePath, router)
|
||||
app.disable('x-powered-by')
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
const { Request, Response } = require('express')
|
||||
const Path = require('path')
|
||||
|
||||
const Logger = require('../Logger')
|
||||
@ -77,6 +78,12 @@ class RssFeedManager {
|
||||
return Database.feedModel.findByPkOld(id)
|
||||
}
|
||||
|
||||
/**
|
||||
* GET: /feed/:slug
|
||||
*
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
*/
|
||||
async getFeed(req, res) {
|
||||
const feed = await this.findFeedBySlug(req.params.slug)
|
||||
if (!feed) {
|
||||
@ -162,11 +169,17 @@ class RssFeedManager {
|
||||
}
|
||||
}
|
||||
|
||||
const xml = feed.buildXml()
|
||||
const xml = feed.buildXml(req.originalHostPrefix)
|
||||
res.set('Content-Type', 'text/xml')
|
||||
res.send(xml)
|
||||
}
|
||||
|
||||
/**
|
||||
* GET: /feed/:slug/item/:episodeId/*
|
||||
*
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
*/
|
||||
async getFeedItem(req, res) {
|
||||
const feed = await this.findFeedBySlug(req.params.slug)
|
||||
if (!feed) {
|
||||
@ -183,6 +196,12 @@ class RssFeedManager {
|
||||
res.sendFile(episodePath)
|
||||
}
|
||||
|
||||
/**
|
||||
* GET: /feed/:slug/cover*
|
||||
*
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
*/
|
||||
async getFeedCover(req, res) {
|
||||
const feed = await this.findFeedBySlug(req.params.slug)
|
||||
if (!feed) {
|
||||
|
@ -10,3 +10,4 @@ Please add a record of every database migration that you create to this file. Th
|
||||
| v2.17.0 | v2.17.0-uuid-replacement | Changes the data type of columns with UUIDv4 to UUID matching the associated model |
|
||||
| v2.17.3 | v2.17.3-fk-constraints | Changes the foreign key constraints for tables due to sequelize bug dropping constraints in v2.17.0 migration |
|
||||
| v2.17.4 | v2.17.4-use-subfolder-for-oidc-redirect-uris | Save subfolder to OIDC redirect URIs to support existing installations |
|
||||
| v2.17.5 | v2.17.5-remove-host-from-feed-urls | removes the host (serverAddress) from URL columns in the feeds and feedEpisodes tables |
|
||||
|
74
server/migrations/v2.17.5-remove-host-from-feed-urls.js
Normal file
74
server/migrations/v2.17.5-remove-host-from-feed-urls.js
Normal file
@ -0,0 +1,74 @@
|
||||
/**
|
||||
* @typedef MigrationContext
|
||||
* @property {import('sequelize').QueryInterface} queryInterface - a suquelize QueryInterface object.
|
||||
* @property {import('../Logger')} logger - a Logger object.
|
||||
*
|
||||
* @typedef MigrationOptions
|
||||
* @property {MigrationContext} context - an object containing the migration context.
|
||||
*/
|
||||
|
||||
const migrationVersion = '2.17.5'
|
||||
const migrationName = `${migrationVersion}-remove-host-from-feed-urls`
|
||||
const loggerPrefix = `[${migrationVersion} migration]`
|
||||
|
||||
/**
|
||||
* This upward migration removes the host (serverAddress) from URL columns in the feeds and feedEpisodes tables.
|
||||
*
|
||||
* @param {MigrationOptions} options - an object containing the migration context.
|
||||
* @returns {Promise<void>} - A promise that resolves when the migration is complete.
|
||||
*/
|
||||
async function up({ context: { queryInterface, logger } }) {
|
||||
// Upwards migration script
|
||||
logger.info(`${loggerPrefix} UPGRADE BEGIN: ${migrationName}`)
|
||||
|
||||
logger.info(`${loggerPrefix} Removing serverAddress from Feeds table URLs`)
|
||||
await queryInterface.sequelize.query(`
|
||||
UPDATE Feeds
|
||||
SET feedUrl = REPLACE(feedUrl, COALESCE(serverAddress, ''), ''),
|
||||
imageUrl = REPLACE(imageUrl, COALESCE(serverAddress, ''), ''),
|
||||
siteUrl = REPLACE(siteUrl, COALESCE(serverAddress, ''), '');
|
||||
`)
|
||||
logger.info(`${loggerPrefix} Removed serverAddress from Feeds table URLs`)
|
||||
|
||||
logger.info(`${loggerPrefix} Removing serverAddress from FeedEpisodes table URLs`)
|
||||
await queryInterface.sequelize.query(`
|
||||
UPDATE FeedEpisodes
|
||||
SET siteUrl = REPLACE(siteUrl, (SELECT COALESCE(serverAddress, '') FROM Feeds WHERE Feeds.id = FeedEpisodes.feedId), ''),
|
||||
enclosureUrl = REPLACE(enclosureUrl, (SELECT COALESCE(serverAddress, '') FROM Feeds WHERE Feeds.id = FeedEpisodes.feedId), '');
|
||||
`)
|
||||
logger.info(`${loggerPrefix} Removed serverAddress from FeedEpisodes table URLs`)
|
||||
|
||||
logger.info(`${loggerPrefix} UPGRADE END: ${migrationName}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* This downward migration script adds the host (serverAddress) back to URL columns in the feeds and feedEpisodes tables.
|
||||
*
|
||||
* @param {MigrationOptions} options - an object containing the migration context.
|
||||
* @returns {Promise<void>} - A promise that resolves when the migration is complete.
|
||||
*/
|
||||
async function down({ context: { queryInterface, logger } }) {
|
||||
// Downward migration script
|
||||
logger.info(`${loggerPrefix} DOWNGRADE BEGIN: ${migrationName}`)
|
||||
|
||||
logger.info(`${loggerPrefix} Adding serverAddress back to Feeds table URLs`)
|
||||
await queryInterface.sequelize.query(`
|
||||
UPDATE Feeds
|
||||
SET feedUrl = COALESCE(serverAddress, '') || feedUrl,
|
||||
imageUrl = COALESCE(serverAddress, '') || imageUrl,
|
||||
siteUrl = COALESCE(serverAddress, '') || siteUrl;
|
||||
`)
|
||||
logger.info(`${loggerPrefix} Added serverAddress back to Feeds table URLs`)
|
||||
|
||||
logger.info(`${loggerPrefix} Adding serverAddress back to FeedEpisodes table URLs`)
|
||||
await queryInterface.sequelize.query(`
|
||||
UPDATE FeedEpisodes
|
||||
SET siteUrl = (SELECT COALESCE(serverAddress, '') || FeedEpisodes.siteUrl FROM Feeds WHERE Feeds.id = FeedEpisodes.feedId),
|
||||
enclosureUrl = (SELECT COALESCE(serverAddress, '') || FeedEpisodes.enclosureUrl FROM Feeds WHERE Feeds.id = FeedEpisodes.feedId);
|
||||
`)
|
||||
logger.info(`${loggerPrefix} Added serverAddress back to FeedEpisodes table URLs`)
|
||||
|
||||
logger.info(`${loggerPrefix} DOWNGRADE END: ${migrationName}`)
|
||||
}
|
||||
|
||||
module.exports = { up, down }
|
@ -29,9 +29,6 @@ class Feed {
|
||||
this.createdAt = null
|
||||
this.updatedAt = null
|
||||
|
||||
// Cached xml
|
||||
this.xml = null
|
||||
|
||||
if (feed) {
|
||||
this.construct(feed)
|
||||
}
|
||||
@ -109,7 +106,7 @@ class Feed {
|
||||
const mediaMetadata = media.metadata
|
||||
const isPodcast = libraryItem.mediaType === 'podcast'
|
||||
|
||||
const feedUrl = `${serverAddress}/feed/${slug}`
|
||||
const feedUrl = `/feed/${slug}`
|
||||
const author = isPodcast ? mediaMetadata.author : mediaMetadata.authorName
|
||||
|
||||
this.id = uuidv4()
|
||||
@ -128,9 +125,9 @@ class Feed {
|
||||
this.meta.title = mediaMetadata.title
|
||||
this.meta.description = mediaMetadata.description
|
||||
this.meta.author = author
|
||||
this.meta.imageUrl = media.coverPath ? `${serverAddress}/feed/${slug}/cover${coverFileExtension}` : `${serverAddress}/Logo.png`
|
||||
this.meta.imageUrl = media.coverPath ? `/feed/${slug}/cover${coverFileExtension}` : `/Logo.png`
|
||||
this.meta.feedUrl = feedUrl
|
||||
this.meta.link = `${serverAddress}/item/${libraryItem.id}`
|
||||
this.meta.link = `/item/${libraryItem.id}`
|
||||
this.meta.explicit = !!mediaMetadata.explicit
|
||||
this.meta.type = mediaMetadata.type
|
||||
this.meta.language = mediaMetadata.language
|
||||
@ -176,7 +173,7 @@ class Feed {
|
||||
this.meta.title = mediaMetadata.title
|
||||
this.meta.description = mediaMetadata.description
|
||||
this.meta.author = author
|
||||
this.meta.imageUrl = media.coverPath ? `${this.serverAddress}/feed/${this.slug}/cover${coverFileExtension}` : `${this.serverAddress}/Logo.png`
|
||||
this.meta.imageUrl = media.coverPath ? `/feed/${this.slug}/cover${coverFileExtension}` : `/Logo.png`
|
||||
this.meta.explicit = !!mediaMetadata.explicit
|
||||
this.meta.type = mediaMetadata.type
|
||||
this.meta.language = mediaMetadata.language
|
||||
@ -202,11 +199,10 @@ class Feed {
|
||||
}
|
||||
|
||||
this.updatedAt = Date.now()
|
||||
this.xml = null
|
||||
}
|
||||
|
||||
setFromCollection(userId, slug, collectionExpanded, serverAddress, preventIndexing = true, ownerName = null, ownerEmail = null) {
|
||||
const feedUrl = `${serverAddress}/feed/${slug}`
|
||||
const feedUrl = `/feed/${slug}`
|
||||
|
||||
const itemsWithTracks = collectionExpanded.books.filter((libraryItem) => libraryItem.media.tracks.length)
|
||||
const firstItemWithCover = itemsWithTracks.find((item) => item.media.coverPath)
|
||||
@ -227,9 +223,9 @@ class Feed {
|
||||
this.meta.title = collectionExpanded.name
|
||||
this.meta.description = collectionExpanded.description || ''
|
||||
this.meta.author = this.getAuthorsStringFromLibraryItems(itemsWithTracks)
|
||||
this.meta.imageUrl = this.coverPath ? `${serverAddress}/feed/${slug}/cover${coverFileExtension}` : `${serverAddress}/Logo.png`
|
||||
this.meta.imageUrl = this.coverPath ? `/feed/${slug}/cover${coverFileExtension}` : `/Logo.png`
|
||||
this.meta.feedUrl = feedUrl
|
||||
this.meta.link = `${serverAddress}/collection/${collectionExpanded.id}`
|
||||
this.meta.link = `/collection/${collectionExpanded.id}`
|
||||
this.meta.explicit = !!itemsWithTracks.some((li) => li.media.metadata.explicit) // explicit if any item is explicit
|
||||
this.meta.preventIndexing = preventIndexing
|
||||
this.meta.ownerName = ownerName
|
||||
@ -272,7 +268,7 @@ class Feed {
|
||||
this.meta.title = collectionExpanded.name
|
||||
this.meta.description = collectionExpanded.description || ''
|
||||
this.meta.author = this.getAuthorsStringFromLibraryItems(itemsWithTracks)
|
||||
this.meta.imageUrl = this.coverPath ? `${this.serverAddress}/feed/${this.slug}/cover${coverFileExtension}` : `${this.serverAddress}/Logo.png`
|
||||
this.meta.imageUrl = this.coverPath ? `/feed/${this.slug}/cover${coverFileExtension}` : `/Logo.png`
|
||||
this.meta.explicit = !!itemsWithTracks.some((li) => li.media.metadata.explicit) // explicit if any item is explicit
|
||||
|
||||
this.episodes = []
|
||||
@ -297,11 +293,10 @@ class Feed {
|
||||
})
|
||||
|
||||
this.updatedAt = Date.now()
|
||||
this.xml = null
|
||||
}
|
||||
|
||||
setFromSeries(userId, slug, seriesExpanded, serverAddress, preventIndexing = true, ownerName = null, ownerEmail = null) {
|
||||
const feedUrl = `${serverAddress}/feed/${slug}`
|
||||
const feedUrl = `/feed/${slug}`
|
||||
|
||||
let itemsWithTracks = seriesExpanded.books.filter((libraryItem) => libraryItem.media.tracks.length)
|
||||
// Sort series items by series sequence
|
||||
@ -326,9 +321,9 @@ class Feed {
|
||||
this.meta.title = seriesExpanded.name
|
||||
this.meta.description = seriesExpanded.description || ''
|
||||
this.meta.author = this.getAuthorsStringFromLibraryItems(itemsWithTracks)
|
||||
this.meta.imageUrl = this.coverPath ? `${serverAddress}/feed/${slug}/cover${coverFileExtension}` : `${serverAddress}/Logo.png`
|
||||
this.meta.imageUrl = this.coverPath ? `/feed/${slug}/cover${coverFileExtension}` : `/Logo.png`
|
||||
this.meta.feedUrl = feedUrl
|
||||
this.meta.link = `${serverAddress}/library/${libraryId}/series/${seriesExpanded.id}`
|
||||
this.meta.link = `/library/${libraryId}/series/${seriesExpanded.id}`
|
||||
this.meta.explicit = !!itemsWithTracks.some((li) => li.media.metadata.explicit) // explicit if any item is explicit
|
||||
this.meta.preventIndexing = preventIndexing
|
||||
this.meta.ownerName = ownerName
|
||||
@ -374,7 +369,7 @@ class Feed {
|
||||
this.meta.title = seriesExpanded.name
|
||||
this.meta.description = seriesExpanded.description || ''
|
||||
this.meta.author = this.getAuthorsStringFromLibraryItems(itemsWithTracks)
|
||||
this.meta.imageUrl = this.coverPath ? `${this.serverAddress}/feed/${this.slug}/cover${coverFileExtension}` : `${this.serverAddress}/Logo.png`
|
||||
this.meta.imageUrl = this.coverPath ? `/feed/${this.slug}/cover${coverFileExtension}` : `/Logo.png`
|
||||
this.meta.explicit = !!itemsWithTracks.some((li) => li.media.metadata.explicit) // explicit if any item is explicit
|
||||
|
||||
this.episodes = []
|
||||
@ -399,18 +394,14 @@ class Feed {
|
||||
})
|
||||
|
||||
this.updatedAt = Date.now()
|
||||
this.xml = null
|
||||
}
|
||||
|
||||
buildXml() {
|
||||
if (this.xml) return this.xml
|
||||
|
||||
var rssfeed = new RSS(this.meta.getRSSData())
|
||||
buildXml(originalHostPrefix) {
|
||||
var rssfeed = new RSS(this.meta.getRSSData(originalHostPrefix))
|
||||
this.episodes.forEach((ep) => {
|
||||
rssfeed.item(ep.getRSSData())
|
||||
rssfeed.item(ep.getRSSData(originalHostPrefix))
|
||||
})
|
||||
this.xml = rssfeed.xml()
|
||||
return this.xml
|
||||
return rssfeed.xml()
|
||||
}
|
||||
|
||||
getAuthorsStringFromLibraryItems(libraryItems) {
|
||||
|
@ -79,7 +79,7 @@ class FeedEpisode {
|
||||
this.title = episode.title
|
||||
this.description = episode.description || ''
|
||||
this.enclosure = {
|
||||
url: `${serverAddress}${contentUrl}`,
|
||||
url: `${contentUrl}`,
|
||||
type: episode.audioTrack.mimeType,
|
||||
size: episode.size
|
||||
}
|
||||
@ -136,7 +136,7 @@ class FeedEpisode {
|
||||
this.title = title
|
||||
this.description = mediaMetadata.description || ''
|
||||
this.enclosure = {
|
||||
url: `${serverAddress}${contentUrl}`,
|
||||
url: `${contentUrl}`,
|
||||
type: audioTrack.mimeType,
|
||||
size: audioTrack.metadata.size
|
||||
}
|
||||
@ -151,15 +151,19 @@ class FeedEpisode {
|
||||
this.fullPath = audioTrack.metadata.path
|
||||
}
|
||||
|
||||
getRSSData() {
|
||||
getRSSData(hostPrefix) {
|
||||
return {
|
||||
title: this.title,
|
||||
description: this.description || '',
|
||||
url: this.link,
|
||||
guid: this.enclosure.url,
|
||||
url: `${hostPrefix}${this.link}`,
|
||||
guid: `${hostPrefix}${this.enclosure.url}`,
|
||||
author: this.author,
|
||||
date: this.pubDate,
|
||||
enclosure: this.enclosure,
|
||||
enclosure: {
|
||||
url: `${hostPrefix}${this.enclosure.url}`,
|
||||
type: this.enclosure.type,
|
||||
size: this.enclosure.size
|
||||
},
|
||||
custom_elements: [
|
||||
{ 'itunes:author': this.author },
|
||||
{ 'itunes:duration': secondsToTimestamp(this.duration) },
|
||||
|
@ -60,42 +60,36 @@ class FeedMeta {
|
||||
}
|
||||
}
|
||||
|
||||
getRSSData() {
|
||||
const blockTags = [
|
||||
{ 'itunes:block': 'yes' },
|
||||
{ 'googleplay:block': 'yes' }
|
||||
]
|
||||
getRSSData(hostPrefix) {
|
||||
const blockTags = [{ 'itunes:block': 'yes' }, { 'googleplay:block': 'yes' }]
|
||||
return {
|
||||
title: this.title,
|
||||
description: this.description || '',
|
||||
generator: 'Audiobookshelf',
|
||||
feed_url: this.feedUrl,
|
||||
site_url: this.link,
|
||||
image_url: this.imageUrl,
|
||||
feed_url: `${hostPrefix}${this.feedUrl}`,
|
||||
site_url: `${hostPrefix}${this.link}`,
|
||||
image_url: `${hostPrefix}${this.imageUrl}`,
|
||||
custom_namespaces: {
|
||||
'itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd',
|
||||
'psc': 'http://podlove.org/simple-chapters',
|
||||
'podcast': 'https://podcastindex.org/namespace/1.0',
|
||||
'googleplay': 'http://www.google.com/schemas/play-podcasts/1.0'
|
||||
itunes: 'http://www.itunes.com/dtds/podcast-1.0.dtd',
|
||||
psc: 'http://podlove.org/simple-chapters',
|
||||
podcast: 'https://podcastindex.org/namespace/1.0',
|
||||
googleplay: 'http://www.google.com/schemas/play-podcasts/1.0'
|
||||
},
|
||||
custom_elements: [
|
||||
{ 'language': this.language || 'en' },
|
||||
{ 'author': this.author || 'advplyr' },
|
||||
{ language: this.language || 'en' },
|
||||
{ author: this.author || 'advplyr' },
|
||||
{ 'itunes:author': this.author || 'advplyr' },
|
||||
{ 'itunes:summary': this.description || '' },
|
||||
{ 'itunes:type': this.type },
|
||||
{
|
||||
'itunes:image': {
|
||||
_attr: {
|
||||
href: this.imageUrl
|
||||
href: `${hostPrefix}${this.imageUrl}`
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
'itunes:owner': [
|
||||
{ 'itunes:name': this.ownerName || this.author || '' },
|
||||
{ 'itunes:email': this.ownerEmail || '' }
|
||||
]
|
||||
'itunes:owner': [{ 'itunes:name': this.ownerName || this.author || '' }, { 'itunes:email': this.ownerEmail || '' }]
|
||||
},
|
||||
{ 'itunes:explicit': !!this.explicit },
|
||||
...(this.preventIndexing ? blockTags : [])
|
||||
|
@ -0,0 +1,202 @@
|
||||
const { expect } = require('chai')
|
||||
const sinon = require('sinon')
|
||||
const { up, down } = require('../../../server/migrations/v2.17.5-remove-host-from-feed-urls')
|
||||
const { Sequelize, DataTypes } = require('sequelize')
|
||||
const Logger = require('../../../server/Logger')
|
||||
|
||||
const defineModels = (sequelize) => {
|
||||
const Feeds = sequelize.define('Feeds', {
|
||||
id: { type: DataTypes.UUID, primaryKey: true, defaultValue: DataTypes.UUIDV4 },
|
||||
feedUrl: { type: DataTypes.STRING },
|
||||
imageUrl: { type: DataTypes.STRING },
|
||||
siteUrl: { type: DataTypes.STRING },
|
||||
serverAddress: { type: DataTypes.STRING }
|
||||
})
|
||||
|
||||
const FeedEpisodes = sequelize.define('FeedEpisodes', {
|
||||
id: { type: DataTypes.UUID, primaryKey: true, defaultValue: DataTypes.UUIDV4 },
|
||||
feedId: { type: DataTypes.UUID },
|
||||
siteUrl: { type: DataTypes.STRING },
|
||||
enclosureUrl: { type: DataTypes.STRING }
|
||||
})
|
||||
|
||||
return { Feeds, FeedEpisodes }
|
||||
}
|
||||
|
||||
describe('Migration v2.17.4-use-subfolder-for-oidc-redirect-uris', () => {
|
||||
let queryInterface, logger, context
|
||||
let sequelize
|
||||
let Feeds, FeedEpisodes
|
||||
const feed1Id = '00000000-0000-4000-a000-000000000001'
|
||||
const feed2Id = '00000000-0000-4000-a000-000000000002'
|
||||
const feedEpisode1Id = '00000000-4000-a000-0000-000000000011'
|
||||
const feedEpisode2Id = '00000000-4000-a000-0000-000000000012'
|
||||
const feedEpisode3Id = '00000000-4000-a000-0000-000000000021'
|
||||
|
||||
before(async () => {
|
||||
sequelize = new Sequelize({ dialect: 'sqlite', storage: ':memory:', logging: false })
|
||||
queryInterface = sequelize.getQueryInterface()
|
||||
;({ Feeds, FeedEpisodes } = defineModels(sequelize))
|
||||
await sequelize.sync()
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
await sequelize.close()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
// Reset tables before each test
|
||||
await Feeds.destroy({ where: {}, truncate: true })
|
||||
await FeedEpisodes.destroy({ where: {}, truncate: true })
|
||||
|
||||
logger = {
|
||||
info: sinon.stub(),
|
||||
error: sinon.stub()
|
||||
}
|
||||
context = { queryInterface, logger }
|
||||
})
|
||||
|
||||
describe('up', () => {
|
||||
it('should remove serverAddress from URLs in Feeds and FeedEpisodes tables', async () => {
|
||||
await Feeds.bulkCreate([
|
||||
{ id: feed1Id, feedUrl: 'http://server1.com/feed1', imageUrl: 'http://server1.com/img1', siteUrl: 'http://server1.com/site1', serverAddress: 'http://server1.com' },
|
||||
{ id: feed2Id, feedUrl: 'http://server2.com/feed2', imageUrl: 'http://server2.com/img2', siteUrl: 'http://server2.com/site2', serverAddress: 'http://server2.com' }
|
||||
])
|
||||
|
||||
await FeedEpisodes.bulkCreate([
|
||||
{ id: feedEpisode1Id, feedId: feed1Id, siteUrl: 'http://server1.com/episode11', enclosureUrl: 'http://server1.com/enclosure11' },
|
||||
{ id: feedEpisode2Id, feedId: feed1Id, siteUrl: 'http://server1.com/episode12', enclosureUrl: 'http://server1.com/enclosure12' },
|
||||
{ id: feedEpisode3Id, feedId: feed2Id, siteUrl: 'http://server2.com/episode21', enclosureUrl: 'http://server2.com/enclosure21' }
|
||||
])
|
||||
|
||||
await up({ context })
|
||||
const feeds = await Feeds.findAll({ raw: true })
|
||||
const feedEpisodes = await FeedEpisodes.findAll({ raw: true })
|
||||
|
||||
expect(logger.info.calledWith('[2.17.5 migration] UPGRADE BEGIN: 2.17.5-remove-host-from-feed-urls')).to.be.true
|
||||
expect(logger.info.calledWith('[2.17.5 migration] Removing serverAddress from Feeds table URLs')).to.be.true
|
||||
|
||||
expect(feeds[0].feedUrl).to.equal('/feed1')
|
||||
expect(feeds[0].imageUrl).to.equal('/img1')
|
||||
expect(feeds[0].siteUrl).to.equal('/site1')
|
||||
expect(feeds[1].feedUrl).to.equal('/feed2')
|
||||
expect(feeds[1].imageUrl).to.equal('/img2')
|
||||
expect(feeds[1].siteUrl).to.equal('/site2')
|
||||
|
||||
expect(logger.info.calledWith('[2.17.5 migration] Removed serverAddress from Feeds table URLs')).to.be.true
|
||||
expect(logger.info.calledWith('[2.17.5 migration] Removing serverAddress from FeedEpisodes table URLs')).to.be.true
|
||||
|
||||
expect(feedEpisodes[0].siteUrl).to.equal('/episode11')
|
||||
expect(feedEpisodes[0].enclosureUrl).to.equal('/enclosure11')
|
||||
expect(feedEpisodes[1].siteUrl).to.equal('/episode12')
|
||||
expect(feedEpisodes[1].enclosureUrl).to.equal('/enclosure12')
|
||||
expect(feedEpisodes[2].siteUrl).to.equal('/episode21')
|
||||
expect(feedEpisodes[2].enclosureUrl).to.equal('/enclosure21')
|
||||
|
||||
expect(logger.info.calledWith('[2.17.5 migration] Removed serverAddress from FeedEpisodes table URLs')).to.be.true
|
||||
expect(logger.info.calledWith('[2.17.5 migration] UPGRADE END: 2.17.5-remove-host-from-feed-urls')).to.be.true
|
||||
})
|
||||
|
||||
it('should handle null URLs in Feeds and FeedEpisodes tables', async () => {
|
||||
await Feeds.bulkCreate([{ id: feed1Id, feedUrl: 'http://server1.com/feed1', imageUrl: null, siteUrl: 'http://server1.com/site1', serverAddress: 'http://server1.com' }])
|
||||
|
||||
await FeedEpisodes.bulkCreate([{ id: feedEpisode1Id, feedId: feed1Id, siteUrl: null, enclosureUrl: 'http://server1.com/enclosure11' }])
|
||||
|
||||
await up({ context })
|
||||
const feeds = await Feeds.findAll({ raw: true })
|
||||
const feedEpisodes = await FeedEpisodes.findAll({ raw: true })
|
||||
|
||||
expect(feeds[0].feedUrl).to.equal('/feed1')
|
||||
expect(feeds[0].imageUrl).to.be.null
|
||||
expect(feeds[0].siteUrl).to.equal('/site1')
|
||||
expect(feedEpisodes[0].siteUrl).to.be.null
|
||||
expect(feedEpisodes[0].enclosureUrl).to.equal('/enclosure11')
|
||||
})
|
||||
|
||||
it('should handle null serverAddress in Feeds table', async () => {
|
||||
await Feeds.bulkCreate([{ id: feed1Id, feedUrl: 'http://server1.com/feed1', imageUrl: 'http://server1.com/img1', siteUrl: 'http://server1.com/site1', serverAddress: null }])
|
||||
await FeedEpisodes.bulkCreate([{ id: feedEpisode1Id, feedId: feed1Id, siteUrl: 'http://server1.com/episode11', enclosureUrl: 'http://server1.com/enclosure11' }])
|
||||
|
||||
await up({ context })
|
||||
const feeds = await Feeds.findAll({ raw: true })
|
||||
const feedEpisodes = await FeedEpisodes.findAll({ raw: true })
|
||||
|
||||
expect(feeds[0].feedUrl).to.equal('http://server1.com/feed1')
|
||||
expect(feeds[0].imageUrl).to.equal('http://server1.com/img1')
|
||||
expect(feeds[0].siteUrl).to.equal('http://server1.com/site1')
|
||||
expect(feedEpisodes[0].siteUrl).to.equal('http://server1.com/episode11')
|
||||
expect(feedEpisodes[0].enclosureUrl).to.equal('http://server1.com/enclosure11')
|
||||
})
|
||||
})
|
||||
|
||||
describe('down', () => {
|
||||
it('should add serverAddress back to URLs in Feeds and FeedEpisodes tables', async () => {
|
||||
await Feeds.bulkCreate([
|
||||
{ id: feed1Id, feedUrl: '/feed1', imageUrl: '/img1', siteUrl: '/site1', serverAddress: 'http://server1.com' },
|
||||
{ id: feed2Id, feedUrl: '/feed2', imageUrl: '/img2', siteUrl: '/site2', serverAddress: 'http://server2.com' }
|
||||
])
|
||||
|
||||
await FeedEpisodes.bulkCreate([
|
||||
{ id: feedEpisode1Id, feedId: feed1Id, siteUrl: '/episode11', enclosureUrl: '/enclosure11' },
|
||||
{ id: feedEpisode2Id, feedId: feed1Id, siteUrl: '/episode12', enclosureUrl: '/enclosure12' },
|
||||
{ id: feedEpisode3Id, feedId: feed2Id, siteUrl: '/episode21', enclosureUrl: '/enclosure21' }
|
||||
])
|
||||
|
||||
await down({ context })
|
||||
const feeds = await Feeds.findAll({ raw: true })
|
||||
const feedEpisodes = await FeedEpisodes.findAll({ raw: true })
|
||||
|
||||
expect(logger.info.calledWith('[2.17.5 migration] DOWNGRADE BEGIN: 2.17.5-remove-host-from-feed-urls')).to.be.true
|
||||
expect(logger.info.calledWith('[2.17.5 migration] Adding serverAddress back to Feeds table URLs')).to.be.true
|
||||
|
||||
expect(feeds[0].feedUrl).to.equal('http://server1.com/feed1')
|
||||
expect(feeds[0].imageUrl).to.equal('http://server1.com/img1')
|
||||
expect(feeds[0].siteUrl).to.equal('http://server1.com/site1')
|
||||
expect(feeds[1].feedUrl).to.equal('http://server2.com/feed2')
|
||||
expect(feeds[1].imageUrl).to.equal('http://server2.com/img2')
|
||||
expect(feeds[1].siteUrl).to.equal('http://server2.com/site2')
|
||||
|
||||
expect(logger.info.calledWith('[2.17.5 migration] Added serverAddress back to Feeds table URLs')).to.be.true
|
||||
expect(logger.info.calledWith('[2.17.5 migration] Adding serverAddress back to FeedEpisodes table URLs')).to.be.true
|
||||
|
||||
expect(feedEpisodes[0].siteUrl).to.equal('http://server1.com/episode11')
|
||||
expect(feedEpisodes[0].enclosureUrl).to.equal('http://server1.com/enclosure11')
|
||||
expect(feedEpisodes[1].siteUrl).to.equal('http://server1.com/episode12')
|
||||
expect(feedEpisodes[1].enclosureUrl).to.equal('http://server1.com/enclosure12')
|
||||
expect(feedEpisodes[2].siteUrl).to.equal('http://server2.com/episode21')
|
||||
expect(feedEpisodes[2].enclosureUrl).to.equal('http://server2.com/enclosure21')
|
||||
|
||||
expect(logger.info.calledWith('[2.17.5 migration] DOWNGRADE END: 2.17.5-remove-host-from-feed-urls')).to.be.true
|
||||
})
|
||||
|
||||
it('should handle null URLs in Feeds and FeedEpisodes tables', async () => {
|
||||
await Feeds.bulkCreate([{ id: feed1Id, feedUrl: '/feed1', imageUrl: null, siteUrl: '/site1', serverAddress: 'http://server1.com' }])
|
||||
await FeedEpisodes.bulkCreate([{ id: feedEpisode1Id, feedId: feed1Id, siteUrl: null, enclosureUrl: '/enclosure11' }])
|
||||
|
||||
await down({ context })
|
||||
const feeds = await Feeds.findAll({ raw: true })
|
||||
const feedEpisodes = await FeedEpisodes.findAll({ raw: true })
|
||||
|
||||
expect(feeds[0].feedUrl).to.equal('http://server1.com/feed1')
|
||||
expect(feeds[0].imageUrl).to.be.null
|
||||
expect(feeds[0].siteUrl).to.equal('http://server1.com/site1')
|
||||
expect(feedEpisodes[0].siteUrl).to.be.null
|
||||
expect(feedEpisodes[0].enclosureUrl).to.equal('http://server1.com/enclosure11')
|
||||
})
|
||||
|
||||
it('should handle null serverAddress in Feeds table', async () => {
|
||||
await Feeds.bulkCreate([{ id: feed1Id, feedUrl: '/feed1', imageUrl: '/img1', siteUrl: '/site1', serverAddress: null }])
|
||||
await FeedEpisodes.bulkCreate([{ id: feedEpisode1Id, feedId: feed1Id, siteUrl: '/episode11', enclosureUrl: '/enclosure11' }])
|
||||
|
||||
await down({ context })
|
||||
const feeds = await Feeds.findAll({ raw: true })
|
||||
const feedEpisodes = await FeedEpisodes.findAll({ raw: true })
|
||||
|
||||
expect(feeds[0].feedUrl).to.equal('/feed1')
|
||||
expect(feeds[0].imageUrl).to.equal('/img1')
|
||||
expect(feeds[0].siteUrl).to.equal('/site1')
|
||||
expect(feedEpisodes[0].siteUrl).to.equal('/episode11')
|
||||
expect(feedEpisodes[0].enclosureUrl).to.equal('/enclosure11')
|
||||
})
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue
Block a user