obsidian-semantic

Log | Files | Refs | README

commit 080c1b55c92058dbbe987b56b2b5ddb20e17a2fb
parent b8129015b6c499dce37778b1b004c60d35eeb98e
Author: Thomas Vigouroux <thomas.vigouroux@univ-grenoble-alpes.fr>
Date:   Thu, 18 Apr 2024 13:40:42 +0200

refactor: expose API through a class

Diffstat:
ASemanticApi.ts | 44++++++++++++++++++++++++++++++++++++++++++++
MSemanticsSettings.ts | 4++--
Mmain.ts | 67+++++++++++++++++++++++++++----------------------------------------
3 files changed, 73 insertions(+), 42 deletions(-)

diff --git a/SemanticApi.ts b/SemanticApi.ts @@ -0,0 +1,43 @@ +import { requestUrl, RequestUrlParam, RequestUrlResponsePromise } from "obsidian"; +import pDebounce from 'p-debounce'; + +const baseURL: string = "https://api.semanticscholar.org/graph/v1"; + +export interface BaseRequest { + method?: string; + contentType?: string; + body?: string | ArrayBuffer; + headers?: Record<string, string>; +} + +export class SemanticApi { + key?: string; + + constructor(key?: string) { + this.key = key; + } + + request(endpoint: string, params: Record<string, string>, base?: BaseRequest): RequestUrlResponsePromise { + var paramsList: string[] = []; + for (let key in params) { + paramsList.push(`${key}=${encodeURIComponent(params[key])}`) + } + + var headers: Record<string,string> = base ? (base.headers ? base.headers : {}) : {}; + if (this.key) { + headers['x-api-key'] = this.key; + } + + var req: RequestUrlParam = { + url: `${baseURL}/${endpoint}?${paramsList.join('&')}`, + method: base ? base.method : undefined, + headers: headers, + body: base ? base.body : undefined, + contentType: base ? base.contentType : undefined, + }; + console.log("Requesting", req); + return requestUrl(req) + } + + debouncedRequest = pDebounce(this.request, 1000) +} +\ No newline at end of file diff --git a/SemanticsSettings.ts b/SemanticsSettings.ts @@ -30,9 +30,9 @@ export class SemanticsSettings extends PluginSettingTab { .setDesc("API Key to use") .addText(text => text .setPlaceholder("api key") - .setValue(this.plugin.settings.apiKey == null ? "" : this.plugin.settings.apiKey) + .setValue(this.plugin.settings.apiKey == undefined ? "" : this.plugin.settings.apiKey) .onChange(async (value) => { - this.plugin.settings.apiKey = value == "" ? null : value; + this.plugin.settings.apiKey = value == "" ? undefined : value; await this.plugin.saveSettings(); })); } diff --git a/main.ts b/main.ts @@ -1,20 +1,16 @@ import { SemanticsSettings } from 'SemanticsSettings'; import { App, Editor, MarkdownView, Modal, Notice, Plugin, SuggestModal, TFile, TFolder, Vault, requestUrl, RequestUrlParam } from 'obsidian'; -import pDebounce from 'p-debounce'; import * as path from 'path'; - -const baseURL: string = "https://api.semanticscholar.org/graph/v1"; - -// Remember to rename these classes and interfaces! +import { SemanticApi } from 'SemanticApi'; interface SemanticSettings { papersPath: string; - apiKey: string | null; + apiKey?: string; } const DEFAULT_SETTINGS: SemanticSettings = { papersPath: 'papers', - apiKey: null + apiKey: undefined } class SemInfos { @@ -74,37 +70,29 @@ class Paper { return Paper.fields() + ",externalIds,citationStyles,citations,references" } - static async get(id: string, long?: boolean, key?: string): Promise<Paper> { - if (key != undefined) { - - } - var request: RequestUrlParam = { - url: `${baseURL}/paper/${id.trim()}?fields=${long ? Paper.fields() : Paper.fieldsLong()}`, - headers: key == null ? {} : { - 'x-api-key': key - } - } - return requestUrl(request).json; + static async get(api: SemanticApi, id: string, long?: boolean, key?: string): Promise<Paper> { + return api.request(`paper/${id.trim()}`, { + "fields": long ? Paper.fields() : Paper.fieldsLong() + }).json; } - static async getBulk(ids: string[], long?: boolean, key?: string): Promise<Paper[]> { - return requestUrl({ - url: `${baseURL}/paper/batch?fields=${long ? Paper.fields() : Paper.fieldsLong()}`, + static async getBulk(api: SemanticApi, ids: string[], long?: boolean, key?: string): Promise<Paper[]> { + return api.request("paper/batch", { + "fields": long ? Paper.fields() : Paper.fieldsLong(), + }, { method: "POST", contentType: "application/json", body: JSON.stringify({ids: ids}), - headers: key == null ? {} : { - 'x-api-key': key - } }).json; } } export default class SemanticIntegration extends Plugin { settings: SemanticSettings; + apiAccess: SemanticApi; openModal() { - new SemanticModal(this.app, this.settings).open(); + new SemanticModal(this.app, this.settings, this.apiAccess).open(); } getPapersFolder(): TFolder { @@ -119,6 +107,8 @@ export default class SemanticIntegration extends Plugin { async onload() { await this.loadSettings(); + this.apiAccess = new SemanticApi(this.settings.apiKey); + this.addRibbonIcon('book-plus', 'Add a new reference', (evt: MouseEvent) => { this.openModal(); }); @@ -177,7 +167,7 @@ export default class SemanticIntegration extends Plugin { } // TODO: fuzzy modal - console.log(await Paper.getBulk(ids)); + console.log(await Paper.getBulk(this.apiAccess, ids)); } }) @@ -203,19 +193,19 @@ export default class SemanticIntegration extends Plugin { var infos = await SemInfos.fromFile(this.app, file); if (infos.id != undefined) { - console.log(await Paper.get(infos.id, true)); + console.log(await Paper.get(this.apiAccess, infos.id, true)); } } } -const debouncedRequest = pDebounce(requestUrl, 1000); - class SemanticModal extends SuggestModal<Paper> { - options: SemanticSettings + options: SemanticSettings; + apiAccess: SemanticApi; - constructor(app: App, options: SemanticSettings) { + constructor(app: App, options: SemanticSettings, api: SemanticApi) { super(app); this.options = options; + this.apiAccess = api; } async getSuggestions(query: string): Promise<Paper[]> { @@ -223,14 +213,11 @@ class SemanticModal extends SuggestModal<Paper> { return []; } - var request: RequestUrlParam = { - url: `${baseURL}/paper/search?query=${encodeURIComponent(query)}&fields=${Paper.fields()}&limit=10`, - headers: this.options.apiKey == null ? {} : { - 'x-api-key': this.options.apiKey - } - } - - var result: Paper[] = (await debouncedRequest(request)).json.data; + var result: Paper[] = (await this.apiAccess.debouncedRequest("paper/search", { + "query": query, + "fields": Paper.fields(), + "limit": String(10) + })).json.data; return result; } @@ -249,7 +236,7 @@ class SemanticModal extends SuggestModal<Paper> { } async onChooseSuggestion(item: Paper, evt: MouseEvent | KeyboardEvent) { - var final = await Paper.get(item.paperId); + var final = await Paper.get(this.apiAccess, item.paperId); var title = final.title.split(":")[0]; var fname = path.join(this.options.papersPath, title) + ".md";