nu_plugin_twitch 0.1.1

A Nu Shell plugin to interact with Twitch IRC and API, making scripting easier.
Documentation
# Nu Plugin Twitch

A [Nu Shell] plugin to interact with Twitch IRC and API, making scripting easier.

## Examples

The `justfile` is full of simple examples, as well as some more advanced in the `/examples/*.nu` files.

### Archive a channel chat for auditing

> Archiving a chat is available via the `just archive-chat {{CHANNEL}}` command.

```nu
# First start archiving the chat for later use
twitch chat Larandar | into sqlite examples/archive.db -t Larandar

# Now let's get the number of messages of each user per minutes
open examples/archive.db | get Larandar | select sender timestamp |
    insert minutes { $in.timestamp | format date "%Y-%m-%d %H:%M:00.000%Z" } |
    group-by --to-table sender minutes |
    move items messages | update messages { length } |
    sort-by count
```

## Roadmap

### 0.1.0: MVP

- [x] Reading messages from IRC
- [x] Parsing subscription notifications
- [x] Sending message to IRC
- [x] OAuth management with `twitch auth` command to authenticate and store a profile
- [x] Refreshing OAuth token

### 0.2.0

- [ ] Couple of GET APIs call (`user`, `broadcast`, `is-live`)
- [ ] Couple of POST APIs call (`title`)

### 1.0.0

- [ ] `twitch cmd` pipeline framework
    - `--consume`: remove message from the output stream
    - `--cooldown`: take a `duration` and execute once per cooldown **per user**
    - `--cooldown-is-global`: use a global cooldown

```nu
const SOUNDS_ROOT = [(pwd) "sounds"] | path join | path expand;

twitch chat CHANNEL | # Play a loud sound with a very long global cooldown and cosume the message
twitch cmd --cooldown 1day --cooldown-is-global --consume "!pipe" {|$msg, $args|
    let $sound = ([$SOUNDS_ROOT "loud_pipe.mp3"] | path join | path expand);
    sound meta $sound | sound play $sound -d $in.duration
} | # Parse the `bruh~ TTS msg` (using nu_plugin_audio_hook and piper1-gpl)
twitch cmd --lock tts "bruh~" {|$msg, $args|
    let $sound = [$SOUNDS_ROOT "_tmp_tts.wav"] | path join;
    python3 -m piper -m en_US-lessac-medium -f $sound -- ($args | str join " ");
    sound play ([$SOUNDS_ROOT "bruh.mp3"] | path join) -d 1sec;
    sound play $sound -d 15sec;
} | # Parse the `!sound tuturu` to play the tuturu.mp3 with a 1min cooldown per user
twitch cmd --cooldown 1min "!sound" {|$msg, $args|
    let $sound = [$SOUNDS $"($args | str join '_').mp3"] | path join
    if ($sound | path parent) != $SOUNDS {
        # WARN: May need to timeout the user for trying hacking you
        $"ARA ARA @($msg.sender), you naughty boy!!" | twitch say CHANNEL
    } else {
        if ($sound | path exists) {
            $"@($msg.sender) not a sound LUL" | twitch say CHANNEL
        } else {
            sound meta $sound | sound play $sound -d $in.duration
        }
    }
}
```

### Future plans

- [ ] `twitch cmd` pipeline from file/db
- [ ] `twitch cmd` running `.nu` script instead of closures

## Credits

- [nu_plugin_dns]https://github.com/dead10ck/nu_plugin_dns: for how to use async code in a [Nu Shell].
- [twitch-irc-rs]https://github.com/robotty/twitch-irc-rs: for parsing all IRC messages.

[Nu Shell]: https://www.nushell.sh/ "Nu Shell"