# @dataplor/sizemore

> Head of Narrative

Latest version **3.0.1** (published 2020-08-03) · MIT license · 0 weekly downloads

## Install

```sh
npm install @dataplor/sizemore
pnpm add @dataplor/sizemore
yarn add @dataplor/sizemore
bun add @dataplor/sizemore
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 3.0.1 |
| Published | 2020-08-03 |
| First published | 2020-08-03 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 4 |
| Unpacked size | 18 KB |
| Known vulnerabilities | 0 (+1 in 1 direct dependencies) |
| Install scripts | no |
| Maintainers | rurabe |

## Links

- npm: https://www.npmjs.com/package/@dataplor/sizemore
- Repository: https://github.com/dataPlor/sizemore
- Homepage: https://github.com/dataPlor/sizemore#readme
- Issues: https://github.com/dataPlor/sizemore/issues
- npm.io page: https://npm.io/package/@dataplor/sizemore

## Dependencies (4)

- [aws-sdk](https://npm.io/package/aws-sdk.md) ^2.709.0
- [mustache](https://npm.io/package/mustache.md) ^4.0.1
- [object-hash](https://npm.io/package/object-hash.md) ^2.0.3
- [@octokit/rest](https://npm.io/package/@octokit/rest.md) ^18.0.0

## Recent versions

- 3.0.1 (latest) — 2020-08-03
- 3.0.0 — 2020-08-03

## README

# Sizemore  
Head of Narrative
  
> ["...a relentless, fucking, experience"](https://www.youtube.com/watch?v=F558itR3hAY)

## Install

```bash
$ yarn add dataplor/sizemore
```

```js
const { configure,loadExpressions } = require('sizemore');

configure({
  bucket: 'somebucket',
  repo: 'scripts',
  repoOwner: 'mycompany',
  scriptsPath: 'src',
});

const callData = JSON.parse(message.body);

