Twitch stream event platform with OBS browser source overlay. Features: - Twitch OAuth login (streamer + mod access) - EventSub WebSocket for subs, gift subs, bits, channel points, follows, raids - Chat commands via tmi.js in the overlay - Gap audio — tone plays on new chat message after silence, volume/pitch scale with gap length - Self-hosted media library (upload sounds and videos) - Action configuration — map any event to sound, video, or alert - Per-action cooldowns, test button, enable/disable toggle - Multiple actions per event (all matching actions fire) - Activity log dashboard with EventSub connection status - Layout editor — iframe-based WYSIWYG with drag handles, live style preview - Custom CSS and custom JS injection into overlay - Custom DOM events (bashyoverlay:sub, bashyoverlay:raid, etc.) for custom JS hooks - deploy.sh — one-shot setup and launch script Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
71 lines
2.5 KiB
HTML
71 lines
2.5 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}Actions — BashyOverlay{% endblock %}
|
|
{% block content %}
|
|
<hgroup>
|
|
<h1>Actions</h1>
|
|
<p>Configure what happens when each event fires.</p>
|
|
</hgroup>
|
|
|
|
<section>
|
|
<h2>Add action</h2>
|
|
<form hx-post="/actions"
|
|
hx-target="#actions-list"
|
|
hx-swap="beforeend"
|
|
hx-on::after-request="this.reset()">
|
|
<div class="form-grid">
|
|
<label>
|
|
Event type
|
|
<select name="event_type" required>
|
|
{% for et in event_types %}
|
|
<option value="{{ et }}">{{ et }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</label>
|
|
<label>
|
|
Event detail
|
|
<input type="text" name="event_detail" placeholder="command name / reward ID / bits min / sub tier">
|
|
<small>Leave blank to match any. For commands: the name without !. For bits: minimum amount.</small>
|
|
</label>
|
|
<label>
|
|
Action type
|
|
<select name="action_type" required>
|
|
{% for at in action_types %}
|
|
<option value="{{ at }}">{{ at }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</label>
|
|
<label>
|
|
Media file <small>(for sound/video)</small>
|
|
<select name="media_file_id">
|
|
<option value="">— none —</option>
|
|
{% for f in media_files %}
|
|
<option value="{{ f.id }}">[{{ f.file_type }}] {{ f.original_name }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</label>
|
|
<label>
|
|
Alert text <small>(shown on screen)</small>
|
|
<input type="text" name="alert_text" placeholder="e.g. {{ '{{username}} just subscribed!' }}">
|
|
</label>
|
|
<label>
|
|
Cooldown (seconds)
|
|
<input type="number" name="cooldown_seconds" value="0" min="0">
|
|
</label>
|
|
</div>
|
|
<button type="submit">Add action</button>
|
|
</form>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>Configured actions</h2>
|
|
<div id="actions-list">
|
|
{% for action in actions %}
|
|
{% set _ = namespace(media_files=media_files) %}
|
|
{% include "partials/action_row.html" %}
|
|
{% endfor %}
|
|
{% if not actions %}
|
|
<p><em>No actions configured yet.</em></p>
|
|
{% endif %}
|
|
</div>
|
|
</section>
|
|
{% endblock %}
|