mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
Add support for every.io newsletter
This commit is contained in:
parent
363489f5be
commit
b6c41b9c73
5 changed files with 233 additions and 4 deletions
|
|
@ -121,12 +121,17 @@ export abstract class ContentHandler {
|
|||
headers: Record<string, string | string[]>,
|
||||
html: string
|
||||
): Promise<string | undefined> {
|
||||
// get url from dom
|
||||
const url = await this.findNewsletterUrl(html)
|
||||
if (url) {
|
||||
return url
|
||||
}
|
||||
// get newsletter url from html
|
||||
const matches = html.match(this.urlRegex)
|
||||
if (matches) {
|
||||
return Promise.resolve(matches[1])
|
||||
return matches[1]
|
||||
}
|
||||
return Promise.resolve(undefined)
|
||||
return undefined
|
||||
}
|
||||
|
||||
parseAuthor(from: string): string {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import { HeyWorldHandler } from './newsletters/hey-world-handler'
|
|||
import { Browser } from 'puppeteer-core'
|
||||
import { StackOverflowHandler } from './websites/stack-overflow-handler'
|
||||
import { GenericHandler } from './newsletters/generic-handler'
|
||||
import { EveryIoHandler } from './newsletters/every-io-handler'
|
||||
|
||||
const validateUrlString = (url: string) => {
|
||||
const u = new URL(url)
|
||||
|
|
@ -82,6 +83,7 @@ const newsletterHandlers: ContentHandler[] = [
|
|||
new CooperPressHandler(),
|
||||
new HeyWorldHandler(),
|
||||
new GenericHandler(),
|
||||
new EveryIoHandler(),
|
||||
]
|
||||
|
||||
export const preHandleContent = async (
|
||||
|
|
|
|||
22
packages/content-handler/src/newsletters/every-io-handler.ts
Normal file
22
packages/content-handler/src/newsletters/every-io-handler.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import { ContentHandler } from '../content-handler'
|
||||
|
||||
export class EveryIoHandler extends ContentHandler {
|
||||
constructor() {
|
||||
super()
|
||||
this.name = 'Every.io'
|
||||
}
|
||||
|
||||
async isNewsletter(input: {
|
||||
from: string
|
||||
html: string
|
||||
headers: Record<string, string | string[]>
|
||||
dom: Document
|
||||
}): Promise<boolean> {
|
||||
return Promise.resolve(input.from === 'Every <hello@every.to>')
|
||||
}
|
||||
|
||||
findNewsletterHeaderHref(dom: Document): string | undefined {
|
||||
const readOnline = dom.querySelector('.newsletter-email .title a')
|
||||
return readOnline?.getAttribute('href') || undefined
|
||||
}
|
||||
}
|
||||
163
packages/content-handler/test/data/every-io-newsletter.html
Normal file
163
packages/content-handler/test/data/every-io-newsletter.html
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -19,6 +19,7 @@ import { getNewsletterHandler } from '../src'
|
|||
import { parseHTML } from 'linkedom'
|
||||
import { HeyWorldHandler } from '../src/newsletters/hey-world-handler'
|
||||
import { GenericHandler } from '../src/newsletters/generic-handler'
|
||||
import { EveryIoHandler } from '../src/newsletters/every-io-handler'
|
||||
|
||||
chai.use(chaiAsPromised)
|
||||
chai.use(chaiString)
|
||||
|
|
@ -102,6 +103,32 @@ describe('Newsletter email test', () => {
|
|||
).to.eventually.equal(url)
|
||||
})
|
||||
})
|
||||
|
||||
context('when email is from Every.io', () => {
|
||||
before(() => {
|
||||
nock('https://u25184427.ct.sendgrid.net')
|
||||
.head(
|
||||
'/ls/click?upn=MnmHBiCwIPe9TmIJeskmAzMyFAOgfmWxTSMhUO2y3cX7SH8TU8fE7Bob959Q5SX8kPrOyAS87mVlVX7RClBX5O3kASzJW2uCz02hYzOF2YQ0jOrkqrBElBIkfeLl7ZERdDGVCD8VSijl4E0Tqgyrzl2vhAQyRsnJuYNo38k-2FROTfvWd85434dJ5Ajc284NO0JH4cM9g-2BdWlh0bID30oroznIHSP8Lg4qTxIVRNMq8zYyOtmR3fanZTexF5IrLPDqQMXmm0Wz0QK23ojkpC8yL3gexm2dDFZNOtKvgYlprJoR6QhevN9bulX1wI8ht5dtNccOAcexw3K4a3WMuoJp4thIKz0hIzOup38HTJPLtjRojXWKOyRBqE-2FdX17d4wY3lSqAN80IHqCic3WUBTenbU6Uo0Qi0FEVj0Iar7TuplOEENppNCZVJ5vpWMlMmQ8Wio7L_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyAZZ0kujTWt86aLf2utm1bD-2FSj2DcbTCh3O3HD32SBIzeJdlXzKUs-2FRqjzbupd0J1Y8z5xnvQV5k1D5zyWOAHSxLv0Ezts-2FF2V2Y974g-2FABq5B151S2LbhNv8zTY6syz-2B1z-2BrGm8iNYGAPN1C9KbPpr0x08ptebSaNu86Stmdovg-3D-3D'
|
||||
)
|
||||
.reply(301, undefined, {
|
||||
Location:
|
||||
'https://every.to/divinations/the-endgame-for-ai-generated-writing',
|
||||
})
|
||||
nock('https://every.to/divinations')
|
||||
.head('/the-endgame-for-ai-generated-writing')
|
||||
.reply(200, '')
|
||||
})
|
||||
|
||||
it('returns url when email is from Every.io', async () => {
|
||||
const url =
|
||||
'https://every.to/divinations/the-endgame-for-ai-generated-writing'
|
||||
const html = load('./test/data/every-io-newsletter.html')
|
||||
|
||||
await expect(
|
||||
new EveryIoHandler().parseNewsletterUrl({}, html)
|
||||
).to.eventually.equal(url)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('get author from email address', () => {
|
||||
|
|
@ -267,7 +294,7 @@ describe('Newsletter email test', () => {
|
|||
expect(handler).to.be.undefined
|
||||
})
|
||||
|
||||
it('returns ContentHandler for TTSO newsletter', async () => {
|
||||
it('returns GenericHandler for TTSO newsletter', async () => {
|
||||
const html = load('./test/data/ttso-newsletter.html')
|
||||
const handler = await getNewsletterHandler({
|
||||
html,
|
||||
|
|
@ -278,7 +305,17 @@ describe('Newsletter email test', () => {
|
|||
'<mailto:unsub-e86467ca.k5yx.x15515@bnc3.mailjet.com>, <https://k5yx.mjt.lu/unsub2?m=AAAAADHYIIAActfCvIAALdDY50AAAAAtZ4AAC8UAAk9yQBj2U4KUkToWXqgR9OqHSm_LHvyrQAIwzU&b=e86467ca&e=7132d286&x=FUkLKVFH4r_0f--3tAm2RPnjzf5a0IVmKjTWv1nE-GAaJXzXvZHIKiojmrtWYhDE>',
|
||||
},
|
||||
})
|
||||
expect(handler).to.be.instanceOf(ContentHandler)
|
||||
expect(handler).to.be.instanceOf(GenericHandler)
|
||||
})
|
||||
|
||||
it('returns EveryIoHandler for every.io newsletter', async () => {
|
||||
const html = load('./test/data/every-io-newsletter.html')
|
||||
const handler = await getNewsletterHandler({
|
||||
html,
|
||||
from: 'Every <hello@every.to>',
|
||||
headers: {},
|
||||
})
|
||||
expect(handler).to.be.instanceOf(EveryIoHandler)
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue