accept opds publication only for publish

pull/46/head
unknown 2019-03-14 12:25:32 -04:00
parent 962aa0acb6
commit c5d05eb89c
3 changed files with 49 additions and 53 deletions

View File

@ -6,7 +6,7 @@
*/ */
const HttpError = require('../errors/HttpError') const HttpError = require('../errors/HttpError')
const { asyncRead, hmacSign } = require('../util') const { hmacSign } = require('../util')
const request = require('request') const request = require('request')
const uriRegex = /^(.+:\/\/)?(.+\.)*(.+\.).{1,}(:\d+)?(.+)?/i const uriRegex = /^(.+:\/\/)?(.+\.)*(.+\.).{1,}(:\d+)?(.+)?/i
@ -19,37 +19,37 @@ module.exports = {
if (!host) throw new HttpError(400, 'Missing hostname') if (!host) throw new HttpError(400, 'Missing hostname')
if (!body) throw new HttpError(400, 'Missing body') if (!body) throw new HttpError(400, 'Missing body')
if (!body.metadata) throw new HttpError(400, 'Missing OPDS metadata')
if (!body.metadata['@type'] || body.metadata['@type'] !== 'http://schema.org/Book') throw new HttpError(400, 'Invalid \'@type\': expected \'http://schema.org/Book\'')
const bookExists = await Book.findOne(body) const query = {
source: host,
title: body.metadata.title,
author: body.metadata.author,
publisher: body.metadata.publisher,
identifier: body.metadata.identifier,
version: body.metadata.modified.replace(/\D/g, '')
}
const bookExists = await Book.findOne(query)
if (bookExists) { if (bookExists) {
throw new HttpError(400, 'Version already exists') throw new HttpError(400, 'Ebook already exists')
} else { } else {
const { title, isbn, author, publisher } = body const { publisher, title, author, identifier } = body.metadata
// require at least 2 fields to be filled out // require at least 3 fields to be filled out
if ([title, isbn, author, publisher].reduce((a, x) => a + (x ? 1 : 0), 0) >= 2) { if ([title, identifier, author, publisher].reduce((a, x) => a + (x ? 1 : 0), 0) >= 3) {
result = await Book.create(body).fetch() result = await Book.create({
...query,
opds: body
}).fetch()
} else { } else {
throw new HttpError(400, 'Please fill out at least 2 fields (title, author, publisher, isbn)') throw new HttpError(400, 'Please fill out at least 3 opds metadata fields (title, author, publisher, identifier)')
} }
} }
if (req.file('opds')) { sendUpdatesAsync(result)
req.file('opds').upload(sails.config.skipperConfig, async function (err, uploaded) { return res.json(result)
if (err) {
await Book.destroy({ id: result.id })
throw new HttpError(500, err.message)
}
const fd = (uploaded[0] || {}).fd
await Book.update({ id: result.id }, { storage: fd })
sendUpdatesAsync(result.id)
return res.json({
...result
})
})
} else {
throw new HttpError(400, 'Missing OPDS file upload')
}
} catch (e) { } catch (e) {
if (e instanceof HttpError) return e.send(res) if (e instanceof HttpError) return e.send(res)
return res.status(500).json({ return res.status(500).json({
@ -59,16 +59,16 @@ module.exports = {
} }
} }
async function sendUpdatesAsync (id) { async function sendUpdatesAsync (book) {
const book = await Book.findOne({ id }) const id = book.id
const targets = await TargetUrl.find() const targets = await TargetUrl.find()
if (!book) return if (!book) return
for (const i in targets) { for (const i in targets) {
try { try {
const item = targets[i] const item = targets[i]
const user = await User.findOne({ id: item.user }) const user = await User.findOne({ id: item.user })
const { author: fAuthor, publisher: fPublisher, title: fTitle, isbn: fIsbn, url } = item const { author: fAuthor, publisher: fPublisher, title: fTitle, identifier: fIsbn, url } = item
const { author: bAuthor, publisher: bPublisher, title: bTitle, isbn: bIsbn } = book const { author: bAuthor, publisher: bPublisher, title: bTitle, identifier: bIsbn, opds } = book
sails.log('sending ' + book.id + ' info to ' + url) sails.log('sending ' + book.id + ' info to ' + url)
if (uriRegex.test(url)) { if (uriRegex.test(url)) {
@ -77,17 +77,7 @@ async function sendUpdatesAsync (id) {
if (fTitle && !((bTitle || '').includes(fTitle))) continue if (fTitle && !((bTitle || '').includes(fTitle))) continue
if (fIsbn && !((bIsbn || '').includes(fIsbn))) continue if (fIsbn && !((bIsbn || '').includes(fIsbn))) continue
let content let content = opds
const skipperConfig = sails.config.skipperConfig
const adapterConfig = { ...skipperConfig, adapter: undefined }
const skipperAdapter = skipperConfig.adapter(adapterConfig)
const opdsHelper = await sails.helpers.opds()
try {
if (!book.storage.length) throw new Error('missing book opds file')
content = await asyncRead(skipperAdapter, opdsHelper, book.storage)
} catch (e) {
content = await opdsHelper.book2opds(book)
}
const timestamp = Date.now() const timestamp = Date.now()
request.post({ request.post({
url: url, url: url,

View File

@ -1,5 +1,4 @@
const HttpError = require('../errors/HttpError') const HttpError = require('../errors/HttpError')
const { asyncRead } = require('../util')
module.exports = { module.exports = {
navigation: async function (req, res) { navigation: async function (req, res) {
@ -49,19 +48,7 @@ module.exports = {
throw new HttpError(404, 'No books matching those parameters were found.') throw new HttpError(404, 'No books matching those parameters were found.')
} }
const skipperConfig = sails.config.skipperConfig books = books.map(b => b.opds)
const adapterConfig = { ...skipperConfig, adapter: undefined }
const skipperAdapter = skipperConfig.adapter(adapterConfig)
const opdsHelper = await sails.helpers.opds()
books = await Promise.all(books.map(book => {
try {
if (!book.storage.length) throw new Error('missing book opds file')
return asyncRead(skipperAdapter, opdsHelper, book.storage)
} catch (e) {
return opdsHelper.book2opds(book)
}
}))
return res.json({ return res.json({
metadata: { metadata: {

View File

@ -0,0 +1,19 @@
exports.up = function (knex, Promise) {
return Promise.all([
knex.schema.table('book', t => {
t.json('opds')
t.renameColumn('isbn', 'identifier')
t.dropColumns('storage')
})
])
}
exports.down = function (knex, Promise) {
return Promise.all([
knex.schema.table('book', t => {
t.dropColumns('opds')
t.renameColumn('identifier', 'isbn')
t.string('storage')
})
])
}