diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6f66c74 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.zip \ No newline at end of file diff --git a/README.md b/README.md index a9020b3..63cea67 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,13 @@ # mealie-extension -A Firefox extension to easily add recipes to a personal Mealie instance. \ No newline at end of file +A Firefox extension to easily add recipes to a personal Mealie instance. + +**Note: This is currently in alpha. Please use at your own risk** + +*How to use* + +Install through Firefox marketplace (pending approval) or use extension debug to install manually as a temp extension. + +Once installed, go to preferences and your Mealie URL and the API token you will be using (this needs to be generated from your account on Mealie). + +After that, either right-click a page or use shortcut "Ctrl+Alt+M". \ No newline at end of file diff --git a/extension/background.js b/extension/background.js new file mode 100644 index 0000000..40b8f2f --- /dev/null +++ b/extension/background.js @@ -0,0 +1,96 @@ +async function Clicked() { + // Grabs our Token and URL from the Preferences page + const { token, url } = await browser.storage.local.get(['token', 'url']); + + // Pull current site's URL + let [tab] = await browser.tabs.query({active: true, currentWindow: true}); + // removes a traling forward slash + let site_url = tab.url.endsWith('/') ? + tab.url.slice(0, -1) : + tab.url; + + let mealie_url = url; + + /*** + * NO LONGER USED + * Was originally designed based off of the bookmarklet example on Mealie's GitHub + * + * + let site_url = document.URL.endsWith('/') ? + document.URL.slice(0, -1) : + document.URL; + // let group_slug = "" // Change this to your group slug. You can obtain this from your URL after logging-in to Mealie + // let use_keywords= "&use_keywords=0" // Optional - use keywords from recipe - update to "" if you don't want that + // let edity = "&edit=0" // Optional - keep in edit mode - update to "" if you don't want that + + if (mealie.slice(-1) === "/") { + mealie = mealie.slice(0, -1) + } + let dest = mealie + "/recipe/create/url?recipe_import_url=" + site_url; + + // Send a message to the content script + browser.tabs.query({active: true, currentWindow: true}, (tabs) => { + console.log("Sending message to content script"); + browser.tabs.sendMessage(tabs[0].id, `Token: ${token}, URL: ${url}`).then(() => { + console.log("Message sent to content script"); + }).catch((error) => { + console.error("Error sending message to content script:", error); + }); + }); + + // Open a new tab with the destination URL + browser.tabs.create({ url: dest }).then(() => { + console.log(`New tab opened with URL: ${dest}`); + }).catch((error) => { + console.error("Error opening new tab:", error); + }); + * + */ + + // Submit POST request to your Mealie server + const postUrl = `${mealie_url}/api/recipes/create/url`; + const requestBody = { + includeTags: false, + url: site_url + }; + + const response = await fetch(postUrl, { + method: "POST", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${token}` + }, + body: JSON.stringify(requestBody) + }); + + if (response.ok) { + const responseData = await response.json(); + console.log("POST request successful:", responseData); + } else { + const errorText = await response.text(); + console.error("POST request failed:", response.statusTextm, errorText); + } +} + +// background.js + +// Create a context menu item +browser.contextMenus.create({ + id: "clickHere", + title: "Add to Mealie", + contexts: ["all"], +}); + +// Add a listener for the context menu item +browser.contextMenus.onClicked.addListener((info, tab) => { + if (info.menuItemId === "clickHere") { + Clicked(); + } +}); + +// Add a listener for the keyboard shortcut +browser.commands.onCommand.addListener((command) => { + if (command === "activateClick") { + Clicked(); + } +}); diff --git a/extension/icons/48.png b/extension/icons/48.png new file mode 100644 index 0000000..ac66efa Binary files /dev/null and b/extension/icons/48.png differ diff --git a/extension/manifest.json b/extension/manifest.json new file mode 100644 index 0000000..0e63afc --- /dev/null +++ b/extension/manifest.json @@ -0,0 +1,34 @@ +{ + "manifest_version": 2, + "name": "Mealie", + "version": "1.0.1", + + "description": "Connects with a local Mealie instance.", + + "icons": { + "48": "icons/48.png" + }, + + "background": { + "scripts": ["background.js"] + }, + "permissions": [ + "webRequest", + "*://*/*", + "contextMenus", + "storage", + "activeTab" + ], + "commands": { + "activateClick": { + "suggested_key": { + "default": "Ctrl+Alt+M" + }, + "description": "Activates 'Clicked' function" + } + }, + "options_ui": { + "page": "options.html", + "open_in_tab": true + } +} \ No newline at end of file diff --git a/extension/options.html b/extension/options.html new file mode 100644 index 0000000..4f2a127 --- /dev/null +++ b/extension/options.html @@ -0,0 +1,17 @@ + + + + + Mealie Extension Options + + +

Extension Options

+ +
+ +
+ + + + + diff --git a/extension/options.js b/extension/options.js new file mode 100644 index 0000000..534dac4 --- /dev/null +++ b/extension/options.js @@ -0,0 +1,16 @@ +// options.js + +document.getElementById('save').addEventListener("click", async () => { + const token = document.getElementById('token').value; + const url = document.getElementById('url').value; + + await browser.storage.local.set({ token, url }); + alert('Options saved!'); +}); + +// Load saved settings if they exist +(async () => { + const { token, url } = await browser.storage.local.get(['token', 'url']); + if (token) document.getElementById('token').value = token; + if (url) document.getElementById('url').value = url; +})(); diff --git a/mealie-ext-screenshot-contextmenu.png b/mealie-ext-screenshot-contextmenu.png new file mode 100644 index 0000000..b281fed Binary files /dev/null and b/mealie-ext-screenshot-contextmenu.png differ