Have AI generate an Apple Script and then execute it

First of all: Great implementation of AI. This is very well done and crazy useful. Using the chat I have an Idea:

Workflow so far:

  • I get an Invoice into DT
  • Each invoice has to be payed from a certain account using Moneymoney.
  • I copy the corresponding script into the chat and have it generate an apple Script.
  • I then execute the script resulting in an money money window with the data prefilled
  • I check the result and authorize the transaction

What I’d love to do:

  • right click on the invoice to trigger a DT-Script
  • Get a window where I can insert my prompt (doing that using Alfred and snippets)
  • Have DT Execute the prompt and execute the resulting script as an Apple Script
  • get the window * check the content * authorize the transaction

Could that be done? That would be awesome (and maybe a good use case for similar requirements)

my prompt so far:

create a script with the following format:"
osascript -e "tell application \"MoneyMoney\"
    create bank transfer from account \"VOB MY ACCOUNT\" to \"[Insert recipient]\" iban \"[Insert account number without spaces]\" amount [insert the amount] purpose \"INVOICE: [insert the number of the invoice]\"
    end tell"
Do not change the format of the script and return only the script. Use the info from the pdf.

I hope someone is interested in working this out with me.

All the best from Germany
Volker

AppleScript code invented by AI is notoriously bad and often wrong. The time spent figuring out a useful prompt is better spent by learning to code. Not necessarily AppleScript, but any programming language.

And many German banks nowadays can process photos of invoices already, BTW.

Instead of generating a script each time I would suggest to use the get chat response for message AppleScript command and to tell the AI to return recipient, account number, amount and invoice number as a JSON object, assuming that the PDF (?) document is already stored in DEVONthink. Then you could you use the returned values after reviewing them.

Thank you for your response. For context I distribute the invoices to 40+ Accounts in 10 german Banks. There might be a way to cut out the snippet part: Each invoice has a 3 letter marker (Like a shortcut) that correlates with certain accounts. Hard coding this relation would eliminate the copy paste issue and streamline the process even more.

Having only rudimentary Apple Script knowledge can you recommend me a book or a website to get the knowledge I would need to achieve my goal, that is:

  • Taking the first 3 letters of the Filename
  • Match those to an Account (hard coded into the script would be totally fine)
  • Get AI to return the above mentioned JSON
  • process the JSON

If there is an example that covers some of the steps this would be awesome. If not and I somehow manage to get this working I will gladly provide my script for other DT users. This seams like a fairly interesting use case.

Well, the books are probably mostly out of print. You might want to have a look at the O’Reilly website for that. Then there’s the MacScripter website for code samples.

Though I don’t understand the fixation on AppleScript. If you don’t know anything about programming, why start with that instead of a modern language? JavaScript can be used for your task equally well, it can handle JSON out of the box, and it is better suited to deal with strings, etc. Not to mention that the web is full of information on it; there are even books out there, all that.

Case in point: (All that can be achieved in AppleScript, too. The ibanMatch part might be a bit harder, though).

const matchAccounts = {'AAA': 'DE12…', 'BBB': 'DE34…', 'CCC': 'DE56…'};
const app = Application('DEVONthink');
const records = app.selectedRecords();
records.forEach(r => {
  const code = r.name().substring(0,2);
  const account = matchAccounts[code]; 
  if (!account) {
    throw new Error(`No account found for code ${code} in record ${r.name()}`);
  }
  const txt = r.plainText();
  // get recipient from text
  const ibanMatch = txt.match(/[A-Z][A-Z][0-9\s]{20,25}/);
  if (!ibanMatch) {
    throw new Error(`No IBAN found in record ${r.name()}`);
  };
  // get amount – that's the hardest part in my experience
})

This sample script (untested) would loop over the currently selected records and use the first three letters of the filename to find the corresponding account defined in the object matchAccounts. It bails out if no match exists.

The code then looks at the text of the record to find the IBAN (again bailing out if none is found). The two remaining parts, finding the recipient and the amount, are more difficult.

If the three-letter code is tied to certain recipients, you can add code to get the amount and the recipient depending on this code. I wrote a sample ages ago.

Edit I just fiddled around with DT’s documentAmount, which is supposedly finding the amount in a document. I ran that on a bit more than 600 documents, and the results were … mixed. In some cases, DT didn’t find anything. In others, it found the correct value. In others, it found e.g. the value without VAT (not helpful). And in others it found a completely bogus value. In my opinion, your safest bet is to tailor functions to get the amount depending on the sender of the invoice.

Simplistic approaches like “take the maximum value” or “take the last amount” will reliably fail: there might be a discount applied to the maximum value or the last amount on the invoice might be the cost of labour (

Getting the information from the PDFs is the hard part. Feeding them to MoneyMoney is simple.

1 Like

Oh, and one more thing: Business invoices in Germany must be machine-readable now. If you’re dealing with 40 accounts, I assume that we’re talking about B2B invoices here. So, the most reasonable way to deal with that is to get yourself a (possibly free) ZugFERD-compatible tool that extracts the XML from the PDF and process that.

This service Webbasiert ZUGFeRD XML extrahieren und anzeigen can be scripted, I guess.

Edit I’ve found two ways to extract the XML ZugFeRD from a PDF document on the command line:

Then you need to parse the resulting XML, probably using NSXMLDocument and NSXMLElement. The code for all this is probably not very simple, but this approach should lead to more reliable results than parsing the PDF text itself.

1 Like