-
-
Notifications
You must be signed in to change notification settings - Fork 1
Development
Open the solution project in your IDE of choice and install the
dependencies and resolve the project using
dotnet restore SubathonManager.sln
When you build and run locally through your IDE,
you should be running SubathonManager.UI as the main project.
The design is documented in this drawio diagram. Right-click the link and select "save lined content as" to download.
You can view renders of the diagram here.
It contains the overall flow, flow per service, db organization, enums, config, and websocket data.
If you make any new changes that require updates to the design, detail them in your pull requests such that we can update it in the source.
Please submit a github issue if you have a bug or feature request.
For bugs, if requested, you may be asked to attached a logfile as well, which you can get from opening the data folder from the settings page, and going to the logs directory.
Please check if an issue or feature request exists similar to yours before submitting!
For all pull requests, they must tie to an issue or enhancement before they will be reviewed.
For fixes or new features, please describe in detail use cases or situations your changes will affect and, if possible, provide screenshots or recordings of said change.
Maintainers will review all PR's prior to merging.
If you are submitting a new preset to include, please make sure your PR only includes net-new files in the presets folder.
Ideally, if you make your own preset widget(s), that you would like to share freely, you can have them in your own repo and link to this project.
We would like to have a diverse set of presets in the base project, but also want to avoid bloating it for users. Eventually, we may create a list of overlays linked within the wiki here. So submit an issue or discussion for these! We'd love to see them.
We support external services that are not native to be integrated into the Subathon Manager.
Specifically, external commands, ExternalDonation's, and ExternalSub's.
POST /api/data/control
{
"user": "name", // string, optional. Defaults to "External"
"command": "CommandName", // string, must match a SubathonCommandType Enum Name. Required.
"message": "", // string, command parameters or empty - required.
"type": "Command" // required
}The commands will be processed through the CommandService, so formatting for message parameters will be the exact same as if it were from a Twitch or Youtube Chat command. See Usage - Commands for details.
POST /api/data/control
{
"user": "name", // string, optional. Defaults to "External"
"currency": "USD", // string. any valid 3 char currency code. Required.
"amount": "12.34", // float as string. Required.
"type": "ExternalDonation", // required
"id": "5fa57900-a69d-4944-9ff1-64c25801fb62" // guid. optional - if you want to persist a unique guid from your service.
}
External donations are accepted and will follow the configuration value for seconds/points per dollar unit of default currency after conversion. Exception to configuration value will be certain overrides, such as KoFiDonation.
user of "SYSTEM" will treat it as a Simulated event source instead of External.
POST /api/data/control
{
"user": "name", // string, optional. Defaults to "External"
"amount": 1, // int, optional. Default 1. This is number of "subs". Like if it were a mass gift of subs.
"value": "Tier 1", // string, optional. Will be used for logging and informational display reasons. If empty, will be "External".
"seconds": 60, // int. Required. Can be 0. How many seconds should this event add?
"points": 1, // int. Required, Can be 0. How many points should this event add?
"type": "ExternalSub", // required
"id": "5fa57900-a69d-4944-9ff1-64c25801fb62" // guid. optional - if you want to persist a unique guid from your service.
}External subscriptions or memberships are accepted. They will require (unless exception, such as KoFiSub override) seconds to add and points to add to be supplied, as no in-app configuration exists. It will be affected by active multipliers.
user of "SYSTEM" will treat it as a Simulated event source instead of External.
We support a way to remotely fetch and reconfigure the seconds or points of most EventTypes.
GET /api/data/values
[
{
"eventType": "TwitchSub",
"source": "Twitch",
"meta": "1000",
"seconds": 60,
"points": 1
},
{
"eventType": "TwitchSub",
"source": "Twitch",
"meta": "2000",
"seconds": 120,
"points": 2
}
//...
]Will return all subathon values that have a points or seconds configuration, along with their source and meta data.
The format it comes in will also be used to send PATCH/POST/PUT requests to update it.
PATCH /api/data/values
POST
PUT
payload
[
{
"eventType": "TwitchSub",
"source": "Twitch",
"meta": "1000",
"seconds": 20,
"points": 1
}
]You can send any number of values to update, and it will only modify those provided. Seconds or Points can be absent (but one must be present) - absent on will not be updated.
Meta must be included, but for most will be an empty string. It is primarily for Subs/Memberships that have a tier name/value.
EventType and Source are required.
Any changes done via the remote PATCH will be logged (depending on configuration) to the Error log Webhook URL (ignore the name).
GET /api/data/amounts
View a summary of all event amounts that have come in, such as number of subs of X type, total dollars per currency, etc.
All events properly processed by the subathon. It will be split with "real" and "simulated"/"system" events.
Partial example - it only shows value things that have come in.
{
"simulated": {
"DonationAdjustment": {
"CAD": -138990
},
"TwitchCheer": 15300,
"TwitchCharityDonation": {
"CAD": 310
},
"TwitchSub": {
"T1": 100
},
"TwitchGiftSub": {
"T1": 1595,
"T2": 240,
"T3": 50
},
"TwitchRaid": {
"count": 2,
"total_viewers": 50
},
"YouTubeSuperChat": {
"CAD": 20
},
"YouTubeMembership": {
"DEFAULT": 1
},
"YouTubeGiftMembership": {
"DEFAULT": 199
}
},
"real": {
"TwitchFollow": 1,
"ExternalDonation": {
"USD": 119057.12
}
}
}GET /api/data/status
Get the current status of the subathon.
Ex
{
"millis_cumulated": 2231441768,
"millis_elapsed": 11652000,
"millis_remaining": 2219789768,
"total_seconds": 2219789,
"days": 25,
"hours": 16,
"minutes": 36,
"seconds": 29,
"points": 2754,
"is_paused": true,
"is_locked": false,
"is_reversed": false,
"multiplier": {
"running": false,
"apply_points": false,
"apply_time": false,
"is_from_hypetrain": false,
"started_at": "2025-12-21T18:05:06.9150335",
"duration_seconds": 0,
"duration_remaining_seconds": 0
}
}