Creating a Maestro Interaction

In this tutorial, we will show you how to create a custom Maestro interaction with an input spec.

The interaction will be to get some input from Google Forms. We will not include the actual implementation of how to access Google Forms.

1. Creating the Class

The first step is to create a class library with a single class. Give the class a name like "AccessGoogleForm".

Make sure the namespace MyInteractions.Forms matches the class library (dll) name.

Write the following code first in AccessGoogleForm.cs:

using Dacris.Maestro;
using Newtonsoft.Json.Linq;

namespace MyInteractions.Forms;

public class AccessGoogleForm : Interaction
{
    public override void Specify()
    {
        InputSpec.AddInputs("formId", "startDate", "clientId", "clientSecretKey", "mockAnswers", "outputPath");
        InputSpec.StateObjectKey("startDate").WithSimpleType(ValueTypeSpec.Date);
        InputSpec.StateObjectKey("mockAnswers").ValueSpec = new ValueSpec
        {
            ValueType = ValueTypeSpec.Object,
            ObjectSpecs = [new InputSpec { Name = "@answerKey", ValueSpec = new ValueSpec { ValueType = ValueTypeSpec.String } }]
        };
    }

    public override async Task RunAsync()
    {
        if (AppState.Instance.IsMock())
        {
            // TODO: Implement a mock interaction that does not actually use HTTP
        }
        // Write out the responses to State
        // TODO: create the responses list and output it as array in the state:
        //AppState.Instance.WritePath(InputState["outputPath"]!.ToString(), new JArray(responses.ToArray()));

        System.Console.WriteLine("This is coming from my interaction");
    }
}

2. Explanation and More Details

First of all, please take a look at the provided sample project, SampleCustomLib, which includes a very basic interaction, to see how it's all set up.

All interactions inherit from the Interaction class.

Notice the Specify() method. This method is optional, in that you can leave it empty if you do not care to have a spec available in the Maestro Assembler.

Maestro Assembler uses the InputSpec provided in order to generate sample input state for you so that you don't have to write all that JSON manually.

What InputSpec specifies is the structure of the input coming from State.json for this interaction. Any data types and data structures are given.

Below is an example of input in State.json used by the AccessGoogleForm interaction.

{
  "inputObject":
  {
    "formId": "1",
    "startDate": "2023-01-01",
    "clientId": "999",
    "clientSecretKey": "",
    "outputPath": "$.formOutput"
  }
}

3. Integrating Your Library into Maestro

First, you need to copy your .dll file and all dependencies into the folder where LogicAppRunner.dll is located.

Next, you need to generate a Patterns folder for Maestro Assembler to use (so that it can see the spec of your interaction).

To generate patterns, you need to create a simple C# console app with the following code:

// Write out metadata to the "Patterns" folder
if (!Directory.Exists("Patterns"))
  Directory.CreateDirectory("Patterns");
await InteractionInputSpec.WriteAsync("Patterns", typeof(AccessGoogleForm).Assembly);

Note - You need to add your interaction library as a reference as well as Dacris.Maestro.dll. Also, don't forget to add corresponding usings.

Run your console app to generate the Patterns folder in the bin subfolder.

Finally, copy the contents of the Patterns folder that was generated to the "Patterns/Json" folder in your Maestro Assembler root folder (the folder having the Maestro Assembler executable).

4. Running a Test App

To run a test app with this interaction, try putting the code below in a file called SampleApp.txt. Don't forget to create a State.json.

alias Dacris.Maestro as the
alias MyInteractions as my

read state from file using the Core
access google form using my Forms with inputObject

Execute this test app using LogicAppRunner.dll and you will see a line on the console saying "This is coming from my interaction".