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:
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";