Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert a Shortcut from a file or iCloud link to Cherri code #47

Open
electrikmilk opened this issue Feb 3, 2024 · 11 comments
Open

Convert a Shortcut from a file or iCloud link to Cherri code #47

electrikmilk opened this issue Feb 3, 2024 · 11 comments
Assignees
Labels
enhancement New feature or request

Comments

@electrikmilk
Copy link
Owner

electrikmilk commented Feb 3, 2024

Many Shortcuts languages before Cherri had this feature, so it is possible 😅

My original thoughts on this were that Cherri abstracts away some parts of creating Shortcuts for the sake of not having to put too much effort into writing a Shortcut, so I figured Cherri would not translate as naturally.

I figured that this would be preferred because converting and then having everything in one long file which may not come out right, would not be preferred to re-writing it, and along the way, finding ways that Cherri can improve the Shortcut or the maintainability of it since you can spread a Shortcut out into multiple files with includes.

However, it's not a great experience to not at least be able to generate a best guess of how a Shortcut would be written in Cherri. Instead having to re-write the entire Shortcut in Cherri. The developer can at least take the guess from there and tweak as needed.

Not saying I'm striving for guess quality but no decompilation will ever be 100% accurate.

@electrikmilk electrikmilk self-assigned this Feb 3, 2024
@electrikmilk electrikmilk added the enhancement New feature or request label Feb 3, 2024
@vergenzt
Copy link

vergenzt commented Mar 8, 2024

Any ideas on this? 🙂 I'm really coming to depend on some Shortcuts I use for personal automation. I recently decided I'd like to convert them to Cherri, and I'd love to have some initial automated "bones" to start from!

@vergenzt
Copy link

vergenzt commented Mar 8, 2024

Oh I just noticed the decomp branch is in progress! 😮

Anything ready to test yet? 😄

@electrikmilk
Copy link
Owner Author

electrikmilk commented Mar 13, 2024

Oh I just noticed the decomp branch is in progress! 😮

Anything ready to test yet? 😄

Thanks for your interest in this feature!

Yes, you can test this. If you use the decomp branch and build or run from the source, you can import a Shortcut using the --import flag entering either an iCloud Shortcut URL or a path to an unsigned Shortcut file. (e.g. go run . --import=unsigned.shortcut)

Keep in mind it is currently in active development so it's likely to be buggy, especially with more complex shortcuts.

@electrikmilk
Copy link
Owner Author

electrikmilk commented Mar 17, 2024

This now works very well on the decomp branch, just need to do more testing and implement more features that require specific implementation to decompile properly.

Now testing decompiling LARGE Shortcuts and comparing then fixing any incorrect decompilation. 😎

@electrikmilk
Copy link
Owner Author

I'm not sure we'll ever get perfect decompilation since Cherri while it tries to be as 1-1 as possible, has conveniences and doesn't always translate 1-1. However, I've been making strides in better matching actions that are split into multiple actions for ease of use. I'm excited to see how close we CAN get.

@vergenzt
Copy link

Good to know! I've got almost a dozen shortcuts that I use on a regular basis (five of which I have set to automatically run periodically throughout the day 🙂) so I'm really looking forward to getting some of this into source control! 😄

@vergenzt
Copy link

Btw it turns out that this comment is not true!

cherri/main.go

Lines 66 to 68 in 68974c0

if hasSignedBytes(shortcutBytes) {
exit("import: Unable to read Shortcut as it has been signed and the contents are encrypted.")
}

It's possible to extract the raw shortcut contents from signed shortcut files.

See https://theapplewiki.com/wiki/Apple_Encrypted_Archive:

