fix newsletters test

This commit is contained in:
Hongbo Wu
2023-09-12 22:42:49 +09:00
parent c3caf15e44
commit cbaa3d6900
8 changed files with 64 additions and 59 deletions

View File

@ -19,7 +19,7 @@ export class Integration {
@PrimaryGeneratedColumn('uuid')
id!: string
@ManyToOne(() => User, { onDelete: 'CASCADE' })
@ManyToOne(() => User, { onDelete: 'CASCADE', eager: true })
@JoinColumn({ name: 'user_id' })
user!: User

View File

@ -102,7 +102,7 @@ export const markEmailAsItemResolver = authorized<
}
// update received email type
await updateReceivedEmail(recentEmail.id, 'article')
await updateReceivedEmail(recentEmail.id, 'article', uid)
const text = `A recent email marked as a library item
by: ${uid}

View File

@ -103,27 +103,24 @@ export function integrationsServiceRouter() {
res.status(200).send('Bad Request')
return
}
const page = await findLibraryItemById(id, userId)
if (!page) {
logger.info('No page found for id', { id })
const item = await findLibraryItemById(id, userId)
if (!item) {
logger.info('No item found for id', { id })
res.status(200).send('No page found')
return
}
if (page.user.id !== userId) {
logger.info('Page does not belong to user', { id, userId })
return res.status(200).send('Page does not belong to user')
}
// sync updated page with integration
logger.info('syncing updated page with integration', {
// sync updated item with integration
logger.info('syncing updated item with integration', {
integrationId: integration.id,
pageId: page.id,
itemId: item.id,
})
const synced = await integrationService.export(integration, [page])
const synced = await integrationService.export(integration, [item])
if (!synced) {
logger.info('failed to sync page', {
logger.info('failed to sync item', {
integrationId: integration.id,
pageId: page.id,
itemId: item.id,
})
return res.status(400).send('Failed to sync')
}
@ -135,7 +132,7 @@ export function integrationsServiceRouter() {
let hasNextPage = true,
count = 0,
after = 0,
pages: LibraryItem[] = [];
items: LibraryItem[] = [];
hasNextPage;
after += size, hasNextPage = count > after
) {
@ -148,15 +145,15 @@ export function integrationsServiceRouter() {
{ from: after, size, dateFilters },
userId
)
pages = libraryItems
const pageIds = pages.map((p) => p.id)
items = libraryItems
const itemIds = items.map((p) => p.id)
logger.info('syncing pages', { pageIds })
logger.info('syncing items', { pageIds: itemIds })
const synced = await integrationService.export(integration, pages)
const synced = await integrationService.export(integration, items)
if (!synced) {
logger.error('failed to sync pages', {
pageIds,
logger.error('failed to sync items', {
pageIds: itemIds,
integrationId: integration.id,
})
return res.status(400).send('Failed to sync')

View File

@ -1,4 +1,5 @@
import axios from 'axios'
import { updateIntegration } from '.'
import { HighlightType } from '../../entity/highlight'
import { Integration } from '../../entity/integration'
import { LibraryItem } from '../../entity/library_item'
@ -64,7 +65,7 @@ export class ReadwiseIntegration extends IntegrationService {
): Promise<boolean> => {
let result = true
const highlights = items.flatMap(this.pageToReadwiseHighlight)
const highlights = items.flatMap(this.libraryItemToReadwiseHighlight)
// If there are no highlights, we will skip the sync
if (highlights.length > 0) {
result = await this.syncWithReadwise(integration.token, highlights)
@ -73,16 +74,18 @@ export class ReadwiseIntegration extends IntegrationService {
// update integration syncedAt if successful
if (result) {
logger.info('updating integration syncedAt')
await authTrx((t) =>
t.getRepository(Integration).update(integration.id, {
await updateIntegration(
integration.id,
{
syncedAt: new Date(),
})
},
integration.user.id
)
}
return result
}
pageToReadwiseHighlight = (item: LibraryItem): ReadwiseHighlight[] => {
libraryItemToReadwiseHighlight = (item: LibraryItem): ReadwiseHighlight[] => {
if (!item.highlights) return []
const category = item.siteName === 'Twitter' ? 'tweets' : 'articles'
return item.highlights
@ -128,7 +131,7 @@ export class ReadwiseIntegration extends IntegrationService {
{
headers: {
Authorization: `Token ${token}`,
ContentType: 'application/json',
'Content-Type': 'application/json',
},
timeout: 5000, // 5 seconds
}

View File

@ -91,23 +91,27 @@ export const addLabelsToLibraryItem = async (
userId: string,
pubsub = createPubSubClient()
) => {
await authTrx(async (tx) => {
const libraryItem = await tx
.withRepository(libraryItemRepository)
.findOneByOrFail({ id: libraryItemId })
await authTrx(
async (tx) => {
const libraryItem = await tx
.withRepository(libraryItemRepository)
.findOneByOrFail({ id: libraryItemId })
if (libraryItem.labels) {
labels.push(...libraryItem.labels)
}
if (libraryItem.labels) {
labels.push(...libraryItem.labels)
}
// save new labels
await tx.getRepository(EntityLabel).save(
labels.map((l) => ({
labelId: l.id,
libraryItemId,
}))
)
})
// save new labels
await tx.getRepository(EntityLabel).save(
labels.map((l) => ({
labelId: l.id,
libraryItemId,
}))
)
},
undefined,
userId
)
// create pubsub event
await pubsub.entityCreated<(Label & { pageId: string })[]>(

View File

@ -29,7 +29,7 @@ export const saveReceivedEmail = async (
export const updateReceivedEmail = async (
id: string,
type: 'article' | 'non-article',
userId?: string
userId: string
) => {
return authTrx(
(t) => t.getRepository(ReceivedEmail).update(id, { type }),

View File

@ -20,7 +20,7 @@ import {
parsePreparedContent,
parseUrlMetadata,
} from '../utils/parser'
import { findOrCreateLabels } from './labels'
import { addLabelsToLibraryItem, findOrCreateLabels } from './labels'
import {
createLibraryItem,
findLibraryItemByUrl,
@ -132,10 +132,11 @@ export const saveEmail = async (
if (newsletterLabel) {
// add newsletter label
await findOrCreateLabels([newsletterLabel], input.userId)
const labels = await findOrCreateLabels([newsletterLabel], input.userId)
await addLabelsToLibraryItem(labels, newLibraryItem.id, input.userId)
}
await updateReceivedEmail(input.receivedEmailId, 'article')
await updateReceivedEmail(input.receivedEmailId, 'article', input.userId)
// create a task to update thumbnail and pre-cache all images
try {

View File

@ -127,12 +127,12 @@ describe('Integrations routers', () => {
let integration: Integration
let item: LibraryItem
let highlight: Highlight
let highlightsData: string
let highlightsData: any
before(async () => {
integration = await saveIntegration(
{
user: { id: user.id },
user,
name: 'READWISE',
token: 'token',
},
@ -157,24 +157,24 @@ describe('Integrations routers', () => {
user.id
)
// create highlights data for integration request
highlightsData = JSON.stringify({
highlightsData = {
highlights: [
{
text: highlight.quote,
title: item.title,
author: item.author,
author: item.author ?? undefined,
highlight_url: getHighlightUrl(item.slug, highlight.id),
highlighted_at: highlight.createdAt.toISOString(),
category: 'articles',
image_url: item.thumbnail,
image_url: item.thumbnail ?? undefined,
// location: highlightPositionPercent,
location_type: 'order',
note: highlight.annotation,
note: highlight.annotation ?? undefined,
source_type: 'omnivore',
source_url: item.originalUrl,
},
],
})
}
})
after(async () => {
@ -205,7 +205,7 @@ describe('Integrations routers', () => {
nock(READWISE_API_URL, {
reqheaders: {
Authorization: `Token ${integration.token}`,
ContentType: 'application/json',
'Content-Type': 'application/json',
},
})
.post('/highlights', highlightsData)
@ -227,7 +227,7 @@ describe('Integrations routers', () => {
nock(READWISE_API_URL, {
reqheaders: {
Authorization: `Token ${integration.token}`,
ContentType: 'application/json',
'Content-Type': 'application/json',
},
})
.post('/highlights')
@ -236,7 +236,7 @@ describe('Integrations routers', () => {
nock(READWISE_API_URL, {
reqheaders: {
Authorization: `Token ${integration.token}`,
ContentType: 'application/json',
'Content-Type': 'application/json',
},
})
.post('/highlights')
@ -272,7 +272,7 @@ describe('Integrations routers', () => {
nock(READWISE_API_URL, {
reqheaders: {
Authorization: `Token ${integration.token}`,
ContentType: 'application/json',
'Content-Type': 'application/json',
},
})
.post('/highlights', highlightsData)
@ -306,7 +306,7 @@ describe('Integrations routers', () => {
nock(READWISE_API_URL, {
reqheaders: {
Authorization: `Token ${integration.token}`,
ContentType: 'application/json',
'Content-Type': 'application/json',
},
})
.post('/highlights', highlightsData)