Skip to content

[Bug] D418282840: Script runs twice #534

@DonnaCoxBaker

Description

@DonnaCoxBaker

Is there an existing issue for this?

  • I have searched the existing issues

Are you using the latest Zotero and the latest plugin?

  • I have confirmed I'm using the latest Zotero and the latest plugin

Environment

  • OS: 11 26200
  • Zotero Version: 7.0.27 (x64)
  • Plugin Version: 2.2.4

Describe the bug

I have been trying to create a script that creates a child "to do" note under a source item, pulling bibliographic information from the parent,linking back to the parent (in case the item is linked to a master note through Better Notes). It asks the user to describe the task and add a due date. It works well and creates what I want it to create. But just after it does that, it pulls up the requests for information again and creates a second to-do child note. ChatGPT created the script and has revised it in numerous ways all day to try to stop the duplication, without success, finally telling me I need to bring this here.

The Note looks like this:

Image

Here is the Actions & Tags Setup:

Image

Here is the code:

// ===== Clean To-Do note creator =====
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");

// --- helpers ---
function promptLine(title, msg, defVal=""){
  const box = { value: defVal };
  const ok = Services.prompt.prompt(null, title, msg, box, null, {});
  if (!ok) return null;
  return (box.value || "").trim();
}
function fmtDate(d){
  const z = new Date(d.getTime() - d.getTimezoneOffset()*60000);
  return z.toISOString().slice(0,10); // ISO YYYY-MM-DD
}
function addDays(d,n){ const x=new Date(d); x.setDate(x.getDate()+n); return x; }

// --- due-date parser ---
function parseDue(input){
  if (!input) return "";
  const raw = String(input).trim();
  if (!raw) return "";
  const s = raw.toLowerCase();

  if (s === "*") return fmtDate(new Date());
  if (/^\+?\d+\s*(d|day|days)?$/.test(s)){
    const n = parseInt(s.replace(/\D/g,""),10);
    if (!isNaN(n)) return fmtDate(addDays(new Date(), n));
  }
  if (s === "today")    return fmtDate(new Date());
  if (s === "tomorrow") return fmtDate(addDays(new Date(),1));
  if (s === "next week")return fmtDate(addDays(new Date(),7));
  if (/^\d{4}-\d{1,2}-\d{1,2}$/.test(s)){
    const [Y,M,D]=s.split("-").map(Number); const dt=new Date(Y,M-1,D);
    if(!isNaN(dt)) return fmtDate(dt);
  }
  if (/^\d{1,2}\/\d{1,2}(\/\d{2,4})?$/.test(raw)){
    const p=raw.split("/").map(Number), nowY=new Date().getFullYear();
    const Y=p[2] ? (p[2]<100 ? 2000+p[2] : p[2]) : nowY;
    const dt=new Date(Y,p[0]-1,p[1]); if(!isNaN(dt)) return fmtDate(dt);
  }
  if (/^\d{8}$/.test(s)){
    const MM=+s.slice(0,2), DD=+s.slice(2,4), YYYY=+s.slice(4);
    const dt=new Date(YYYY,MM-1,DD); if(!isNaN(dt)) return fmtDate(dt);
  }
  if (/^\d{6}$/.test(s)){
    const MM=+s.slice(0,2), DD=+s.slice(2,4), YY=+s.slice(4);
    const YYYY=2000+YY; const dt=new Date(YYYY,MM-1,DD);
    if(!isNaN(dt)) return fmtDate(dt);
  }
  return raw;
}

// --- selection ---
let sel = items;
if ((!sel || !sel.length) && typeof item !== "undefined" && item) sel = [item];
if (!sel || sel.length !== 1) return;

const picked = sel[0];
const isNote = (typeof picked.isNote === "function") ? picked.isNote() : !!picked.isNote;
const topItem = (isNote && picked.parentID) ? Zotero.Items.get(picked.parentID) : picked;
if (!topItem || typeof topItem.getField !== "function") return;

// --- prompts ---
const task = promptLine("Task","What is the task?");
if (!task) return;

