-
Notifications
You must be signed in to change notification settings - Fork 3
Home
This is a small wiki to describe how to develop for this project, instructions on how to use the widget are here: Streaming Widget Wiki
The project has a number of modules and states that are initiated in their respective singletons at launch: ModulesSingleton
and StatesSingleton
.
These can be accessed in other places of the code like so:
const modules = ModulesSingleton.getInstance()
const states = StatesSingleton.getInstance()
Keep in mind to not access other modules in your own module's constructor, as the order of instantiation can change. That said, the singleton is instantiated at the beginning of execution, so any access outside the constructor should in most cases be fine.
The main way to add functionality to the project is by writing a module. These are usually classes that we instantiate in the modules singleton. There are a few steps to make modules accessible to an end user.
- Add a module source file to
./src/modules/
, anything in here will get transpiled and then included at runtime. - Write your module, it's fine to have it either as a static class (only static function) or something that needs to be instantiated in the singleton.
- If the module is non-static, add a property for it in
./src/modules_singleton.ts
, e.g:class ModulesSingleton { public yourModule = new YourModule() ... }
This should mean your module is now ready to be interacted with by other code.
To allow for an end user to trigger things in your module, we need to add an action for it, this can then be set up in the config by the user. This is a multi-step process:
- Add a new interface for your module by creating a new file in
./src/interfaces/
, in it we will add at least a config interface, which will be the object to setup to run the module, e.g:interface IYourConfig { // Mandator parameters setupParam1: string setupParam2: number // Optional parameters optionalSetupParam1?: boolean optionalSetupParam2?: { [key: string]: string } }
- Add the property for this config to the main event interface in
./src/interfaces/ievents.ts
. Add your config as a property toIEvent.actions
and make it optional, e.g:interface IEvent { actions: { yourConfig?: IYourConfig // or yourConfigWithIncrementalRewardSupport: IYourConfig|IYourConfig[] ... } ... }
- Create an action callback builder in
./src/actions.ts
, the builder can take a few parameters that are supplied to all actions when executed, e.g:There are a few more considerations if your action supports the incremental reward type. It's fairly specialized, but here is an example:public static buildYourCallback( config: IYourConfig|undefined, key: string // Optional input in case you need to know the key ): ITwitchActionCallback|undefined { if(config) return (user: IActionUser) => { // If your module needs to have an instance const modules = ModulesSingleton.getInstance() modules.yourModule.yourPublicFunction(singleConfig, user, key) // user and key are additional data that can be useful // If your module is all static functions YourModule.yourPublicStaticFunction(singleConfig) } }
public static buildYourIncrementalCallback( config: IYourConfig|IYourConfig[]|undefined, // Note array type ): ITwitchActionCallback|undefined { if(config) return (user: IActionUser, index?: number) => { // Note index const singleConfig = Utils.randomOrSpecificFromArray(config, index) // Random if index is undefined if(singleConfig) { const modules = ModulesSingleton.getInstance() modules.yourModule.yourPublicFunction(singleConfig) // or YourModule.yourPublicStaticFunction(singleConfig) } } }
- Use your build to build a callback in
Actions.buildActionCallback()
, add a property for your action, e.g:// The actions come from the triggered IEvent, the key is something to use if you need it. const yourCallback = this.buildYourCallback(actions?.yourConfig, key)
- If you want to see it logged, add something to notify that your new action has been registered in a callback, also in
Actions.buildActionCallback()
, e.g:Utils.logWithBold( ... +(yourCallback?'😁':'') // Will add the emoji if callback is set ... )
- Finally, add the execution of the callback if it exists, this is done in a separate callback that this builds. It's callbacks in callbacks, hurray! See the bottom of
Actions.buildActionCallback()
and add your callback, e.g:return async (user: IActionUser, index?: number, msg?: ITwitchPubsubRewardMessage) => { ... // Runs your module callback if(yourCallback) yourCallback(user) // Alternatively with the index, if it supports incremental rewards if(yourCallback) yourCallback(user, index) ... }