An open API service indexing awesome lists of open source software.

https://github.com/stuf/obs.remote.kefir

OBS WebSocket integration based on Kefir streams and partial lenses
https://github.com/stuf/obs.remote.kefir

kefir nodejs obs-remote obs-studio obs-websocket partial-lenses reactive websockets

Last synced: 11 months ago
JSON representation

OBS WebSocket integration based on Kefir streams and partial lenses

Awesome Lists containing this project

README

          

[![Maintainability](https://api.codeclimate.com/v1/badges/78fc583705036be7cb23/maintainability)](https://codeclimate.com/github/stuf/obs.remote.kefir/maintainability)
[![Test Coverage](https://api.codeclimate.com/v1/badges/78fc583705036be7cb23/test_coverage)](https://codeclimate.com/github/stuf/obs.remote.kefir/test_coverage)
[![Build Status](https://travis-ci.org/stuf/obs.remote.kefir.svg?branch=master)](https://travis-ci.org/stuf/obs.remote.kefir)
[![npm version](https://badge.fury.io/js/obs.remote.kefir.svg)](https://badge.fury.io/js/obs.remote.kefir)

[OBS WebSocket](https://github.com/Palakis/obs-websocket) integration based on [Kefir streams](https://github.com/kefirjs/kefir) and [partial lenses](https://github.com/calmm-js/partial.lenses) for reactive applications.

---

# OBS Remote

## Contents

* [Getting Started](#getting-started)
* [About the API](#about-the-api)
* [Reference](#reference)
* [OBS](#obs)
* [Sessions](#sessions)
* [`connect :: String -⁠> WebSocket`](#obs-connect)
* [`listen_ :: (WebSocket, (Object -⁠> Object)) -⁠> Observable`](#obs-listen_)
* [`listen :: WebSocket -⁠> Observable`](#obs-listen)
* [`listenWithTransformer :: WebSocket -⁠> (Object -⁠> Object) -⁠> Observable`](#obs-listenWithTransformer)
* [`command_ :: (String, Object, WebSocket) -⁠> Observable`](#obs-command_)
* [`command :: String -⁠> WebSocket -⁠> Observable`](#obs-command)
* [`commandWithArgs :: String -⁠> Object -⁠> WebSocket -⁠> Observable`](#obs-commandWithArgs)
* [Sockets](#sockets)
* [Core](#core)
* [`createSocket_ :: (url, options) ~> WebSocket`](#createSocket_)
* [`createSocket :: url -> options ~> Socket`](#createSocket)
* [Listening to events](#listening-to-events)
* [`listenTo_ :: (socket, type) ~> Observable`](#listenTo_)
* [`listenToOnce_ :: (socket, type) ~> Observable`](#listenToOnce_)
* [`listenTo :: socket -> type ~> Observable`](#listenTo)
* [`listenToOnce :: socket -> type ~> Observable`](#listenToOnce)
* [Sending commands](#sending-commands)
* [`send_ :: (type, args, socket) ~> Observable`](#send_)
* [`send2 :: (type, args) -> socket ~> Observable`](#send2)
* [`send3 :: type -> args -> socket ~> Observable`](#send3)
* [Utilities](#utilities)
* [`genFunc :: (String -⁠> Function) -⁠> (String -⁠> String)`](#util-genFunc)
* [`inList :: a -⁠> POptic s a`](#util-inList)
* [`getFromList :: Foldable f => a -⁠> f a -⁠> a`](#util-getFromList)
* [`flatJoin :: [a] -⁠> String`](#util-flatJoin)
* [`getEvent :: ObsEvent -⁠> String`](#util-getEvent)
* [`getRequest :: ObsRequest -⁠> String`](#util-getRequest)
* [`splitPascal :: String -⁠> [String]`](#util-splitPascal)
* [`splitCamelCase :: String -⁠> [String]`](#util-splitCamelCase)
* [`camelCasePascal :: String -⁠> String`](#util-camelCasePascal)
* [`kebabCasePascal :: String -⁠> String`](#util-kebabCasePascal)
* [`constCasePascal :: String -⁠> String`](#util-constCasePascal)
* [`pascalCaseCamel :: String -⁠> String`](#util-pascalCaseCamel)
* [`pascalCaseKebab :: String -⁠> String`](#util-pascalCaseKebab)
* [`pascalCaseConst :: String -⁠> String`](#util-pascalCaseConst)
* [`camelCaseKebab :: String -⁠> String`](#util-camelCaseKebab)
* [Acknowledgements](#acknowledgements)

---

## Getting Started

The library has only named exports. This allows you to import as much or as little as you want from it. Either by doing

```js
import * as socket from 'obs.remote.kefir';
```

or

```js
import { createSocket, send } from 'obs.remote.kefir';
```

## About the API

The public-facing API is with [`sanctuary-def`][sanctuary-def], to allow run-time type checking. This helps out a lot when working with data that's coming from the outside and allows to fail fast when introduced with something we're not expecting.

Note that run-time type checking has performance implications. Checking is disabled in production, but if you find you want to disable type checking, it can be disabled with the `DISABLE_TYPE_CHECKING` environment variable set to `1`;

```sh
stuf@local:~/project$ DISABLE_TYPE_CHECKING=1 node app.js
```

## Reference

### OBS

Contains functions for connecting to an OBS websocket,
observing OBS events as well as sending commands to the OBS
websocket.

```js
const OBS = require('obs.remote.kefir/lib/obs');
```

#### Sessions

connect :: String -⁠> WebSocket

listen_ :: (WebSocket, (Object -⁠> Object)) -⁠> Observable

Listen to events from the given websocket, and uptionally apply
a custom transforming function on the result.

This is the uncurried and unchecked version of the function.

listen :: WebSocket -⁠> Observable

Create an Observable from any events OBS emits.

All objects will be rewritten so that all `kebab-case` keys
will be transformed into `camelCase` keys.

If you want to override the default transforming function,
use [`listenWithTransformer`](#listenWithTransformer) instead.

Usually one creates an Observable from all events, and create
new Observables by filtering the events by their event name.
These can then be used on their own or by combining them
to ensure some computation or action is taken when both events
have occurred.

```js
const obsEvents = listen(ws);

obsEvents.filter(R.whereEq({ updateType: 'transition-begin' }))
.onValue(e => {
// Do something when transition begins
});

obsEvents.filter(R.whereEq({ updateType: 'preview-scene-changed' }))
.onValue(e => {
// Do something when the preview scene is changed
});
```

listenWithTransformer :: WebSocket -⁠> (Object -⁠> Object) -⁠> Observable

Create an Observable from any events OBS emits, and transform the event
with the given function.

command_ :: (String, Object, WebSocket) -⁠> Observable

Send a command with optional arguments to the given websocket.
Uncurried.

command :: String -⁠> WebSocket -⁠> Observable

Send a command without arguments to the given websocket.
Curried, takes two arguments.

commandWithArgs :: String -⁠> Object -⁠> WebSocket -⁠> Observable

Send a command with arguments to the given websocket.
Curried, takes three arguments.

shouldDisableChecks :: String -⁠> String -⁠> Boolean

createEnv :: () -⁠> Function

Handling websockets per se does not require anything extra,
besides using a library such as [`ws`][ws] if you're working
in a non-browser environment.

This library exposes a number of functions that can be used for
handling websockets through [`Kefir`][kefir] observables,
instead of using callbacks or Promises.

The functions this module exposes are meant for low-level handling
of websockets. For controlling OBS specifically, refer to
the [OBS](#api-obs) module.

```js
const socket = require('obs.remote.kefir/lib/socket');
```

#### Core

createSocket_ :: (String, Object) -⁠> WebSocket

Create a new websocket connection to the given `url` and `options`.

```js
const ws = createSocket('ws://localhost:4000');
```

createSocket :: String -⁠> Object -⁠> WebSocket

Curried version of [`createSocket_`](#createSocket_). Creates a websocket.

```js
const newLocalSocket = createSocket('ws://localhost:4000');
const ws = newLocalSocket({ options: {} });
```

#### Listening to Events

listenTo_ :: String -⁠> WebSocket -⁠> Observable

Listen for events of a certain type from the given socket.

```js
const messages = listenTo_('message', ws);
messages.onValue(msg => {
// Do something
})
```

listenTo :: String -⁠> WebSocket -⁠> Observable

Curried version of [`listenTo_`](#listenTo_)

Listen to events of a certain type from the given socket.
Often used as a helper for listening to an event from a bunch
of sockets.

```js
const messagesFrom = listenTo('message');
const messages = messagesFrom(webSocket);
const otherMessages = messagesFrom(anotherWebSocket);
```

Note that you can use [`R.flip`][R.flip] or [`S.flip`][S.flip] to
create a function that you can use to register different event
listeners from a single websocket.

```js
const listenFrom = S.flip(listenTo);
const listenFor = listenFrom(ws);
const messages = listenFor('message'); // Observable of messages emitted from websocket
const errors = listenFor('error'); // Observable of errors emitted from websocket
```

listenToOnce_ :: (String, WebSocket) -⁠> Observable

Create an Observable of events, but emits only a single event, then ends.

It's identical to doing:

```js
listenTo(socket, 'open').take(1).onValue(v => {
// Do something
})
```

listenToOnce :: String -⁠> WebSocket -⁠> Observable

Curried version of [`listenToOnce_`](#listenToOnce_). Like with [`listenTo`](#listenTo)
can be used to easily create Observables of a single event.

It's identical to doing:

```js
const listenOnceFrom = S.flip(listenToOnce);
const onceForEvent = listenOnceFrom(ws);

onceForEvent('message').onValue(v => {
// Do something
});
```

#### Sending Commands

send_ :: (String, Object, WebSocket) -⁠> Observable

Send `socket` a message of given `type` with optional arguments.

send2 :: String -⁠> WebSocket -⁠> Observable

Curried binary version of [`send_`](#send_)

send3 :: String -⁠> Object -⁠> WebSocket -⁠> Observable

Curried ternary version of [`send_`](#send_)

### OBS types

ObsRequest

Represents a `Request` in OBS.

ObsEvent

Represents an `Event` in OBS.

### Observable

KefirObservable

Represents a Kefir `Observable` instance.

KefirProperty

Represents a Kefir `Property` instance.

KefirStream

Represents a Kefir `Stream` instance.

WebSocket

Represents an instance of `WebSocket`


Contains some generic utilities for handling string tokens of
different kinds, and conversion functions for them—e.g. for
creating isomorphisms on tokens, to avoid having to manually convert
tokens back and forth when interfacing with OBS.

genFunc :: (String -⁠> Function) -⁠> (String -⁠> String)

inList :: a -⁠> POptic s a

getFromList :: Foldable f => a -⁠> f a -⁠> a

Find the item `x` from the given list of `xs` and return it.

flatJoin :: [a] -⁠> String

Utility for joining nested arrays of strings into a string.

getEvent :: ObsEvent -⁠> String

Get the string representation of the given OBS event type.

getRequest :: ObsRequest -⁠> String

Get the string representation of the given OBS request type.

splitPascal :: String -⁠> [String]

Split a pascal-cased string into an array of words.

splitCamelCase :: String -⁠> [String]

Split a camelcased string into an array of words.

camelCasePascal :: String -⁠> String

Get the camel-case version of a pascal-cased string.

```js
camelCasePascal('FooBar'); // => 'fooBar'

kebabCasePascal :: String -⁠> String

Get the kebab-case version of a pascal-cased string.

```js
kebabCasePascal('FooBar'); // => 'foo-bar'
```

constCasePascal :: String -⁠> String

Get the "const-cased" version of a pascal-cased string.

```js
constCasePascal('FooBar'); // => 'FOO_BAR'
```

pascalCaseCamel :: String -⁠> String

pascalCaseKebab :: String -⁠> String

pascalCaseConst :: String -⁠> String

camelCaseKebab :: String -⁠> String

## Acknowledgements

* *You* ♡

[ws]: https://github.com/websockets/ws
[kefir]: https://kefirjs.github.io/kefir/
[sanctuary-def]: https://github.com/sanctuary-js/sanctuary-def
[R.flip]: http://ramdajs.com/docs/#flip
[S.flip]: https://sanctuary.js.org/#flip