const dueRaw = promptLine("Due Date (optional)","Type *, +7, 11102025, 11/10/25, 2025-11-10, etc.");
const dueDisplay = parseDue(dueRaw || "");

// --- compose ---
const combined = dueDisplay ? `${task} (Due: ${dueDisplay})` : task;
const created  = fmtDate(new Date());

const creators   = topItem.getField("creatorsString") || "";
const title      = topItem.getField("title") || "";
const pubTitle   = topItem.getField("publicationTitle") || "";
const place      = topItem.getField("place") || "";
const publisher  = topItem.getField("publisher") || "";
const dateStr    = topItem.getField("date") || "";
const doiPart    = topItem.getField("DOI") ? (" https://doi.org/" + topItem.getField("DOI")) : "";
const urlPart    = (!topItem.getField("DOI") && topItem.getField("url")) ? (" " + topItem.getField("url")) : "";
const placePub   = [place, publisher].filter(Boolean).join(": ");
const bibText    = [creators, title, pubTitle, placePub, dateStr, (doiPart || urlPart)]
                    .filter(Boolean).join(". ");

const link = (topItem.libraryID && topItem.libraryID !== 1)
  ? `zotero://select/groups/${topItem.libraryID}/items/${topItem.key}`
  : `zotero://select/library/items/${topItem.key}`;

// --- HTML layout ---
let html = `
⚡ <b>DO:</b> ${Zotero.Utilities.htmlSpecialChars(combined)}

<p class="source">
  <a href="${Zotero.Utilities.htmlSpecialChars(link)}">${Zotero.Utilities.htmlSpecialChars(bibText)}</a>
</p>

<span style="display:block; text-align:left; font-size:1.0em; font-weight:bold; margin:0;">
<b>Details</b>
<br>
<hr>
</span>

<p><span style="font-weight: normal;"><em>Created ${Zotero.Utilities.htmlSpecialChars(created)}</em></span></p>
`.trim();

// --- create note ---
const child = new Zotero.Item("note");
child.parentID = topItem.id;
child.setNote(html);
await child.saveTx();

Debug Output

D418282840

[JavaScript Error: "uncaught exception: undefined"]

Warning: attempting to write 12126 bytes to preference extensions.actionsTags.rules.1728800687408-bcwQxPwN. This is bad for general performance and memory usage. Such an amount of data should rather be written to an external file.

Warning: attempting to write 4670 bytes to preference extensions.actionsTags.rules.1762818073217-bcwQxPwN. This is bad for general performance and memory usage. Such an amount of data should rather be written to an external file.

[JavaScript Error: "TypeError: emptyListMessage is null" {file: "chrome://zotero/content/standalone/standalone.js" line: 676}]
ZoteroStandalone</this.updateAddonsPane/<@chrome://zotero/content/standalone/standalone.js:676:7

[JavaScript Error: "Error processing feed from https://rss.app/feeds/f0WPtxfxufySzlMP.xml:

Error: Processing failed"]

[JavaScript Error: "Error processing feed from https://rss.app/feeds/gEW5O8FWGmBVpFWF.xml:

Error: Processing failed"]

[JavaScript Error: "Error processing feed from https://rss.app/feeds/EFPPpAusuzbnH3Qs.xml:

Error: Processing failed"]

appName => Zotero, version => 7.0.27 (x64), os => Windows 11 26200, locale => en-US, extensions => Actions and Tags for Zotero (2.2.4, extension), Night (0.1.0-2, extension, disabled), Zotero PDF Preview (1.0.0-4, extension, disabled), Aria (0.7.5, extension, disabled), Add-on Market for Zotero (2.1.1, extension, disabled), Folder Import for Zotero (0.0.9, extension, disabled), Zutilo Utility for Zotero (4.0.1, extension, disabled), ZotCard (3.3.0, extension, disabled), Notero (1.2.1, extension, disabled), Zotero Pin Items (0.4.3, extension, disabled), Zotero OCR (0.9.3, extension, disabled), Zotero Attanger (1.3.9, extension, disabled), Better Notes for Zotero (2.5.9, extension, disabled)

Anything else?

No response

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions