import { useTranslation } from 'react-i18next';
import toastr from 'toastr';
+import ChatSettingsForm from './ChatSettingsForm';
+import CommandDialog from './CommandDialog';
+import Commands from './Commands';
+import GuessingSettingsForm from './GuessingSettingsForm';
+import ChatBotLog from '../chat-bot-logs/ChatBotLog';
import ChannelSelect from '../common/ChannelSelect';
+import Icon from '../common/Icon';
import ToggleSwitch from '../common/ToggleSwitch';
+const CHAT_CATEGORIES = [
+ 'unclassified',
+ 'hi',
+ 'gl',
+ 'gg',
+ 'eyes',
+ 'love',
+ 'lol',
+ 'yes',
+ 'no',
+ 'rage',
+ 'sad',
+ 'sweat',
+ 'wtf',
+ 'pog',
+ 'hype',
+ 'kappa',
+ 'o7',
+ 'question',
+ 'thx',
+];
+
const Controls = () => {
const [channel, setChannel] = React.useState(null);
const [chatText, setChatText] = React.useState('');
+ const [editCommand, setEditCommand] = React.useState('');
+ const [editCommandSettings, setEditCommandSettings] = React.useState({});
+ const [showCommandDialog, setShowCommandDialog] = React.useState(false);
const { t } = useTranslation();
}
}, [channel, chatText, t]);
+ const randomChat = React.useCallback(async (category) => {
+ try {
+ await axios.post(`/api/channels/${channel.id}/chat`, {
+ bot_nick: 'horstiebot',
+ category,
+ });
+ toastr.success(t('twitchBot.chatSuccess'));
+ } catch (e) {
+ toastr.error(t('twitchBot.chatError'));
+ }
+ }, [channel, chatText, t]);
+
const join = React.useCallback(async (bot_nick) => {
try {
const rsp = await axios.post(`/api/channels/${channel.id}/join`, { bot_nick });
}
}, [channel, t]);
+ const saveChatSettings = React.useCallback(async (values) => {
+ try {
+ const rsp = await axios.post(`/api/channels/${channel.id}/chat-settings`, values);
+ setChannel(rsp.data);
+ toastr.success(t('twitchBot.saveSuccess'));
+ } catch (e) {
+ toastr.error(t('twitchBot.saveError'));
+ }
+ }, [channel, t]);
+
+ const onAddCommand = React.useCallback(() => {
+ setEditCommand('');
+ setEditCommandSettings({});
+ setShowCommandDialog(true);
+ }, [channel]);
+
+ const onEditCommand = React.useCallback((name, settings) => {
+ setEditCommand(name);
+ setEditCommandSettings(settings);
+ setShowCommandDialog(true);
+ }, [channel]);
+
+ const onRemoveCommand = React.useCallback(async (name) => {
+ try {
+ const rsp = await axios.delete(`/api/channels/${channel.id}/commands/${name}`);
+ setChannel(rsp.data);
+ toastr.success(t('twitchBot.saveSuccess'));
+ } catch (e) {
+ toastr.error(t('twitchBot.saveError'));
+ }
+ }, [channel]);
+
+ const saveCommand = React.useCallback(async (values) => {
+ try {
+ const rsp = await axios.put(
+ `/api/channels/${channel.id}/commands/${values.name}`,
+ values,
+ );
+ setChannel(rsp.data);
+ setShowCommandDialog(false);
+ setEditCommand('');
+ setEditCommandSettings({});
+ toastr.success(t('twitchBot.saveSuccess'));
+ } catch (e) {
+ toastr.error(t('twitchBot.saveError'));
+ throw e;
+ }
+ }, [channel]);
+
+ const saveGuessingGame = React.useCallback(async (values) => {
+ try {
+ const rsp = await axios.put(
+ `/api/channels/${channel.id}/guessing-game/${values.name}`,
+ values,
+ );
+ setChannel(rsp.data);
+ toastr.success(t('twitchBot.saveSuccess'));
+ } catch (e) {
+ toastr.error(t('twitchBot.saveError'));
+ throw e;
+ }
+ }, [channel]);
+
return <>
<Row className="mb-4">
<Form.Group as={Col} md={6}>
<Form.Label>{t('twitchBot.channel')}</Form.Label>
<Form.Control
as={ChannelSelect}
+ autoSelect
joinable
manageable
onChange={({ channel }) => { setChannel(channel); }}
</Row>
{channel ?
<Row>
- <Form.Group as={Col} md={6}>
- <Form.Label>{t('twitchBot.chat')}</Form.Label>
- <Form.Control
- as="textarea"
- onChange={({ target: { value } }) => {
- setChatText(value);
+ <Col className="mt-5" md={6}>
+ <h3>{t('twitchBot.chat')}</h3>
+ <Form.Group>
+ <Form.Label>{t('twitchBot.chat')}</Form.Label>
+ <Form.Control
+ as="textarea"
+ onChange={({ target: { value } }) => {
+ setChatText(value);
+ }}
+ value={chatText}
+ />
+ <div className="button-bar">
+ <Button
+ className="mt-2"
+ disabled={!chatText || !channel.join}
+ onClick={() => {
+ if (chatText) chat(chatText, 'localhorsttv');
+ }}
+ variant="twitch"
+ >
+ {t('twitchBot.sendApp')}
+ </Button>
+ <Button
+ className="mt-2"
+ disabled={!chatText || !channel.chat}
+ onClick={() => {
+ if (chatText) chat(chatText, 'horstiebot');
+ }}
+ variant="twitch"
+ >
+ {t('twitchBot.sendChat')}
+ </Button>
+ </div>
+ </Form.Group>
+ <h3 className="mt-3">{t('twitchBot.randomChat')}</h3>
+ <div className="button-bar">
+ {CHAT_CATEGORIES.map(category =>
+ <Button
+ key={category}
+ onClick={() => { randomChat(category); }}
+ variant="outline-secondary"
+ >
+ {t(`twitchBot.chatCategories.${category}`)}
+ </Button>
+ )}
+ </div>
+ </Col>
+ <Col className="mt-5" md={6}>
+ <div className="d-flex justify-content-between">
+ <h3>{t('twitchBot.chatSettings')}</h3>
+ <div className="button-bar">
+ <ChatBotLog id={channel.id} />
+ </div>
+ </div>
+ <ChatSettingsForm channel={channel} onSubmit={saveChatSettings} />
+ </Col>
+ <Col className="mt-5" md={12}>
+ <h3>{t('twitchBot.commands')}</h3>
+ <Commands
+ channel={channel}
+ onEditCommand={onEditCommand}
+ onRemoveCommand={onRemoveCommand}
+ />
+ <CommandDialog
+ name={editCommand}
+ onHide={() => {
+ setShowCommandDialog(false);
+ setEditCommand('');
+ setEditCommandSettings({});
}}
- value={chatText}
+ onSubmit={saveCommand}
+ settings={editCommandSettings}
+ show={showCommandDialog}
/>
- <div className="button-bar">
- <Button
- className="mt-2"
- disabled={!chatText || !channel.join}
- onClick={() => {
- if (chatText) chat(chatText, 'localhorsttv');
- }}
- variant="twitch"
- >
- {t('twitchBot.sendApp')}
- </Button>
- <Button
- className="mt-2"
- disabled={!chatText || !channel.chat}
- onClick={() => {
- if (chatText) chat(chatText, 'horstiebot');
- }}
- variant="twitch"
- >
- {t('twitchBot.sendChat')}
+ <div>
+ <Button onClick={onAddCommand} variant="primary">
+ {t('twitchBot.addCommand')}
</Button>
</div>
- </Form.Group>
+ </Col>
+ <Col className="mt-5" md={12}>
+ <div className="d-flex align-items-end justify-content-between">
+ <h3>{t('twitchBot.guessingGame.settings')}</h3>
+ <div className="button-bar">
+ {channel.access_key ?
+ <Button
+ href={`/guessing-game/monitor/${channel.access_key}`}
+ target="_blank"
+ title={t('button.browserSource')}
+ variant="outline-secondary"
+ >
+ <Icon.BROWSER_SOURCE title="" />
+ </Button>
+ : null}
+ <Button
+ onClick={() => {
+ window.open(
+ `/guessing-game/controls/${channel.id}`,
+ '',
+ 'width=640,height=800,titlebar=0,menubar=0,toolbar=0',
+ );
+ }}
+ title={t('twitchBot.guessingGame.popoutControls')}
+ variant="outline-secondary"
+ >
+ <Icon.OPEN title="" />
+ </Button>
+ </div>
+ </div>
+ <GuessingSettingsForm
+ name="gtbk"
+ onSubmit={saveGuessingGame}
+ settings={channel.guessing_settings?.gtbk || {}}
+ />
+ </Col>
</Row>
:
<Alert variant="info">