Skip to content

Releases: BOLL7708/desbot

v6.562 Setup & Reward Fixes

24 Oct 16:49
Compare
Choose a tag to compare

Fixes

  • Install script fixed so it adjusts the presets import path.
  • Fixed database retrieval so it doesn't return prepopulated default classes, but nothing, if the post did not exist.
  • Fix database migration always asking to migrate if latest migration version did not match widget version.
  • Updated readme with some details, hid links to outdated wikis for now.
  • Fixed accumulating reward messing up titles and failing to update,
    • Made it only cost the remainder at the end of the run.
    • Stopped price from going negative on final redemption.
  • Fix new counters getting the base class instead of their specific classes when saved to the database.

Known Issues

  • Users can get randomized an empty voice, I don't know why this happens and have not been able to replicate it off stream yet.
  • Some users don't get the Twitch authentication after installing the widget, could not replicate, yet.

v6.554 Here you go Jeppe, a Database!

11 Oct 18:45
Compare
Choose a tag to compare

Database Settings

This has been a month in the works, now all settings (as a first step, as outlined in the prior release) are now stored in a MariaDB database.

When you load the widget now, it will open the editor, which is not yet an editor, but it will let you set up the database and import your old settings, as well as login with your Twitch accounts. This comes with some steps in preparation though.

  1. You need a newer XAMPP with Maria DB 10.2 or later, for JSON support, and I'll recommend going for PHP 8.1 or higher as that is what I am running, and might use the features of in the future.
  2. For your configs, you will have to redo most imports, because I did a bunch of refactoring during this transition to database settings. This also means you need to delete the whole dist folder and rebuild it.

Then you just load the existing widget page and it will go through the setup, which hopefully will be explanatory enough to "just work", as it were. If not, make sure to tell me exactly where you got stuck, so I can improve the experience for future users.

On the last page of the setup you will see a link to the actual widget page. Yes, the default index is now the editor, and the widget URL/link is something you will have to update on your browser sources in OBS.

After that, you might also need to change references to label-files in OBS, text files with contents from the label action, as they have moved from the now defunct _settings into the new _data folder.

Other stuff?!?

  • Fix quotes ignoring entries with only one word.
  • Make redemption clearing delete redemptions that no longer exists on Twitch, instead of leaving them in the database forever.
  • Screenshots are now converted to 85% quality JPEGs before being sent to Discord, to avoid hitting the upload size limit.

v5.511 Reward Merging, Game Event Triggering & Plans

05 Feb 18:27
Compare
Choose a tag to compare

(this was a draft that was mistakenly never published, the release was made, but the release notes were forgotten as a draft for more than a year, no wonder nobody read about my plans...)

Updates

Event Options

Added rewardMergeUpdateConfigWithFirst to event options, this means reward properties when doing incrementing, accumulating or multi-tier events can use the first reward setup as a base, and merge the other setups on top of that.

Game Specific Events

The triggering of action entries should be fixed, I don't really know why the old code stopped working, but now it by default tries to merge the base event with the game specific event and should trigger all of that. It has only been briefly tested, so report any issues if you bump into them.

Fixes

A range of fixes, one was to try and prevent caching of the page to allow .js files to load fresh, hopefully that works. It became a necessity after switching to JS modules.

Plans

With time it has become apparent that it is not sustainable to keep the widget in this state and gain more users, as there is only one of me, and eventually there will only be helping, no more coding.

When even the software developers I know are users of the widget are hesitant to update due to config changes, that's a good sign things have to change. I've already started working on database support, and will start off with moving all settings into that, which means TTS settings, trophy registrations, achievements, etc.

Eventually this means the config should also go into the database, but that is a huge system-wide change, and it will take a lot of planning, time and effort to make it happen, much as it also requires a config editor to be able to use it. This means new features have been pushed into the future, as most if not all time working on this will go towards this user friendly experience.

As how it is expected to work, when things are in a database, I can supply releases with .sql files that are automatically run to migrate the user to the next release upon launching the widget. This is the plan anyhow, and I'm hopeful this will work out, eventually. Oh and if anyone wants to help with things like the config editor, don't hesitate to reach out, I'm mainly a backend developer after all.

v5.508 Imports & Help

04 Sep 21:37
Compare
Choose a tag to compare

Updates

Modules

A major change now is something to thank @jeppevinkel for, he didn't do it, but he tipped me off this existed. Most of the widget is now dynamically loaded by import/export modules supported by modern browsers. This means most files include import lines for whatever classes are used, like many other programming languages.

