Skip to content

Instantly share code, notes, and snippets.

@kebot
Last active October 25, 2023 07:55
Show Gist options
  • Save kebot/90de9c41742cacf371368d85870c4a75 to your computer and use it in GitHub Desktop.
Save kebot/90de9c41742cacf371368d85870c4a75 to your computer and use it in GitHub Desktop.
Generate Epub for Omnivore Articles (new version see here -> https://github.com/agrmohit/omnivore-epub )
// get a list of articles based on search endpoint
import { gql, GraphQLClient } from 'npm:graphql-request'
import sanitizeHtml from 'npm:sanitize-html'
import epub, { Chapter } from 'npm:epub-gen-memory'
const OMNIVORE_API_KEY = ''
const OMNIVORE_ENDPOINT = 'https://api-prod.omnivore.app/api/graphql'
const graphQLClient = new GraphQLClient(OMNIVORE_ENDPOINT, {
headers: {
authorization: OMNIVORE_API_KEY
}
})
async function getUnreadArticles () {
const query = gql`
{
articles {
... on ArticlesSuccess {
edges {
cursor,
node {
title
slug
description
url
savedAt
language
subscription
isArchived
author
}
}
}
}
}
`
type Edge = {
cursor: string,
node: {
title: string,
slug: string,
url: string
savedAt: string
language: string
subscription: string
isArchived: boolean
author: string
}
}
const data = await graphQLClient.request<{articles: { edges: Edge[] }}>(query)
return data.articles.edges.map(e => e.node)
}
async function getArticle (slug: string) {
const query = gql`{
article (username: "K.Y.", slug: "${slug}") {
... on ArticleSuccess {
article {
id, slug, url, content
}
}
}
}`
const data = await graphQLClient.request<{
article: {
article: {
id: string,
slug: string,
url: string,
content: string
}
}
}>(query)
const sanitizedArticle = sanitizeHtml(data.article.article.content)
return {
...data.article.article,
content: sanitizedArticle
}
}
// mark sended
async function makeMagazine () {
console.log('〰️ getting article list')
const articles = await getUnreadArticles()
console.log('🤖 done')
const chapters: Chapter[] = []
for (const article of articles) {
if (!article.isArchived) {
console.log(`fetching ${article.title}`)
const content = (await getArticle(article.slug)).content
chapters.push({
title: article.title,
author: article.author,
content,
url: article.url
})
console.log(`✅ done`)
}
}
// make a PDF and save it
const fileBuffer = await epub.default({
title: 'Test Articles',
author: 'Omnivore',
// cover: article.image,
}, chapters)
await Deno.writeFile('./output.epub', fileBuffer)
console.log('📚 Success')
}
await makeMagazine()
Deno.exit()
@shombando
Copy link

@kebot I added a tiny bit of error checking on chapters since it failed on one of my articles: https://gist.github.com/shombando/87a58583f02bb543b0a98bb24f813039/revisions?diff=unified

Thanks for making this excellent and concise script.

@agrmohit
Copy link

There has been a change in omnivore api which results in this script breaking. I have a fixed version with a few more changes here

@kebot
Copy link
Author

kebot commented Oct 25, 2023

nice, let's use https://github.com/agrmohit/omnivore-epub for future update of this project

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment