All C# actions have access to a Dictionary<string, object> propertry named args
This property contains all variables from the current argument stack, including variables from the event trigger or any custom arguments you may have populated with previous sub-actions.
CPH.TryGetArg(), added in Streamer.bot v0.2.3.args property directly in your code!In addition to TryGetArg<T>(), you can also safely check if an argument exists by utilizing the general C# methods ContainsKey() or TryGetValue().
// If %rawInput% exists, store it in rawInput
CPH.TryGetArg("rawInput", out string rawInput);
// Log the result
CPH.LogInfo($"Variable rawInput: {rawInput}");
string myVariable = args.ContainsKey("myVariable") ? args["myVariable"] : null;
// Log the result
CPH.LogInfo($"Variable myVariable: {myVariable}");
  // If arg doesn't exist, return false to stop execution
  if (!args.TryGetValue("rawInput", out object rawInputObj))
    return false;
  // Parse string value
  string rawInput = rawInputObj?.ToString();
  // Log the result
  CPH.LogInfo($"Variable rawInput: {rawInput}");
You can access global variables with the methods CPH.GetGlobalVar<T>() and CPH.SetGlobalVar<T>().
For example, to retrieve the value of a global variable named myGlobalVar as a string:
string myString = CPH.GetGlobalVar<string>("myGlobalVar", true);
To set the value of a global variable named myGlobalVar to a new string value, you can do the following:
CPH.SetGlobalVar("myGlobalVar", "some new value", true);
SetGlobalVar will create it for you.If a global variable does not exist, CPH.GetGlobalVar<T>() will return null.
You should always check for null before using the value:
string myString = CPH.GetGlobalVar<string>("myGlobalVar", true);
if (myString == null)
{
   //Do whatever would happen when the variable "test" would not exist
}
To immediately give a variable a default value when the global var does not exist you can use the null-coalescing operator ??
// Attempt to get global variable, if it does not exist, set it to "defaultValue"
string myGlobalVar = CPH.GetGlobalVar<string>("myGlobalVar") ?? "defaultValue";
Nullable<T> type or the shorthand T? syntax.// Using Nullable<T>
int myInt = CPH.GetGlobalVar<Nullable<int>>("myGlobalVar", true) ?? 0;
List<int> myIntList = CPH.GetGlobalVar<Nullable<List<int>>("testList",true) ?? new List<int>();
// Using T?
int myInt = CPH.GetGlobalVar<int?>("myGlobalVar", true) ?? 0;
List<int> myIntList = CPH.GetGlobalVar<List<int>?>("testList",true) ?? new List<int>();
When saving and getting global variables, you can use any data type that is serializable by the built-in JSON serializer.
This includes primitive types like int, string, bool, float, double, decimal and complex types like List<T>, Dictionary<TKey, TValue> and event custom classes.
At a certain level of complexity, such as deeply-nested Dictionary or List objects, you may run into issues where the serializer cannot properly serialize or deserialize the data.
The following example shows a complex nested data structure which can be safely saved and retrieved with the built-in serializer:
Dictionary<string,List<List<string>>> test = new Dictionary<string,List<List<string>>>();
//...
CPH.SetGlobalVar("complex", test, false);
Dictionary<string,List<List<string>>> testReturn= CPH.GetGlobalVar<Dictionary<string,List<List<string>>>>("complex", false)
If you have a complex data type, or custom class that cannot be serialized by the built-in serializer, you can use a custom serializer like Newtonsoft.Json, which is included in Streamer.bot by default.
Example using Newtonsoft.Json to serialize a custom class:
//Use the Newtonsoft.Json library
using Newtonsoft.Json;
//...
//Custom class
public class TestClass
{
  private string userName {get;set;}
  private Dictionary<string,string> userThings {get;set;}
}
//... Let's say I have a list of TestClass objects
List<TestClass> testList = new List<TestClass>(){...};
string jsonSaveString = JsonConvert.SerializeObject(testList);
CPH.SetGlobalVar("savingClass", jsonSaveString, true);
Special arguments eventSource and __source are enum values and must be accessed with their corresponding methods.