Imports can be easily auto-generated for any class that miss them by following the below instructions.

In Visual Studio Code

  1. Open Settings and change these two values:
TypeScript > Preferences
    Import Module Specifier: relative
    Import Module Specifier Ending: js
  1. On anything that needs to be imported, press CTRL + . and the import should have been added at the top of the file.

In IntelliJ

  1. Open Settings and change these two values:
Editor > Codestyle > TypeScript > Imports
    [x]: Use paths relative to tsconfig.json
    Use file extension: always ".js"
    Use path mappings from tsconfig.json: Never
  1. On anything that needs to be imported, press CTRL + ENTER and the import should have been added at the top of the file.

Twitch Category

  • Some games will not have a Steam title that match the Twitch Game registry, so there is a mismatch or no match at all. A table for overriding what is matched has been added.
  • I also renamed the default game category and moved it from Config.controller to Config.twitch.
Config.twitch = {
    defaultGameCategory: 'Games + Demos',
    gameTitleToCategoryOverride: {
        'Vermillion - VR Painting': 'Vermillion'
    }
}

Help

Commands can now include help properties.

Config.events = {
  '': {
    triggers: {
      entries: ['Hello'],
        helpTitle: 'Title that is used if posting the help to Discord to break up sections.',
        helpInput: ['first param', 'second param'],
        helpText: 'This is a description about how a command is supposed to be used.'
    }
  }
}

There are two new commands that can be used with the above, copy them from the template.

  • !posthelp - Will post all commands with help properties to the Discord webhook with the same key, from the template: HelpToDiscord
  • !help [command] - Will post help for the command to chat, uses the key: HelpToChat

Quote

If the user tag is left out when using !quote the configured channel name will be used instead, which is usually the streamer account, for convenience.

Dictionary

It is now possible to append and reduce a list of substitute words for a dictionary entry with the !word command.

  • !word test hello - will replace the current entry for test.
  • !word +test world - will add another word to the existing entry for test, replacement will be random.
  • !word -test world - will remove a word from the existing entry for test if a match was found.

Text Tags

  • Added eventLevelMaxShort which can be used for accumulating rewards for a shortened goal number.

Entries

  • Audio action srcEntries now has proper entries handling, meaning things like .userRandom() should now work.

Actions

User

The user object that is used in actions now contains inputWords, a complement to input, and it's simply input split on space. This is mostly used for development and the custom action.

System

The events action and rewardStates action has been consolidated into a common system action.

Config.events = {
  actionEntries: {
    system: {
      triggerCommandEntries: ['command'],
      triggerEventEntries: ['OneKey', 'OtherKey'],
      triggerInterval: 20,
      toggleRewardStates: { 'OneKey': { state: false } }
    }
  }
}

Event Options

Added a new option to ignore automatically posting of reward redemptions to key-referenced Discord Webhook.

  • rewardIgnoreAutomaticDiscordPosting

v5.493 Keys

22 Aug 13:17
Compare
Choose a tag to compare

This is a small big update. That means the release notes will be short, but it's a huge change, big enough to up the main version number again. Yep, shake in fear, dear end users.

Update

Keys

What was a class with static properties is now a type. This means you need to update !keys.ts and most of your configs. The templates have been updated accordingly. The install script has not been tested yet.

This change was done to make it easier to add new keys, to remove the need to both make a key name and a key value. Now they are both one and the same.

!keys.ts

What was this:

class Keys {
  static readonly A_KEY = 'KeyValue'
  static readonly ANOTHER_KEY = 'OtherKeyValue'
}

Is now this:

type TKeys =
  'Unknown'
  | 'KeyValue'
  | 'OtherKeyValue'

Configs

What does this mean for the rest of the configs? It means any place where a Keys.A_KEY was referenced, it should now be just 'KeyValue' instead. See example below.

What was this:

Config.events = {
  [Keys.A_KEY]: {}
}

Is now this:

Configs.events = {
  'KeyValue': {}
}

In short, you remove the square brackets and the Keys reference, then put the string value there instead.

Note: When using the array extensions, like .useRandom(), on an array of keys, the result loses the TKeys type, so we need to cast it to TKeys with <TKeys[]> in front, or with as TKeys[] behind. I will try to make this easier to use in the future.

Config.events = {
  'KeyValue': {
    actionsEntries: {
      events: {
        keyEntries: <TKeys[]> ['OtherKeyValue', 'AnotherKeyValue'].useRandom()
      }
    }
  }
}

