Javascript that works when run in Script Editor, but not from a Smart Rule

Hi. I’ve been writing some javascript scripts that work very well, thanks to all the excellent posts in this forum!

One scripts that are quite simple and only have the one performsmartrule() function, I find that they run without issues in both the Script Editor and also from a Smart Rule. The problem that I’m finding is for longer scripts that have multiple functions that they run just fine in Script Editor; however, call up errors when done through a Smart Rule.

When I run through a Smart Rule I’m getting: on performSmartRule (Error -1708).

Just wondering if this is a known issue, or if it is something specific to the code and I just need to drill down into it?

Thanks!

Show your code, please. It’s pointless to speculate about something one can’t see.

Sure, this is a script that works great when run from the Script Editor, but not when it’s through Smart Rules (simplified slightly as to not make this too long):

(() => {
  if (currentAppID() === "DNtp") return;
  const app = Application("DEVONthink 3");
  performsmartsule(app.selectedRecords());
})();

function currentAppID() {
  const p = Application.currentApplication().properties();
  return Application(p.name).id();
}

function performsmartsule(records) {
  var app = Application("DEVONthink 3");
  app.includeStandardAdditions = true;

  records.forEach(record => {
    const content = record.plainText();
    const result = processTextBasedOnPhrase(content);
    if (result) {
      record.name = result.name;
      record.tags = result.tags;
    }
  });
  
}


function processTextBasedOnPhrase(text) {
	const receipts = [
		{ title: 'Patreon', phrases: ['Patreon'], dateFormat: 'UK-monthStr', tags: ['Subscription','Patreon'] },
		{ title: 'Apple Music', phrases: ['Apple Music'], dateFormat: 'GMAIL', tags: ['Subscription'] },
	];

	for (const receipt of receipts) {
		if ( areAllPhrasesInText(text, receipt.phrases) ) {
			const date = extractDateStructured(text, receipt.dateFormat );
			if (date) {
        		const title = `${receipt.title} - ${dateToTitleStr(date.day, date.month, date.year)}`;
				receipt.tags.push(date.year);
        		return { name: title, tags: receipt.tags };
			}
      }
	}
	return null;
}


function extractDateStructured(text, dateFormat) {
  const monthRegexPart = "(Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)";

  const dateRegexMap = {
    "ISO": /\d{4}-\d{2}-\d{2}/, // YYYY-MM-DD
    "US": /(\d{2})-(\d{2})-(\d{4})/, // MM-DD-YYYY
    "UK": /(\d{2})\/(\d{2})\/(\d{4})/, // DD/MM/YYYY
	"UK-shortYear": /(\d{2})\/(\d{2})\/(\d{2})/, // DD/MM/YY
    "EU": /(\d{2})\.(\d{2})\.(\d{4})/, // DD.MM.YYYY
	"GMAIL": new RegExp(`${monthRegexPart} (\\d{1,2}), (\\d{4})`, "i"), // MMM D, YYYY
	"UK-monthStr": new RegExp(`(\\d{1,2}) ${monthRegexPart} (\\d{4})`, "i"), // DD MMM YYYY
  };

  let regex =  dateRegexMap[dateFormat]; 
  let match = text.match(regex);

  // Initialize date structure
  let dateStructure = {
    day: "",
    month: "",
    year: ""
  };

  if (match && match[1]) {
    let year, month, day;
    switch (dateFormat) {
      case "US":
        [month, day, year] = [match[1], match[2], match[3]];
        break;
      case "UK":
	  case "UK-shortYear":
      case "EU":
        [day, month, year] = [match[1], match[2], match[3]];
        break;
	  case "GMAIL":
	  	[day, month, year] = [match[2], getMonthNumber(match[1]), match[3]];
		break;	
	  case "UK-monthStr":
	  	[day, month, year] = [match[1], getMonthNumber(match[2]), match[3]];
		break;
      case "ISO":
      default:
        [year, month, day] = match[1].split('-');
        break;
    }

	if (dateFormat == "UK-shortYear") {
		year = '20' + year;
	}

    // Assign parsed values
    dateStructure = { day, month, year };
  }

  return dateStructure;
}

function areAllPhrasesInText(text, phrases) {
    return phrases.every(phrase => text.includes(phrase));
}

function dateToTitleStr(day, month, year) {
  day = parseInt(day, 10);
  const date = new Date(year, month - 1, day);
  const monthStr = date.toLocaleString('default', { month: 'long' });
  return `${monthStr} ${day}, ${year}`;
}

function getMonthNumber(monthName) {
  const monthNames = [
    "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December"
  ];
  const abbreviatedMonthNames = [
    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  ];

  // Normalize input for comparison
  monthName = monthName.toLowerCase();

  let index = monthNames.findIndex(name => name.toLowerCase().startsWith(monthName));
  if (index !== -1) return index + 1;

  index = abbreviatedMonthNames.findIndex(name => name.toLowerCase() === monthName);
  if (index !== -1) return index + 1;

  return null; // Return null if no valid month is found
}

You might want to check the spelling of performsmartsule. DT is certainly never going to call that in a smart rule. Neither in a smart sule, as it stands.

1 Like

Lol!! Thank you!

For the next time: Please always post the code, with your first post!

It’s the most important information in such a case.