1 import axios from 'axios';
2 import React from 'react';
3 import { Alert, Button, Col, Form, Row } from 'react-bootstrap';
4 import { useTranslation } from 'react-i18next';
5 import toastr from 'toastr';
7 import ChatSettingsForm from './ChatSettingsForm';
8 import CommandDialog from './CommandDialog';
9 import Commands from './Commands';
10 import GuessingSettingsForm from './GuessingSettingsForm';
11 import ChatBotLog from '../chat-bot-logs/ChatBotLog';
12 import ChannelSelect from '../common/ChannelSelect';
13 import Icon from '../common/Icon';
14 import ToggleSwitch from '../common/ToggleSwitch';
16 const CHAT_CATEGORIES = ['unclassified', 'hi', 'gl', 'gg', 'lol', 'pog', 'hype', 'o7'];
18 const Controls = () => {
19 const [channel, setChannel] = React.useState(null);
20 const [chatText, setChatText] = React.useState('');
21 const [editCommand, setEditCommand] = React.useState('');
22 const [editCommandSettings, setEditCommandSettings] = React.useState({});
23 const [showCommandDialog, setShowCommandDialog] = React.useState(false);
25 const { t } = useTranslation();
27 const chat = React.useCallback(async (text, bot_nick) => {
29 await axios.post(`/api/channels/${channel.id}/chat`, {
33 toastr.success(t('twitchBot.chatSuccess'));
35 toastr.error(t('twitchBot.chatError'));
37 }, [channel, chatText, t]);
39 const randomChat = React.useCallback(async (category) => {
41 await axios.post(`/api/channels/${channel.id}/chat`, {
42 bot_nick: 'horstiebot',
45 toastr.success(t('twitchBot.chatSuccess'));
47 toastr.error(t('twitchBot.chatError'));
49 }, [channel, chatText, t]);
51 const join = React.useCallback(async (bot_nick) => {
53 const rsp = await axios.post(`/api/channels/${channel.id}/join`, { bot_nick });
55 toastr.success(t('twitchBot.joinSuccess'));
57 toastr.error(t('twitchBot.joinError'));
61 const part = React.useCallback(async (bot_nick) => {
63 const rsp = await axios.post(`/api/channels/${channel.id}/part`, { bot_nick });
65 toastr.success(t('twitchBot.partSuccess'));
67 toastr.error(t('twitchBot.partError'));
71 const saveChatSettings = React.useCallback(async (values) => {
73 const rsp = await axios.post(`/api/channels/${channel.id}/chat-settings`, values);
75 toastr.success(t('twitchBot.saveSuccess'));
77 toastr.error(t('twitchBot.saveError'));
81 const onAddCommand = React.useCallback(() => {
83 setEditCommandSettings({});
84 setShowCommandDialog(true);
87 const onEditCommand = React.useCallback((name, settings) => {
89 setEditCommandSettings(settings);
90 setShowCommandDialog(true);
93 const onRemoveCommand = React.useCallback(async (name) => {
95 const rsp = await axios.delete(`/api/channels/${channel.id}/commands/${name}`);
97 toastr.success(t('twitchBot.saveSuccess'));
99 toastr.error(t('twitchBot.saveError'));
103 const saveCommand = React.useCallback(async (values) => {
105 const rsp = await axios.put(
106 `/api/channels/${channel.id}/commands/${values.name}`,
109 setChannel(rsp.data);
110 setShowCommandDialog(false);
112 setEditCommandSettings({});
113 toastr.success(t('twitchBot.saveSuccess'));
115 toastr.error(t('twitchBot.saveError'));
120 const saveGuessingGame = React.useCallback(async (values) => {
122 const rsp = await axios.put(
123 `/api/channels/${channel.id}/guessing-game/${values.name}`,
126 setChannel(rsp.data);
127 toastr.success(t('twitchBot.saveSuccess'));
129 toastr.error(t('twitchBot.saveError'));
135 <Row className="mb-4">
136 <Form.Group as={Col} md={6}>
137 <Form.Label>{t('twitchBot.channel')}</Form.Label>
143 onChange={({ channel }) => { setChannel(channel); }}
144 value={channel ? channel.id : ''}
148 <Form.Group as={Col} md={3}>
149 <Form.Label>{t('twitchBot.joinApp')}</Form.Label>
153 onChange={({ target: { value } }) => {
155 join('localhorsttv');
157 part('localhorsttv');
164 <Form.Group as={Col} md={3}>
165 <Form.Label>{t('twitchBot.joinChat')}</Form.Label>
169 onChange={({ target: { value } }) => {
184 <Col className="mt-5" md={6}>
185 <h3>{t('twitchBot.chat')}</h3>
187 <Form.Label>{t('twitchBot.chat')}</Form.Label>
190 onChange={({ target: { value } }) => {
195 <div className="button-bar">
198 disabled={!chatText || !channel.join}
200 if (chatText) chat(chatText, 'localhorsttv');
204 {t('twitchBot.sendApp')}
208 disabled={!chatText || !channel.chat}
210 if (chatText) chat(chatText, 'horstiebot');
214 {t('twitchBot.sendChat')}
218 <h3 className="mt-3">{t('twitchBot.randomChat')}</h3>
219 <div className="button-bar">
220 {CHAT_CATEGORIES.map(category =>
223 onClick={() => { randomChat(category); }}
224 variant="outline-secondary"
226 {t(`twitchBot.chatCategories.${category}`)}
231 <Col className="mt-5" md={6}>
232 <div className="d-flex justify-content-between">
233 <h3>{t('twitchBot.chatSettings')}</h3>
234 <div className="button-bar">
235 <ChatBotLog id={channel.id} />
238 <ChatSettingsForm channel={channel} onSubmit={saveChatSettings} />
240 <Col className="mt-5" md={12}>
241 <h3>{t('twitchBot.commands')}</h3>
244 onEditCommand={onEditCommand}
245 onRemoveCommand={onRemoveCommand}
250 setShowCommandDialog(false);
252 setEditCommandSettings({});
254 onSubmit={saveCommand}
255 settings={editCommandSettings}
256 show={showCommandDialog}
259 <Button onClick={onAddCommand} variant="primary">
260 {t('twitchBot.addCommand')}
264 <Col className="mt-5" md={12}>
265 <div className="d-flex align-items-end justify-content-between">
266 <h3>{t('twitchBot.guessingGame.settings')}</h3>
267 <div className="button-bar">
268 {channel.access_key ?
270 href={`/guessing-game/monitor/${channel.access_key}`}
272 title={t('button.browserSource')}
273 variant="outline-secondary"
275 <Icon.BROWSER_SOURCE title="" />
281 `/guessing-game/controls/${channel.id}`,
283 'width=640,height=800,titlebar=0,menubar=0,toolbar=0',
286 title={t('twitchBot.guessingGame.popoutControls')}
287 variant="outline-secondary"
289 <Icon.OPEN title="" />
293 <GuessingSettingsForm
295 onSubmit={saveGuessingGame}
296 settings={channel.guessing_settings?.gtbk || {}}
301 <Alert variant="info">
302 {t('twitchBot.selectChannel')}
308 export default Controls;