v4.491 Reward States & Events Action

19 Aug 16:03
Compare
Choose a tag to compare

Fixes

Reward Toggling

If a reward is now in the main profiles or games profiles, it will not be overridden by a reward-per-game setting unless it is explicitly set. This has now changed twice.

  • Original: Rewards-per-game overrode anything if it was set in either on/off list, would set the flipped state the game didn't match.
  • Update to fix issue Doc had: Rewards-per-game only overrides profiles if the reward is in any of the lists, and only then.
  • Final: A mix, we still override with rewards-per-game on a match, but if a profile has set a state, we don't override it with the flipped value.

Updates

RewardStates Action

The action for changing the state of rewards on Twitch has been updated. It can now take an optional state, if not included it will toggle, and a value for if the state should override things like the profiles used for games.

[Keys.EXAMPLE]: {
  actionsEntries: {
    rewardStates: {
      [Keys.YOUR_REWARD]: {
        state: true, // Leave this out to toggle the current state
        override: true // Will store the state in the always on/off lists in the config
      }
    }
  }
}

Commands Action renamed to Events Action

The ability to trigger other commands have been expanded to also be able to trigger other events on their key, as such the action has been renamed.

[Keys.EXAMPLE]: {
  actionsEntries: {
    events: {
      commandEntries: ['one_command', 'another_command'],
      keyEntries: [Keys.ONE_KEY, Keys.ANTHER_KEY],
      interval: 20
    }
  }
}

Text Tags

These were added as I thought I needed them, but right now I'm not using them myself, so tell me if you find that they are not doing what you expect.

  • userMessage - The message provided by the user regardless if it was a command or prompted reward.
  • userInputWord1 - The first word from the user input
  • userInputWord2 - The second word from the user input
  • userInputWord3 - The third word from the user input
  • userInputWord4 - The fourth word from the user input
  • userInputWord5 - The fifth word from the user input

v4.486 Multi-Tier Behavior, Event Options Profiles & User Cooldowns

18 Aug 20:54
Compare
Choose a tag to compare

Fixes

  • Fixed TTS changes not being applied to actions in the same event.
  • Added missing accumulating reward settings load on init.
  • Fixed example audio configs in the template to have srcEntries.

New Stuff

User based cooldowns for commands

Commands had optional cooldowns, they were always global though, now you can set one cooldown for global and one for user. This means a single user has their own cooldown, so others can still trigger the command during that time.
If there is a global cooldown and a user cooldown, both are used. Meaning a user can not use the command if the global cooldown is still running, or, if they have their own personal cooldown running.

[Keys.EXAMPLE]: {
  triggers: {
    command: { // or remoteCommand
      entries: 'example',
      globalCooldown: 10,
      userCooldown: 5*60
    }
  }
}

Multi-Tier Event Behavior

This enables events that when triggered levels up, and if triggered again before a timeout will level up again, to the set maximum level. This will affect the index used, and it relies on .useSpecific() on your entries.

In any entries, index 0 will be what is called if the event is reset, when it times out, leave it as an empty object {} if it should do nothing. Then the one after that will be level 1, 2, 3 etc. The final level will be reused if there are no more.

[Keys.EXAMPLE]: {
  options: {
    behavior: EBehavior.MultiTier, // The new behavior
    multiTierTimeout: 30, // Number of seconds before it resets
    multiTierMaxLevel: 3, // The maximum level it can reach, if not set it will use the count of reward configs.
    multiTierDoResetActions: true, // Set this to trigger the first actions in the set when resetting.
    multiTierDisableWhenMaxed: true // Set this to hide the reward when it has reached maximum level.
  }
}

Event Option Overrides

It is now possible to configure overrides to values in Config.events.options, this is done in Config.twitch.eventOptionsDefault and eventOptionsPerGame, which are now default properties for Config.twitch and needs to be added. See the template for sample input for them.

Text Tags

With multi-tier events comes a number of new text tags associated with them.

  • eventLevel - Current level of the event
  • eventLevelNext - The next level of the event
  • eventLevelMax - The maximum level of the event
  • eventLevelProgress - A progress value for the event: x/y
  • eventLevelNextProgress - A progress value for the event using the next level: x+1/y

Cooldown Renamed

In the command and remoteCommand actions, cooldown has been renamed to globalCooldown.
This as we now have a secondary option, mentioned earlier: userCooldown.

Specific Index Option

