Skip to content

Latest commit

 

History

History
360 lines (275 loc) · 9.18 KB

scripts.md

File metadata and controls

360 lines (275 loc) · 9.18 KB

Scripts (Advanced)

Scripts can be used to create advanced type of triggers / chains of your media.

A script can have pre-defined variables (to be changed outside of the script).

If you need calculated variables that don't need to be changed on each call, you do / add them inside the Bootstrap Script. You need to return them like that:

return {myVar, andOtherVar, andSoOn};

The Execution Script which is called each time per trigger, does the actual "stuff".

Note: Scripts are handled inside the Backend, so there is no availability of Browser-Functions like alert and other stuff. But mostly everything else in JS can be used.

Script Examples can be found here

Pre-Defined Variables

Script Types Variable Name Description
both variables It holds all values of your added Custom Variables
both store See the Store-Documentation
both sleep Check Sleep API below
both logger Check Logger API below
both obs Check OBS API below
both memebox Check MemeBox API below
both utils Check Utils API below
both twitch Check Twitch API below
both eventbus Check EventBus API below
both process Check Process API below
both rxjs rxjs.* and rxjs.operators https://rxjs.dev/guide/operators
Execution Script bootstrap It holds all values of your Bootstrap Script
Execution Script triggerPayload Check Trigger payload below. It has the current information of the action trigger.
only Permanent Scripts wss Create your custom websocket server - Check WSS API below

Sleep API

If you need to wait for X seconds or ms you can use this:

await sleep.secondsAsync(X)
await sleep.msAsync(Y);
await sleep.for(X, sleep.TYPE.MS);

// also you can use
sleep.TYPE.SECONDS
sleep.TYPE.MINUTES

Logger API

logger.log('Something', 1234)
logger.error('er')

Obs API

obs.connectIfNot(); // tries to connect if it currently isn't
obs.isConnected();

obs.getFilter('SourceName', 'FilterName')
  .updateEnabled(true / false)

obs.replaceBrowserSourceUrl('browserSourceName', 'newUrl')
obs.refreshBrowserSource('browserSourceName')

// in permanent scripts
obs.onEvent$('eventName') // to subscribe to changes

obs.raw the commands/docs of OBS WebSocket (js) and Plugin 4.9

OBS WebsocketJS https://github.com/obs-websocket-community-projects/obs-websocket-js/tree/v4

OBS Protocol: https://github.com/Palakis/obs-websocket/blob/4.x-current/docs/generated/protocol.md

WSS API

Note: This only works inside Permanent Scripts

// creates a new websocket server running at port: 1337
const myWSS = wss.createWSS({
  port: 1337
});

logger.log('address: ', myWSS.address())

myWSS.on('connection', function connection(ws) {
  
  // the normal websocket client reference
  ws.on('message', function incoming(message) {
    logger.log('received: %s', message);

    ws.send('result: '+ message);
  });

  ws.send('something');
});


// can also use to connect to a websocket
const wsClient = ws.connect('address');  

wsClient.on / wsClient.send

MemeBox API

// Get your action by ActionID and ScreenId (use the button "Add action at cursor")
const myActionVar = memebox.getMedia(
  'cab50f01-2cd5-4797-9c7b-40dc3217272d',
  '696f0c9a-bf99-42c2-becf-45e0efa87fbe'
);

// memebox.getAction for everything, that doesn't need `triggerWhile`

// only for media: trigger it and have it visible all the time, 
// while this (callback) code is running 
// the await part is a promise and it will wait until this media is hidden again
await myActionVar.triggerWhile(async (helpers) => {
  await sleep.secondsAsync(1);

  // move your media to these positions, this is done in a transition (animation)
  await myActionVar.updateScreenOptions({
    position: enums.PositionEnum.Absolute,
    top: '10%',
    left: '15%'
  })

  await sleep.secondsAsync(2);

  await myActionVar.updateScreenOptions({
    position: enums.PositionEnum.Absolute,
    top: '40%',
    left: '35%'
  });
  
  await sleep.secondsAsync(2);

  // if none of these helpers are called, the last change of "updateScreenOptions" will be still applied
  helpers.resetAfterDone(250);
  // helpers.reset()    
  // ^ this resets the media while its still "visible", 
  // so it might break the previous animation flow
}, 
  // the options to trigger this media,
  // for example here with a custom variable value
  {
  action: {
    variables: {
      text_to_show: "This is the first message"
    }
  }
});

