diff options
author | Mark Powers <mark@marks.kitchen> | 2025-07-04 12:03:11 -0500 |
---|---|---|
committer | Mark Powers <mark@marks.kitchen> | 2025-07-04 12:03:11 -0500 |
commit | 13feb30f3ff9b913670a5fe7c8a9c1907d2c1740 (patch) | |
tree | ab6c820b4904ee7b05cb284af87ea2afc680d628 /src/index.ts |
Initial commitmain
Diffstat (limited to 'src/index.ts')
-rw-r--r-- | src/index.ts | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..f3dcd0f --- /dev/null +++ b/src/index.ts @@ -0,0 +1,156 @@ +import joplin from 'api'; +import { SettingItemType, ModelType, ToastType } from 'api/types'; + +enum ItemChangeEventType { + create = 1, + update = 2, + delete = 3 +} + +const settingObjs = { + 'HooksEnabled': { + value: false, + type: SettingItemType.Bool, + section: 'WebAngling', + public: true, + label: 'Enable Webhooks. Must also enable Note Changes or Resource Changes.' + }, + "URL": { + value: null, + type: SettingItemType.String, + section: 'WebAngling', + public: true, + label: 'Webhook URL.' + }, + "Method": { + value: false, + type: SettingItemType.String, + section: 'WebAngling', + public: true, + label: 'HTTP Method to use sending webhook (e.g., POST, GET).', + isEnum: true, + options: { + 'POST': 'POST', + 'GET': 'GET', + }, + }, + "NoteChangesEnabled": { + value: false, + type: SettingItemType.Bool, + section: 'WebAngling', + public: true, + label: 'Send Webhooks on note changes.' + }, + "ResourceChangesEnabled": { + value: false, + type: SettingItemType.Bool, + section: 'WebAngling', + public: true, + label: 'Send Webhooks on resource changes.' + }, + "IncludeTitle": { + value: true, + type: SettingItemType.Bool, + section: 'WebAngling', + public: true, + label: 'Include Note/Resource title in webhook payload.' + } +} + +async function registerSettings(){ + await joplin.settings.registerSection('WebAngling', { + label: 'Web Angling', + iconName: 'fas fa-fish', + }); + await joplin.settings.registerSettings(settingObjs) +} + +async function onEvent( + event_type: string, + id: string, + change_type="Update", +){ + const anglerSettings = await joplin.settings.values(Object.keys(settingObjs)); + + if(!anglerSettings["HooksEnabled"]){ + return + } + + const obj_type = ModelType[await joplin.data.itemType(id)] + let title = undefined; + if(obj_type == "Note"){ + if(!anglerSettings["NoteChangesEnabled"]){ + return + } + if(anglerSettings["IncludeTitle"]){ + const note = await joplin.data.get(['notes', id], { fields: ['title'] }); + title = note.title + } + } else { + if(!anglerSettings["ResourceChangesEnabled"]){ + return + } + } + + const payload = { + object_type: obj_type, + object_id: id, + change_type: change_type, + title: title + } + try { + await doFetch( + anglerSettings["URL"], + payload, + anglerSettings["Method"] as string, + {}, + "application/json", + ) + } catch (error) { + await joplin.views.dialogs.showToast( + { + message: `Webhook error ${error.message}`, + type: ToastType.Error, + duration: 5000, + } + ); + } +} + +async function doFetch(url, payload, method = 'POST', headers = {}, contentType = 'application/json') { + const finalHeaders = { + 'Content-Type': contentType, + ...headers, + }; + + try { + const response = await fetch(url, { + method: method, + headers: finalHeaders, + body: contentType === 'application/json' ? JSON.stringify(payload) : payload, + }); + + if (!response.ok) { + throw new Error(`Webhook request failed with status ${response.status}`); + } + + return response; + } catch (error) { + console.error("Webhook request error:", error); + throw error; + } +} + +joplin.plugins.register({ + onStart: async function() { + await registerSettings() + + await joplin.workspace.onNoteChange(async (e) => { + await onEvent("note", e.id, ItemChangeEventType[e.event]) + }); + + await joplin.workspace.onResourceChange(async (e) => { + await onEvent("resource", e.id, "update") + }); + }, +}); |