This is an option in Config.events.options, set specificIndex to have .useSpecific() use that index if the event has no behavior set. This means you can make a custom action to modify what is in the config to have a reward act differently.

[Keys.EXAMPLE]: {
  options: {
    specificIndex: 1
  },
  actionsEntities: [
    { speech: { entries: 'one' } },
    { speech: { entries: 'two' } }, // Only this will be used now
    { speech: { entries: 'three' } }
  ].useSpecific()
}

v4.479 Relay & Move Space

15 Aug 09:26
Compare
Choose a tag to compare

I will try to do smaller and more frequent updates, as well, it melts my brain to save up too much and write release notes for all of it. Some features are just too big for that not to happen though! This time it's a small update.

This update requires at least version v1.43 of OpenVR2WS if you want to use the new features: Relay and Move Space.

New Features

Actions

Move Space

This new action will move your calibrated VR space. It can take properties for X, Y and Z, a boolean for if the Chaperone should be offset in the opposite direction, and a duration before it resets. All values are optional, with offsets , x, y, z defaulting to 0, the moveChaperone flag to true and if duration is not supplied there will be no reset.

[Keys.EXAMPLE]: {
  actionsEntries: {
    vrMoveSpace: {
      y: 0.5,
      duration: 1
    }
  }
}

Triggers

Relay

It is now possible to remote control the widget by using OpenVR2WS as a relay station. You can as an example install a Websocket plugin in your Stream Deck software and use that to activate triggers in the widget.

[Keys.EXAMPLE]: {
  triggers: {
    relay: 'your_key'
  }
}

And this is a sample payload to send to OpenVR2WS to activate this relay trigger.

{
  "key":"Relay",
  "value":"your_password",
  "value2":"a_twitch_username_to_act_as",
  "value3":"your_key"
}

See where to set the password in the next section.

Config Changes

Relay

For relays to work we use a common password, just so we can filter incoming messages if we want multiple channels of communication. The password is sent to every connect client so it would probably be better to call it channel, but this is it for now.

Config.credentials = {
  OpenVR2WSRelayPassword: 'your_password'
}

Commands, etc

Remote commands now use entries instead of the event key, just like standard commands:

{
  triggers: {
    remoteCommand: { entries: 'the_command' }
  }
}

An addition to this, is that the triggers for commands, remote commands and relay now all can be set to %eventKey to again use the event key (Keys.YOUR_KEY) as its value.

Action Rename

The action openVR2WS has been renamed to vrSetting, as that is what it was used for.
Another change is that world scale values are no longer handled as a decimal value but integers, meaning 0.5 is now 50.

v4.475 Entries & Accumulating Events

12 Aug 16:52
Compare
Choose a tag to compare

Version 4.x?

What is this, a new major version? This concludes something I sketched out back in May, so three months ago. The way events are triggered to activate a bunch of actions have been updated, now there's a handler in the middle that can handle weird behaviors, like incrementing, accumulating and random events.

A whole lot happened in this release, and I might have missed something. If you bump into any issues, please tell me and I might have to append these release notes. Thanks!

Note: This release moves files around a bit, so after pulling the changes, you should delete your dist folder and regenerate all files.

Config Changes

Commands no longer using keys as triggers

Due to commands now sharing their actions with rewards (and other triggers), it ended up becoming an issue to have the strings be used for both the key and the trigger for commands. Because of this, commands now need to list their triggers in the trigger setup.