// these can be used for actions and media
// just a simple memebox action trigger (with variables example)
await myActionVar.trigger({
  // all properties optional
  
  action: {      // see action Overrides
    variables: {
      text_to_show: "This is the second message"
    }
  },

  screenMedia: {
    position: enums.PositionEnum.Centered,
    width: '300px',
    height: '200px'
  }
});

// simple trigger without anything
await myActionVar.trigger();

action Overrides

interface ActionOverridableProperties {
  variables?: Dictionary<unknown>;     // the variables inside scripts / widgets
}

updateScreenOptions or screenMedia overrides

interface ScreenMediaOverridableProperties {
  visibility: VisibilityEnum;
  loop?: boolean;

  // later some other settings like position and stuff
  width?: string; // 60%, 720px
  height?: string;

  // todo extract position to its own object
  position?: PositionEnum;
  left?: string;
  right?: string;
  bottom?: string;
  top?: string;
  transform?: string;
  imgFit?: string;

  /**
   * If you are in a script and currently animation all stuff in "triggerWhile" then you can
   * use this to prevent transition between those settings "updates"
   */
  animating?: boolean;

  animationIn?: string | null;
  animationOut?: string | null;

  animationInDuration?: number,
  animationOutDuration?: number,

  zIndex?: number;

  customCss?: string;
}


// in scripts usable by enums.PositionEnum
enum PositionEnum {
  FullScreen,
  Absolute,
  Centered,
  Random
}

enum VisibilityEnum {
  Play = 0,
  Static,
  Toggle
}

Utils API

utils.randomElement(array)  // returns a random element

Twitch API

twitch.getBroadcasterIdAsync() 

twitch.getHelixDataAsync('chat/emotes?broadcaster_id=123456')  // see Helix API Docs https://dev.twitch.tv/docs/api/reference#get-channel-emotes

twitch.say(messageToWriteInChat);

EventBus API

This eventbus is to be used between scripts and widgets (not implemented yet). So that more advanced stuff can be done.

const eventsToSubscribe = ['MYSCRIPT_EVENTX'];

eventBus

const {debounceTime, tap} = rxjs.operators;

// on$ returns an rxjs Observable, which you can use your operators on
// https://rxjs.dev/guide/operators 
eventBus.on$(eventsToSubscribe)
  .pipe(   // pipe is optional only if you want to use rxjs operators
  debounceTime(),
  tap()
)
  .subscribe((e) => {
  // e.type is your event as string
  // e.payload the data that was sent to it
})

eventBus.send('MYSCRIPT_EVENTX', {
  myObject: {   // everything inside this object is the `e.payload`
    data: true
  }  
})

Process API

If you need to start a bunch of apps for example or only one on an action then you can use this

process.spawn(`C:\\WINDOWS\\system32\\notepad.exe`);

Trigger payload

The triggerPayload variable holds all the data about what/who triggered the script. An example of the data returned when the script is triggered by a chat message command:

{
  "id": "db4cc5f3-2e7e-400c-a2db-bcf20398a434",
  "uniqueId": "5f4f1a08-2320-4414-af78-fb694e4105fe",
  "targetScreen": "",
  "origin": 3,
  "originId": "a4d2776d-e27a-4cb8-b86b-273a070c09f1",
  "byTwitch": {
    "timestamp": "2022-05-20T22:54:17.885Z",
    "payload": {
      "channel": "#gacbl",
      "self": false,
      "message": "!cnt",
      "userstate": {
        "badge-info": { "subscriber": "19" },
        "badges": { "broadcaster": "1", "subscriber": "3012", "glhf-pledge": "1" },
        "client-nonce": "42820cad6af02ef7fb567eb1644d4f9a",
        "color": "#1E90FF",
        "display-name": "GacBL",
        "emotes": null,
        "first-msg": false,
        "flags": null,
        "id": "cd998b3b-0495-485b-9226-e66c49225cdf",
        "mod": false,
        "room-id": "120572949",
        "subscriber": true,
        "tmi-sent-ts": "1653087364485",
        "turbo": false,
        "user-id": "120572949",
        "user-type": null,
        "emotes-raw": null,
        "badge-info-raw": "subscriber/19",
        "badges-raw": "broadcaster/1,subscriber/3012,glhf-pledge/1",
        "username": "gacbl",
        "message-type": "chat"
      }
    },
    "type": "message"
  },
  "overrides": { 
    "action": { 
      "variables": { 
        "label": "Sample counter:"
      }
    }
  }
}

For mor information about what is stored in the triggerPayload variable you can always use the logger API to see all the data it holds.