ChasterSharp is a lightweight C# wrapper for the Chaster.app API, designed to provide a foundational framework for building more advanced clients and applications on top of it. The intended use case of this framework is to support bots and other service integrations to interact with Chaster directly, as opposed to extending Chaster's functionality via the Extensions API. As such, support for partner extensions will be limited if available at all.
This project is currently under active development, and breaking changes to the API may occur frequently. Please be aware that any code relying on this API may need to be updated accordingly.
All service calls are handled through the ChasterClient type, simply initiate one with a HttpClient instance and an API auth token.
HttpClienthttpClient=new();ChasterClientchasterClient=new(httpClient,CHASTER_AUTH_TOKEN);You can then perform actions on the current user's lock(s), such as adding time.
varpersonalLocks=awaitchasterClient.GetLocksAsync(UserLockStatus.Active);if(personalLocks.Valueisnull)return;foreach(varpersonalLockinpersonalLocks.Value){awaitchasterClient.AddLockTimeAsync(personalLock.Id,60*60*24);//Add 24h to lock}The API coverage is pretty good, including undocumented functionality such as sending wearers to the pillory.
varsearchDto=newKeyholderSearchLocksDto(){Status=KeyholderSearchLocksDtoStatus.Locked,};//There is potential pagination here, but you get the ideavarkeyholderLocks=awaitchasterClient.SearchLockedUsersAsync(searchDto);if(keyholderLocks.Valueisnull)return;foreach(varkeyholdeLockinkeyholderLocks.Value.Locks){string?pilloryExtensionId=keyholdeLock.Extensions.FirstOrDefault(x =>x.GetExtensionSlug()==ExtensionSlug.Pillory)?.Id;if(string.IsNullOrEmpty(pilloryExtensionId))continue;//Pillory extension not foundif(keyholdeLock.IsFrozen)awaitchasterClient.PilloryLockAsync(keyholdeLock.Id,pilloryExtensionId,"for being frozen",60*10);}In some cases you will encounter properties with a type of JsonElement as opposed to a strongly typed class. This is because the object for these properties are dynamic and have different structures (e.g., Config, Payload, and UserData). The intended handling in these cases is to determine the object type either from a sibling property, or by a property within the JsonElement itself. You can then deserialize to a common type via JsonElement.Deserialize(obj) and, inversely, serialize to a JsonElement using JsonSerializer.SerializeToElement(obj).
publicstaticasyncTaskUpdateDiceExtension(ChasterClientclient,LockForKeyholderkeyholderLock,intdiceMultiplier){if(!keyholderLock.Trusted)return;//Not trusted, so we can't modify extensionsvardiceExtension=keyholderLock.Extensions.FirstOrDefault(x =>x.GetExtensionSlug()==ExtensionSlug.Dice);if(diceExtensionisnull)return;//Dice extension not foundvardiceExtensionConfig=diceExtension.Config.Deserialize<DiceConfig>()!;diceExtensionConfig.Multiplier=diceMultiplier;diceExtension.Config=JsonSerializer.SerializeToElement(diceExtensionConfig);vareditExtensionsDto=newEditLockExtensionsDto(){Extensions=ToLockExtensionConfig(keyholderLock.Extensions)};awaitclient.UpdateLockExtensionsAsync(keyholderLock.Id,editExtensionsDto);}publicstaticList<LockExtensionConfigDto>ToLockExtensionConfig(List<ExtensionPartyForPublic>extensions){varconfigs=newList<LockExtensionConfigDto>();foreach(varextensioninextensions){configs.Add(newLockExtensionConfigDto(){Slug=extension.Slug,Config=extension.Config,Mode=extension.Mode,Regularity=extension.Regularity});}returnconfigs;}It's important to keep in mind that this project is intended as a foundation for more sophisticated clients. Transient HTTP errors are inevitable and you should take steps to retry failed API calls, a package such as Polly may be a good solution here.
Furthermore, it is quite burdensome to perform more complex tasks such as updating extensions on a lock. For these reasons, it is important for you to build functionality on top of this base rather than relying on it soley.
Contributions are encouraged! Whether it's refining existing features, adding new functionalities, or enhancing documentation, your contributions can help enrich the framework for the entire community. Consider joining our Discord server if you are interested in helping.