if (typeof Zotero === 'undefined') { var Zotero; } function log(msg) { Zotero.debug("Zotero JS Bridge: " + msg); } function install() { } function uninstall() { } function startup({ id, version, resourceURI, rootURI }) { log("Starting up..."); // Register generic execution endpoint Zotero.Server.Endpoints["/zotero-js-bridge/execute"] = function () { }; Zotero.Server.Endpoints["/zotero-js-bridge/execute"].prototype = { supportedMethods: ["POST"], supportedDataTypes: ["application/json", "application/x-www-form-urlencoded"], init: async function (options, sendResponseCallback) { try { let requestData = typeof options === 'string' ? options : (options.data || options); if (typeof requestData === 'string') { try { requestData = JSON.parse(requestData); } catch (e) { // Handled later or ignored if not JSON } } let code = requestData.code; if (!code) { sendResponseCallback(400, "application/json", JSON.stringify({ success: false, error: "Missing 'code' in request body" })); return; } // Execute code in Zotero's context, providing async support const asyncFunc = new Function('Zotero', `return (async () => { ${code} })();`); const result = await asyncFunc(Zotero); sendResponseCallback(200, "application/json", JSON.stringify({ success: true, result: result })); } catch (e) { log("Error in /execute: " + e); sendResponseCallback(500, "application/json", JSON.stringify({ success: false, error: e.message || e.toString() })); } } }; // Register endpoint to find full text / PDFs for items Zotero.Server.Endpoints["/zotero-js-bridge/findPDFsForItems"] = function () { }; Zotero.Server.Endpoints["/zotero-js-bridge/findPDFsForItems"].prototype = { supportedMethods: ["POST"], supportedDataTypes: ["application/json", "application/x-www-form-urlencoded"], init: async function (options, sendResponseCallback) { try { let requestData = typeof options === 'string' ? options : (options.data || options); if (typeof requestData === 'string') { try { requestData = JSON.parse(requestData); } catch (e) { // Handled later } } let itemIds = requestData.itemIds; if (!Array.isArray(itemIds)) { sendResponseCallback(400, "application/json", JSON.stringify({ success: false, error: "Missing or invalid 'itemIds' in request body" })); return; } // Retrieve items and filter out nulls/falsy values let items = await Zotero.Items.getAsync(itemIds); if (!items) items = []; items = items.filter(item => item != null); if (items.length > 0) { Zotero.Attachments.addAvailablePDFs(items); } sendResponseCallback(200, "application/json", JSON.stringify({ success: true, message: `Started finding PDFs for ${items.length} items.` })); } catch (e) { log("Error in /findPDFsForItems: " + e); sendResponseCallback(500, "application/json", JSON.stringify({ success: false, error: e.message || e.toString() })); } } }; } function shutdown() { log("Shutting down..."); delete Zotero.Server.Endpoints["/zotero-js-bridge/execute"]; delete Zotero.Server.Endpoints["/zotero-js-bridge/findPDFsForItems"]; }