Signed shortcuts are AEA files but they are actually not encrypted. The 32bit size for the AEA context can be found at location 0x8-0xB in the file, and the size plus 0x495c will be the starting location of an LZFSE compressed Apple Archive. (For an example of this, take a look at libshortcutsign's extract_aa_from_aea function.) After decompression, the magic number is the 4 ASCII characters "AA01".

I have an example of doing this using https://github.com/wader/fq for my own shortcuts repo I started a few weeks ago here:

https://github.com/vergenzt/shortcuts/blob/8c11c3856b2cc0b5db98e862c1737ac015b5ea05/lib/tasks/import.yaml#L31-L33

@vergenzt
Copy link

Hmm btw I just tested the latest decomp branch again and I'm getting a compilation error:

$ go install github.com/electrikmilk/cherri@decomp
go: github.com/electrikmilk/[email protected] requires go >= 1.22; switching to go1.22.2
# github.com/electrikmilk/cherri
../../go/pkg/mod/github.com/electrikmilk/[email protected]/decompile.go:719:18: undefined: actionOutputs
../../go/pkg/mod/github.com/electrikmilk/[email protected]/decompile.go:720:43: undefined: actionOutputs

Any ideas?

@vergenzt
Copy link

Alright so a few updates!

  1. I was able to resolve that decomp branch Go compilation error via vergenzt@d45deae.
  2. I attempted to import all of my Shortcuts! 😄 There were a number of issues. You can view the results at https://github.com/vergenzt/shortcuts/tree/main/src. For the imports that succeeded, there is a *.cherri file in the repo next to the corresponding *.plist / *.json files (I included both for each Shortcut for ease of comparison). For imports that failed, there is a *.cherri-decompile.log file containing the stderr panic output.

There were a few issues I've noticed so far:

  1. There were quite a few panics. 😅 I haven't dug into the details yet.
  2. Custom actions seemed to not be extracted at all. E.g. the single custom action at https://github.com/vergenzt/shortcuts/blob/62b5893173eb1c7003f22f22efc849f5a4dd151e/src/Automation%20Utils/Fastmail%20Auth.json#L4-L10
        {
          "WFWorkflowActionIdentifier": "dk.simonbs.DataJar.GetValueIntent",
          "WFWorkflowActionParameters": {
            "UUID": "9B76AD6E-10C1-4A4E-A9F0-7CE3F3A21D3D",
            "keyPath": "fastmail-config"
          }
        }
    vs the empty *.cherri file at https://github.com/vergenzt/shortcuts/blob/62b5893173eb1c7003f22f22efc849f5a4dd151e/src/Automation%20Utils/Fastmail%20Auth.cherri.

@electrikmilk
Copy link
Owner Author

Alright so a few updates!

  1. I was able to resolve that decomp branch Go compilation error via vergenzt@d45deae.
  2. I attempted to import all of my Shortcuts! 😄 There were a number of issues. You can view the results at https://github.com/vergenzt/shortcuts/tree/main/src. For the imports that succeeded, there is a *.cherri file in the repo next to the corresponding *.plist / *.json files (I included both for each Shortcut for ease of comparison). For imports that failed, there is a *.cherri-decompile.log file containing the stderr panic output.

There were a few issues I've noticed so far:

  1. There were quite a few panics. 😅 I haven't dug into the details yet.

  2. Custom actions seemed to not be extracted at all. E.g. the single custom action at https://github.com/vergenzt/shortcuts/blob/62b5893173eb1c7003f22f22efc849f5a4dd151e/src/Automation%20Utils/Fastmail%20Auth.json#L4-L10

        {
          "WFWorkflowActionIdentifier": "dk.simonbs.DataJar.GetValueIntent",
          "WFWorkflowActionParameters": {
            "UUID": "9B76AD6E-10C1-4A4E-A9F0-7CE3F3A21D3D",
            "keyPath": "fastmail-config"
          }
        }

    vs the empty *.cherri file at https://github.com/vergenzt/shortcuts/blob/62b5893173eb1c7003f22f22efc849f5a4dd151e/src/Automation%20Utils/Fastmail%20Auth.cherri.

Yeah, we should probably at least put a raw action if we don't know what the action is by default, fill in the gaps from there so that it's at least there if it's not a standard action.

@electrikmilk
Copy link
Owner Author

Btw it turns out that this comment is not true!

cherri/main.go

Lines 66 to 68 in 68974c0

if hasSignedBytes(shortcutBytes) {
exit("import: Unable to read Shortcut as it has been signed and the contents are encrypted.")
}

It's possible to extract the raw shortcut contents from signed shortcut files.

See https://theapplewiki.com/wiki/Apple_Encrypted_Archive:

Signed shortcuts are AEA files but they are actually not encrypted. The 32bit size for the AEA context can be found at location 0x8-0xB in the file, and the size plus 0x495c will be the starting location of an LZFSE compressed Apple Archive. (For an example of this, take a look at libshortcutsign's extract_aa_from_aea function.) After decompression, the magic number is the 4 ASCII characters "AA01".

I have an example of doing this using https://github.com/wader/fq for my own shortcuts repo I started a few weeks ago here:

https://github.com/vergenzt/shortcuts/blob/8c11c3856b2cc0b5db98e862c1737ac015b5ea05/lib/tasks/import.yaml#L31-L33

This is good stuff, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: 🏗 In progress
Development

When branches are created from issues, their pull requests are automatically linked.

2 participants