C# Scripting
Write powerful scripts using C# with full .NET support, strong typing, LINQ, and access to the entire .NET ecosystem.
Overview
C# is a powerful, statically-typed language that provides excellent IDE support, robust error handling, and access to the full .NET framework. It's ideal for complex scripts that benefit from strong typing and advanced features.
Strong Typing
Catch errors at compile time with static type checking.
LINQ Support
Query and transform data with elegant LINQ expressions.
.NET Libraries
Access System.*, JSON parsing, HTTP, and more.
IDE Support
Full IntelliSense and debugging in external editors.
When to Use C#
- Complex data processing and transformations
- Integration with .NET libraries
- Scripts that benefit from strong typing
- Large scripts with multiple helper classes
- When you need advanced async/await patterns
Setup
C# scripting requires the Mono runtime, which is included with FaustBot. No additional setup is required.
Create a C# Script
In your action, add a Run Script effect and select C# as the language.
Write Your Code
The script must contain a CPHInline class with an Execute() method.
External Editing (Optional)
For complex scripts, save the file externally and use Visual Studio or VS Code for full IntelliSense support.
Script Structure
C# scripts follow a specific structure with a class containing the entry point method.
using System;
public class CPHInline
{
public bool Execute()
{
// Your code here
CPH.SendMessage("Hello from C#!");
return true;
}
}Available Objects
These objects are automatically available in your scripts:
| Object | Description |
|---|---|
CPH | Main API object for all FaustBot functionality |
args | Dictionary containing trigger event data |
Type Safety
C# provides strong typing for variables, giving you compile-time error checking and better IDE support.
public bool Execute()
{
// Strongly typed variable access
string username = args["user"].ToString();
int points = CPH.GetUserVar<int>(username, "points", 0);
DateTime lastSeen = CPH.GetUserVar<DateTime>(username, "lastSeen");
// Type-safe global variables
int totalFollowers = CPH.GetGlobalVar<int>("totalFollowers", 0);
List<string> recentUsers = CPH.GetGlobalVar<List<string>>("recentUsers");
// Set with proper types
CPH.SetUserVar(username, "points", points + 100);
CPH.SetGlobalVar("lastActivity", DateTime.Now, true);
return true;
}Common Types
| Type | Use Case |
|---|---|
string | Text, usernames, messages |
int | Whole numbers, points, counts |
double | Decimal numbers, percentages |
bool | True/false flags |
DateTime | Timestamps, dates |
List<T> | Collections of items |
Dictionary<K,V> | Key-value mappings |
.NET Features
LINQ Queries
Use LINQ for powerful data querying and transformation.
using System.Linq;
using System.Collections.Generic;
public class CPHInline
{
public bool Execute()
{
// Get all users with more than 1000 points
var topUsers = GetAllUsers()
.Where(u => u.Points > 1000)
.OrderByDescending(u => u.Points)
.Take(10)
.ToList();
// Format leaderboard
var leaderboard = topUsers
.Select((u, i) => $"{i + 1}. {u.Name}: {u.Points} pts")
.Aggregate((a, b) => $"{a} | {b}");
CPH.SendMessage($"Top 10: {leaderboard}");
return true;
}
private List<UserData> GetAllUsers()
{
// Implementation here
return new List<UserData>();
}
}Async/Await
Handle asynchronous operations cleanly with async/await patterns.
using System;
using System.Threading.Tasks;
public class CPHInline
{
public bool Execute()
{
// Run async operation synchronously
var result = FetchDataAsync().GetAwaiter().GetResult();
CPH.SendMessage($"Got result: {result}");
return true;
}
private async Task<string> FetchDataAsync()
{
// Simulate async work
await Task.Delay(100);
// Make HTTP request
var response = await CPH.HttpGetAsync("https://api.example.com/data");
return response;
}
}JSON Handling
Parse and create JSON using System.Text.Json or Newtonsoft.Json.
using System;
using System.Text.Json;
public class CPHInline
{
private class ApiResponse
{
public string Status { get; set; }
public DataPayload Data { get; set; }
}
private class DataPayload
{
public string Name { get; set; }
public int Value { get; set; }
}
public bool Execute()
{
// Parse JSON response
string json = CPH.HttpGet("https://api.example.com/data");
var response = JsonSerializer.Deserialize<ApiResponse>(json);
if (response?.Status == "success")
{
CPH.SendMessage($"Got: {response.Data.Name} = {response.Data.Value}");
}
// Create JSON
var outData = new { user = args["user"], timestamp = DateTime.UtcNow };
string outJson = JsonSerializer.Serialize(outData);
CPH.SetArgument("jsonOutput", outJson);
return true;
}
}Advanced Patterns
Helper Classes
Define helper classes within your script for better organization.
using System;
using System.Collections.Generic;
public class CPHInline
{
// Helper class for structured data
private class UserStats
{
public string Username { get; set; }
public int Points { get; set; }
public int WatchTime { get; set; }
public DateTime FirstSeen { get; set; }
public string GetRank()
{
if (Points >= 10000) return "Legend";
if (Points >= 5000) return "Elite";
if (Points >= 1000) return "Veteran";
return "Newcomer";
}
}
public bool Execute()
{
string user = args["user"].ToString();
var stats = new UserStats
{
Username = user,
Points = CPH.GetUserVar<int>(user, "points", 0),
WatchTime = CPH.GetUserVar<int>(user, "watchTime", 0),
FirstSeen = CPH.GetUserVar<DateTime>(user, "firstSeen")
};
CPH.SendMessage($"{stats.Username} is a {stats.GetRank()} with {stats.Points} points!");
return true;
}
}Error Handling
Use try-catch blocks for robust error handling with specific exception types.
using System;
public class CPHInline
{
public bool Execute()
{
try
{
// Main logic
string user = args["user"]?.ToString()
?? throw new ArgumentNullException("user");
int amount = ParseAmount(args["message"]?.ToString());
ProcessReward(user, amount);
return true;
}
catch (ArgumentNullException ex)
{
CPH.LogError($"Missing required argument: {ex.ParamName}");
return false;
}
catch (FormatException ex)
{
CPH.SendMessage("Invalid number format. Usage: !reward <amount>");
return false;
}
catch (Exception ex)
{
CPH.LogError($"Unexpected error: {ex.Message}");
CPH.LogError(ex.StackTrace);
return false;
}
}
private int ParseAmount(string input)
{
if (string.IsNullOrWhiteSpace(input))
throw new FormatException("Amount is required");
return int.Parse(input.Trim());
}
private void ProcessReward(string user, int amount)
{
int current = CPH.GetUserVar<int>(user, "points", 0);
CPH.SetUserVar(user, "points", current + amount);
CPH.SendMessage($"Gave {amount} points to {user}!");
}
}External Libraries
You can reference external .NET assemblies in your scripts.
// Reference external assemblies at the top
// #r "path/to/MyLibrary.dll"
using System;
using MyLibrary;
public class CPHInline
{
public bool Execute()
{
// Use external library
var helper = new MyHelper();
var result = helper.ProcessData(args["message"].ToString());
CPH.SendMessage(result);
return true;
}
}Library Tips
- Place DLLs in the FaustBot plugins directory
- Use NuGet packages by downloading the DLL
- Ensure library targets .NET Standard or compatible framework
- Test library compatibility before using in production