return loadExpressions({
  ref:         callData.script.commit,
  voiceConfig: callData.call.voice,
  data:        callData.call.data,
  verifying:   callData.call.contexts.map(c => c.attribute),
}).then( expressionSet => {
  expressionSet.loadAudio().then(() => {
    // some stuff
    // then!
    const frame = expressionSet.getExpression("hello").audio.slice(0,320)
    ws.send(frame)
      
    );
  });
});
```

## ENV
  
```
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
GITHUB_PERSONAL_ACCESS_TOKEN
```

## Definitions

- `key`: a unique string that represents something the bot might say, ie `"hello"`, or `"verify_name"`
- `Line`: A single phrase associated with a `key`. The phrase includes placeholders for data and must be supplied with that data to be ready to deploy.
- `Script`: A collection of `Lines` that make up the generic vocabulary of the bot.
- `Expression`: A single phrase associated with a key, but distinct from a `Line` in that the placeholders have been filled in by the data for this particular record.
- `ExpressionSet`: A collection of `Expressions`

## API

### loadExpressions(ref: string, voiceConfig: object, data: object, verifying: array)
Returns a `Promise` that resolves with an `ExpressionSet` ready to use. Fetch scripts from central repository, create an `ExpressionSet` with an `Expression` for each `Line` in the `Script`.

```js
const callData = JSON.parse(message.body);
loadExpressions({
  voiceConfig: callData.voice,
  data:        callData.data,
  verifying:   callData.contexts.map(c => c.attribute),
}).then( expressionSet => {
  // do things with the expressionSet
})
```

| Attribute | Type    | Required      | Description                                |
| --------- | ------- | ------------- | ------------------------------------------ |
| `ref`    | string  | optional           | A git ref for the [script repo]([https://github.com/dataPlor/bot_scripts](https://github.com/dataPlor/bot_scripts)), which is usually a commit SHA. If omitted, it will fetch the latest scripts.             |
| `voiceConfig`     | object | required |  |
| `voiceConfig.provider`     | string | required | Voice synthesis provider, ie `aws` |
| `voiceConfig.voice`     | string | required | ID of the voice to use, ie `Lupe` |
| `voiceConfig.locale`     | string | required | Valid locale string, ie `es-US` |
| `data` | object  | required | An object with the data for this record, ie `{name: "foo"}`  |
| `verifying` | array[string]  | required | An array of strings of attributes which are being verified by this call, ie `["name"]`  |


### ExpressionSet
A wrapper for a collection of expressions. By default, the scripts are fetched but the audio is not. You must call `loadAudio` to add the binary audio streams to the `Expressions`

#### Attributes
| Attribute | Type     | Description                                |
| --------- | -------  | ------------------------------------------ |
| `commit`    | string  | git SHA that represents the "version" of the Script             |
| `script`     | object | `Script` object |
| `voiceConfig`     | object |  same three keys as above: `provider`,`voice`,`locale` |
| `data`     | object | Data provided to `Lines` to turn them into `Expressions` |
| `verifying`     | array[string] | Attributes this call is verifying, used to determine which `Lines`/`Expressions` can be skipped. |
| `data` | object  |  An object with the data for this record, ie `{name: "foo"}`  |
| `verifying` | array[string]  |  An array of strings of attributes which are being verified by this call, ie `["name"]`  |
| `expressions` | object  |  Object of expressions by key  |

#### Methods

##### getExpression(key string)
```js
const expression = expressionSet.getExpression('hello');
expression.key  // => "hello"
expression.text // => "¡Hola!"
```

Fetch a specific `Expression` by its `key`.

##### loadAudio()
```js
expressionSet.loadAudio().then(() => {
  // audio is ready!
  expressionSet.getExpression('hello').audio.pipe(somewhere)
});
```

Have all `Expressions` fetch pre-synthesized binary Audio from s3. Returns a promise with no resolution value.

### Expression
An object containing all the information about a single phrase the bot can say.

#### Attributes
| Attribute | Type     | Description                                |
| --------- | -------  | ------------------------------------------ |
| `key`    | string  | ie `'hello'` or `'verify_name'`             |
| `commit`    | string  | git SHA that represents the "version" of the Script             |
| `line`     | object | `Line` object |
| `voice`     | string |  from `voiceConfig`, ie `"Lupe"` |
| `provider`     | string | from `voiceConfig`, ie `"aws"` |
| `locale`     | string | from `voiceConfig`, ie `"es-US"` |
| `data` | object  |  An object with all the data for this record, ie `{name: "foo"}`  |
| `ssml` | string  |  Interpolated string taking the template from `this.line.ssml` and interpolating using `this.data`, ie `"<speak><prosody rate=\"110%\">¿Estoy marcando a Ryan Taco?</prosody></speak>"`  |
| `text` | string  |  Interpolated string taking the template from `this.line.text` and interpolating using `this.data`, ie `"¿Estoy marcando a Ryan Taco?"`  |
| `filename` | string  |  filename of the audio on s3, which is a hashed function of `ssml`,`voice`,`provider`,`locale`  |
| `s3Key` | string  |  Key of the audio on s3, includes full path unlike filename, ie `"expressions/4128ab87ef...809a9b08ce8.mp3"`  |
| `audio` | ArrayBuffer  |  binary audio data, in wav PCM format. Not set until `loadAudio()` is called on this `Expression` or parent `ExpressionSet` |
#### Methods

##### toJSON()
```js
const expression = expressionSet.getExpression('hello');
expression.toJSON()  // => {key, ssml, text, voice, provider, locale}
```

Return a plain JS object with the key, ssml, text, voice, provider, locale.

##### loadAudio()
```js
const expression = expressionSet.getExpression('hello');
expression.loadAudio().then(() => {
  const msg = expression.audio.slice(0,320);
  ws.send(msg)
});
```
Returns a promise with no resolution value. Fetch audio from S3, convert it from mp3 to PCM wav and store it on this instance as `this.audio` as an `ArrayBuffer`.

### fetchScripts(ref: string, locale: string)
Returns a `Promise` that resolves with a plain JS `Script` object. Usually you want to `loadExpressions` but if you want the scripts by themselves you can get them here.

```js
fetchScripts({locale: 'es-US', ref: '72e4defe85961d7d3986f02a262d8002c7257449'}).then( script => {
  // do things with the script
  script['hello'] 
  // => {
  //  "required": true,
  //  "ssml": "<speak><prosody rate=\"110%\">¡Hola!</prosody></speak>",
  //  "text": "¡Hola!" 
  //}
})
```

| Attribute | Type    | Required      | Description                                |
| --------- | ------- | ------------- | ------------------------------------------ |
| `ref`    | string  | optional           | A git ref for the [script repo]([https://github.com/dataPlor/bot_scripts](https://github.com/dataPlor/bot_scripts)), which is usually a commit SHA. If omitted, it will fetch the latest scripts.             |
| `locale`     | string | required | Valid locale string, ie `es-US` |

### hashExpression(expression Expression)
Returns a SHA512 hash unique to this `Expression`'s `ssml`, `locale`, `voice` and `provider`. Why a long ass 512 hash? I really don't want collisions.

```js
hashExpression(expression) // => "0153d6c2914f8b9dfbd773c41986e412ede26d3f01e7441b600049a527912097d233385036fd4ff34369f5915c74929126d9bff78e962ff24410374bfbedda78"
```

| Attribute | Type    | Required      | Description                                |
| --------- | ------- | ------------- | ------------------------------------------ |
| `expression`    | Expression  | required           | An expression to hash             |

### hashedFilename(expression Expression,extension string)
Returns a SHA512 hash unique to this `Expression`'s `ssml`, `locale`, `voice` and `provider`. Why a long ass 512 hash? I really don't want collisions.

```js
hashedFilename(expression) // => "0153d6c2914f8b9dfbd773c41986e412ede26d3f01e7441b600049a527912097d233385036fd4ff34369f5915c74929126d9bff78e962ff24410374bfbedda78.mp3"
```

| Attribute | Type    | Required      | Description                                |
| --------- | ------- | ------------- | ------------------------------------------ |
| `expression`    | Expression  | required           | An expression to hash             |
| `extension`    | string  | optional           | Defaults to `.mp3`             |

## You wanted me? Well let this be a lesson!

> And the lesson is: If you're looking for a reckoning, a reckoning is what you'll find! If you're looking for a villain, then I'm your man! But look at yourselves. This world you built is bound by villainy. You sleep on the broken bodies of the ones who were here before you. Warm yourselves with their embers! Plow their bones into your fields! You paid them for this land with lead, and I'll pay you back in full!
>
>You wanted me??? Well all I can say to that is, here I fucking am!

[https://www.youtube.com/watch?v=T1de3dRPyiY](https://www.youtube.com/watch?v=T1de3dRPyiY)

---
_Source: https://npm.io/package/@dataplor/sizemore · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
