From 0d6712df6e133a1d75e5a3dde32ce20ba0590561 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Sat, 11 May 2024 11:32:16 +0800 Subject: [PATCH] polling new content api to get highlighted content --- src/api.ts | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/src/api.ts b/src/api.ts index 1300187..541104b 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,4 +1,5 @@ import { Item, ItemFormat, Omnivore } from '@omnivore-app/api' +import { requestUrl } from 'obsidian' export enum HighlightColors { Yellow = 'yellow', @@ -7,6 +8,50 @@ export enum HighlightColors { Blue = 'blue', } +interface GetContentResponse { + data: { + libraryItemId: string + downloadUrl: string + error?: string + }[] +} + +const getContent = async ( + endpoint: string, + apiKey: string, + libraryItemIds: string[], +): Promise => { + const response = await requestUrl({ + url: `${endpoint}/api/content`, + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: apiKey, + }, + body: JSON.stringify({ libraryItemIds, format: 'highlightedMarkdown' }), + }) + + return response.json +} + +const downloadFromUrl = async (url: string): Promise => { + try { + // polling until download is ready or failed + const response = await requestUrl({ + url, + }) + return response.text + } catch (error) { + // retry after 1 second if download returns 404 + if (error.status === 404) { + await sleep(1000) + return downloadFromUrl(url) + } + + throw error + } +} + export const getItems = async ( endpoint: string, apiKey: string, @@ -27,11 +72,40 @@ export const getItems = async ( after, first, query: `${updatedAt ? 'updated:' + updatedAt : ''} sort:saved-asc ${query}`, - includeContent, + includeContent: false, format, }) const articles = response.edges.map((e) => e.node) + if (includeContent && articles.length > 0) { + try { + const content = await getContent( + endpoint, + apiKey, + articles.map((a) => a.id), + ) + + await Promise.allSettled( + content.data.map(async (c, index) => { + if (c.error) { + console.error('Error fetching content', c.error) + return + } + + // timeout if download takes too long + articles[index].content = await Promise.race([ + downloadFromUrl(c.downloadUrl), + new Promise( + (_, reject) => setTimeout(() => reject('Timeout'), 10000), // 10 seconds + ), + ]) + }), + ) + } catch (error) { + console.error('Error fetching content', error) + } + } + return [articles, response.pageInfo.hasNextPage] }