[Keys.EXAMPLE]: {
  triggers: {
    command: {
      // These are entries so can take an array,
      // will always use all though as nothing else makes sense.
      entries: 'example'
    }
}

Note: This might beak some uses of keys, like in the end stream command, so keep an eye out for that.

Entries

A bunch of action configs contain fields that end in entries or are just that. These should all be handled in a specific way, as they can all be arrays and arrays have now been extended with a bunch of possible treatment properties.

{
  discord: { 
    // This additional call on the array will set its type, 
    // and in this case that means it will use a random value from the array.
    entries: ['First string', 'Other string'].useRandom()
  }
}

These are the available properties.

const arr1 = [].useAll() // The default, will use all of the entries
const arr2 = [].useRandom() // Will use one random entry from the array
const arr3 = [].useAllRandom() // Will use all entries but in a random order
const arr4 = [].useSpecific() // Will use one specific entry based on an index generated by special event behaviors.

Behaviors

Behaviors are special handling of event triggering, there are a few types available as you can see below:

/**
 * Various types of special event behavior.
 */
enum EBehavior { 
    All, // This is the default, all entries will be used.
    Random, // A random entry will be used.
    Incrementing, // An index will increment for each triggering, and the entry for that index will be used.
    Accumulating, // A count is accumulating, 
    // the first entry is triggered every time until we meat the goal, 
    // the second entry will be used when the goal has been reached.
    Multitier// TODO: Not implemented yet.
}

The above enum is set in the Event.options.behavior. See example below.

[Keys.EXAMPLE]: {
  options: {
    behavior: EBehavior.Incrementing
  }
}

Note: If you are using the new Accumulating behavior, you should also set the option accumulationGoal in Event.options.

Places that has changed to entries

Chat actions are now a proper config with an entries field.

actionsEntries: { // This also changed, more about this below
  chat: { entries: 'An entry' },
  web: { entries: ['All entries can be an array too'] },
  discord: { entries: ['And an array with', 'the type for behavior'].useRandom() },
  remoteCommand: { entries: '!acommandentry' },
  lights: { entries: {x: 1, y: 1} },
  audio: { srcEntries: '_assets/asource.wav' },
  pipe: {
    imagePathEntries: ['Path1', 'Path2'],
    imageDataEntries: 'imagedata'
  }
}

Actions

Entries

As mentioned for other things, Event.actions is now Event.actionsEntries to adhere to the entries scheme. It can also take the use calls to act with the event behavior. It is now simply a single IActions object, or an array of them, and that array can use the behaviors.

[Keys.EXAMPLE]: {
  actionsEntries: [
    { speech: { entries: 'One' } },
    { speech: { entries: 'One' } }
  ].useRandom()
}

Actions that no longer accept arrays of configs

This is a change due to actions themself being able to be handled in accordance with the event behavior, this reduces complexity. Basically, instead of having arrays of configs in one actions object, we have an array of actions objects.

  • openVR2WS
  • obs
  • pipe
  • lights
  • chat

Timelines are no more

While timelines were nice, they were also limited in usability. For one they only supported absolute timestamps, not relative delays. This is now changed, and these values are now additional properties for the IAction interface.

These will run in the order they are listed if using _delayMs, or in the order of their absolute _timeMs value. If there is a mix, any time a _timeMs value is used, it will reset whichever time _delayMs had set prior, and the next _delayMs will then add to that time.

[Keys.EXAMPLE]: {
  actionsEntries: [
    { 
      _timeMs: 1000, // Will happen after one second
      chat: { entries: 'Hello' } 
    },
    { 
      _delayMs: 2000, // Will happen two seconds after the previous action that set a time (or 0 if none)
      chat: { entries: 'Bye' } 
    }
  ]
}

The exec action has been split up

The exec action would do both key presses in application windows and execute custom URIs. This have now been split up in two other actions.

[Keys.EXAMPLE]: {
  keys: {}, // see IPressKeysAction
  uri: { entries: 'custom://something' }
}

SpeechReferences

With a new command we should add a few speech references for it.
Check for Config.controller.speechReferences in the config.template.ts file, and copy that speech reference to your config.

Subscription announcements

This is a bit work in progress as I don't know how to get all values yet, will see how this works out.

Config.twitch.announceSubs = [
   // Check the config.template.ts file for a full list of these.
  { tier: 0, gift: false, multi: false, message: '%userTag subbed with Prime' }
]

Text Tags

To support accumulating events, a few additional text tags were added.

  • eventKey // The key from Keys associated with this event.
  • eventCost // If it was a reward, what it cost.
  • eventCount // The current accumulating value for this event.
  • eventCountPercent // The current accumulating progress in percent.
  • eventGoal // The goal for accumulation, if set.

Keys

Refactor: COMMAND_RESET_INCREWARD into COMMAND_RESET_INCREMENTING_EVENTS
Add: COMMAND_RESET_ACCUMULATING_EVENTS

Settings

The file for counters for incrementing rewards have changed. It was twitch_reward_counters.csv, but is now event_counters_incremental.csv.

v3.465 Hotifx & Command Entries

03 Aug 21:31
Compare
Choose a tag to compare

The previous hotfix wasn't hot enough, so here's another.

It turns out combining rewards and commands with the same key used for both resulted in chaos, so now I've split things up so keys for commands are now just keys, and not used for the commands themselves.

Templates have been updated accordingly. This is a fairly major change in a tiny update, sorry! 😅

Config Changes

{
  command: {
    entries: ['hello', 'hi', 'yo'] // This can be either a single string, or an array of string.
  }
}