Across the Irvine valley. ๐Ÿ“ธ

Across the valley

Purchased a license for Shottr, a macOS screenshot tool, based on a discussion thread I stumbled on and it’s probably the best $4 I’ve spent in a year. Normally it would be $8, but took advantage of the first week coupon code.

Remembering those who gave it all for our freedom. ๐Ÿ“ธ

Memorial Day remembrance ceremony.

HB Northside Lineup ๐Ÿ“ธ

HB Northside Surf Lineup

If you have multiple domains you’d like to redirect to your domain (or any domain for that matter), and know how to manage your own DNS records, I highly recommend using as a redirect solution.

Blooming cactus ๐Ÿ“ธ

Blooming cactus

Giving Mimestream as spin as my mail client on macOS since I use Google Workspace for my domains. It’s impressive, but a $50/year subscription might be a little steep for me. We’ll see in 12 days.

Iโ€™m developing a love/hate relationship with the Copado CI/CD platform for Salesforce deployments. When it works, itโ€™s a dream. When it doesnโ€™t, itโ€™s a pain to figure out why.

I’ve been a WordPress user since the early days and have carried my content with me from one host to another. I think it’s time to put the old content to rest and start fresh with

A Better AppleScript Password Generator

As I continue to explore ChatGPT’s AppleScript code generation capabilities, I fed it a password generation script I came up with years ago and asked it to make it better.

The results were impressive.

My original script didn’t have error-checking or user bailout points. ChatGPT was smart enough to add them for me, along with some other smart “decisions” when it came to copying out the generated password. I did have to make a few edits for correctness.

This is the result, which I’ve opted to start using instead of my old script:

property allowedCharacters : {33, 35, 36, 37, 38, 42, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 61, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122}
property givenPasswordLength : 21

repeat while true
        set givenPasswordLength to text returned of (display dialog "Enter desired password length:" with title "Password Generator" default answer givenPasswordLength)
        set givenPasswordLength to givenPasswordLength as integer
        if givenPasswordLength is not greater than 0 then error "Please enter a valid positive integer."
        exit repeat
    on error errMsg
        display alert "Error" message errMsg as warning
        return -- added to ensure proper script exit
    end try
end repeat

repeat while true
        set generatedPassword to generatePassword()
        set dialogResult to (display dialog "New generated password:" & return & return & generatedPassword with title "Password Generator" buttons {"Refresh", "Copy", "Cancel"} default button "Refresh" cancel button "Cancel")
        if button returned of dialogResult is "Copy" then
            set the clipboard to generatedPassword as string
            exit repeat
        else if button returned of dialogResult is "Cancel" then
            exit repeat
        end if
    on error errMsg
        display alert "Error" message errMsg as warning
        return -- added to ensure proper script exit
    end try
end repeat

on generatePassword()
    set generatedPassword to ""
    repeat givenPasswordLength times
        set randomCharacterPosition to random number from 1 to count allowedCharacters
        set generatedPassword to generatedPassword & (ASCII character item randomCharacterPosition of allowedCharacters)
    end repeat
    return generatedPassword
end generatePassword

As always, this improved script works great with FastScripts.

AppleScript to Compress Files or Folders

A while ago, I created an AppleScript that allows you to compress files and folders by simply dropping them onto the applet. A reader left a comment asking for a way to achieve the following tasks:

  1. Select a folder from Finder.
  2. Store the folder name as “x”.
  3. Compress all files and sub-folders within the folder “x”, including their paths.
  4. Rename the resulting zip file as “”.
  5. Delete all the files that were used to create the zip file.
With the help of ChatGPT, I was able to come up with a solution to this challenge, which can be a great way to manage archives if you’re into that sort of thing.

I must admit that ChatGPT did a decent job in generating the AppleScript, but there were some bugs that I had to fix manually. Nevertheless, it’s both scary and exciting to have a tool that can generate usable code.

As always, you can run this script using FastScripts from your menu bar for quick and easy access.

-- choose files or folders to archive since AppleScript can't seem to allow both at once...
set archiveOption to button returned of (display dialog "Archive files or folders?" buttons {"Cancel", "Folders", "Files"} default button 3)

-- now let's choose what we want to archive...
if archiveOption is "Files" then
    set selectedItems to choose file with prompt "Select files you want to compress:" with multiple selections allowed
else if archiveOption is "Folders" then
    set selectedItems to choose folder with prompt "Select folders you want to compress:" with multiple selections allowed
else if archiveOption is "Cancel" then
end if

-- set the array of files or folders selected...
if the selectedItems is {} then
else if (selectedItems count) is equal to 1 then
    set thePathFilename to the quoted form of POSIX path of (selectedItems as string)
    set thePathFilename to {}
    repeat with i from 1 to (selectedItems count)
        copy (quoted form of POSIX path of (item i of selectedItems as string)) & space to end of thePathFilename
    end repeat
    set thePathFilename to thePathFilename as string
end if

-- coerce a date string for the archive name
set currentDate to current date
set yearStr to year of currentDate as string
set monthStr to (month of currentDate as integer) as string
if length of monthStr = 1 then set monthStr to "0" & monthStr
set dayStr to day of currentDate as string
if length of dayStr = 1 then set dayStr to "0" & dayStr
set currentDateStr to yearStr & "-" & monthStr & "-" & dayStr

-- next, let's name our archive, which defaults to "Archive" & the currentDateStr we just coerced
set archiveName to text returned of (display dialog "Enter a name for your archive:" default answer "Archive " & currentDateStr buttons {"Cancel", "OK"} default button 2)

-- then, let's choose where to save the archive and compress it with the shell "zip" command
set archiveFile to POSIX path of (choose folder with prompt "Choose a location to save the archive:")
do shell script "cd " & quoted form of archiveFile & " && zip -r " & quoted form of archiveName & ".zip " & thePathFilename

-- finally, let's delete the files we just archived if we decide we don't need them around anymore.
set deleteFiles to button returned of (display dialog "Do you want to delete the original files?" buttons {"Yes", "No"} default button 2)
set deleteOption to false
if deleteFiles is "Yes" then
    set deleteOption to true
end if
if deleteOption is equal to true then
    if selectedItems is not {} then
        set fileList to {}
        repeat with itemPath in selectedItems
            set end of fileList to quoted form of POSIX path of itemPath
        end repeat
        repeat with fileItem in fileList
            do shell script "rm " & fileItem
        end repeat
    end if
end if