Skip to content

Instantly share code, notes, and snippets.

@ment4list
Last active April 2, 2024 16:49
Show Gist options
  • Save ment4list/4571644f7b49c1ae72c4ac1ec5ce9c91 to your computer and use it in GitHub Desktop.
Save ment4list/4571644f7b49c1ae72c4ac1ec5ce9c91 to your computer and use it in GitHub Desktop.
Omnivore Articles to ePub via ScriptKit script
// Name: Send to Kindle - Omnivore
// This is a script meant to be added to [ScriptKit](https://www.scriptkit.com/) to add your Omnivore articles as an epub.
// Email is sent via AppleScript
import "@johnlindquist/kit"
// Source: https://github.com/agrmohit/omnivore-epub/blob/main/main.ts
import epub from "epub-gen-memory";
import { gql, GraphQLClient } from "graphql-request";
import sanitizeHtml from "sanitize-html";
const config = {
"endpoint": "https://api-prod.omnivore.app/api/graphql",
"title": "Omnivore Articles",
"author": "Omnivore",
"cover": "https://cdn.discordapp.com/attachments/779248028824764426/1149996974234423346/cover.jpg",
"description": "Articles from Omnivore",
"addLabelsInContent": false,
"addArticleLinkInContent": true,
"allowImages": true,
"outputFileName": "output.epub",
"maxArticleCount": 5, //,100 // itemsToFetch
"ignoredLabels": ["pdf"],
"ignoredLinks": ["https://www.youtu", "https://youtu"],
};
const currentVersion = "v0.2.0";
console.log(`ℹ Omnivore EPUB ${currentVersion}`);
console.log("ℹ️ Homepage: https://github.com/agrmohit/omnivore-epub");
const OMNIVORE_API_KEY = await env("OMNIVORE_API_KEY");
const OMNIVORE_ENDPOINT = config.endpoint;
const KINDLE_EMAIL_ADDRESS = await env("KINDLE_EMAIL_ADDRESS");
if (!OMNIVORE_API_KEY) {
console.log("❌ Omnivore API token not set");
console.log(
"❌ Get a token following instructions on: https://docs.omnivore.app/integrations/api.html#getting-an-api-token",
);
console.log("❌ When you have a token, insert it as value for 'token' field in 'config.json' file");
// Deno.exit(1);
}
const graphQLClient = new GraphQLClient(OMNIVORE_ENDPOINT, {
headers: {
authorization: OMNIVORE_API_KEY,
},
});
async function checkForUpdates() {
const response = await fetch("https://api.github.com/repos/agrmohit/omnivore-epub/tags");
const tags = await response.json();
if (tags[0].name !== currentVersion) {
console.log("ℹ New update available");
console.log(`ℹ ${currentVersion} --> ${tags[0].name}`);
}
}
async function getUnreadArticles() {
const query = gql`
{
search(first: ${config.maxArticleCount}) {
... on SearchSuccess {
edges {
cursor
node {
title
slug
description
url
savedAt
language
subscription
isArchived
author
labels {
name
}
}
}
}
}
}
`;
var Label = {
name: ''
};
var Edge = {
cursor: '',
node: {
title: '',
slug: '',
url: '',
savedAt: '',
language: '',
subscription: '',
isArchived: false,
author: '',
labels: [],
labelsArray: [],
}
};
const data = await graphQLClient.request(
query,
);
return data.search.edges.map((e) => {
if (e.node.labels) {
e.node.labelsArray = e.node.labels.map((label) => label.name);
}
return e.node;
});
}
async function getArticle(slug) {
// console.log(' getArticle() with slug' + slug )
const query = gql`{
article (username: "anonymous", slug: "${slug}") {
... on ArticleSuccess {
article {
id, slug, url, content
}
}
}
}`;
const data = await graphQLClient.request(query)
let allowedTags;
if (config.allowImages) {
allowedTags = sanitizeHtml.defaults.allowedTags.concat(["img"]);
} else {
allowedTags = sanitizeHtml.defaults.allowedTags.concat();
}
if(!data) {
return {
title: 'None..',
content: ''
}
}
const sanitizedArticle = sanitizeHtml(data.article.article.content, {
allowedTags: allowedTags,
});
return {
...data.article.article,
content: sanitizedArticle,
};
}
async function makeMagazine() {
console.log("〰️ getting article list");
const articles = await getUnreadArticles();
console.log("🤖 done");
const chapters = [];
for (const article of articles) {
if (!article.isArchived) {
console.log(`🌐 fetching ${article.title}`);
let content = (await getArticle(article.slug)).content;
if (article.labelsArray) {
if (
config.ignoredLinks.some((url) => article.url.includes(url))
|| article.labelsArray.find((label) => config.ignoredLabels.includes(label))
) {
console.log("⚠️ article skipped");
continue;
}
if (config.addLabelsInContent) {
content = `<b>Labels: ${article.labelsArray.join(", ")}</b>` + content;
}
}
if (config.addArticleLinkInContent) {
content = `<a href="${article.url}">Link to Article</a><br><br>` + content;
}
chapters.push({
title: article.title,
author: article.author ?? "Omnivore",
content: content,
filename: article.slug,
});
console.log(`✅ done`);
}
}
console.log('Done fetching content for articles... Writing ePub file... Please wait.')
const fileBuffer = await epub.default(
{
title: config.title,
author: config.author,
cover: config.cover,
description: config.description,
ignoreFailedDownloads: true,
},
chapters,
);
console.log("📚 Successfully created ebook");
await writeFile(home('Downloads/output.epub'), fileBuffer)
// Send email via applescript
await applescript(`
-- Set your email details
set recipientAddress to "${KINDLE_EMAIL_ADDRESS}"
set emailSubject to "Omnivore Latest Articles for ${dateAsStr()}"
set emailBody to "Please see your epub attached"
-- Path to the file you want to attach
set attachmentPath to "${outputPath}"
-- Create a new outgoing message
tell application "Mail"
set newMessage to make new outgoing message with properties {subject:emailSubject, content:emailBody, visible:true}
-- Set the recipient
tell newMessage
make new to recipient with properties {address:recipientAddress}
-- Attach the file
make new attachment with properties {file name:attachmentPath} at after the last paragraph
end tell
-- Send the message
send newMessage
end tell
`);
}
await checkForUpdates();
await makeMagazine();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment