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 ChannelSelect from '../common/ChannelSelect';
12 import Icon from '../common/Icon';
13 import ToggleSwitch from '../common/ToggleSwitch';
15 const CHAT_CATEGORIES = ['unclassified', 'hi', 'gl', 'gg', 'lol', 'pog', 'hype', 'o7'];
17 const Controls = () => {
18 const [channel, setChannel] = React.useState(null);
19 const [chatText, setChatText] = React.useState('');
20 const [editCommand, setEditCommand] = React.useState('');
21 const [editCommandSettings, setEditCommandSettings] = React.useState({});
22 const [showCommandDialog, setShowCommandDialog] = React.useState(false);
24 const { t } = useTranslation();
26 const chat = React.useCallback(async (text, bot_nick) => {
28 await axios.post(`/api/channels/${channel.id}/chat`, {
32 toastr.success(t('twitchBot.chatSuccess'));
34 toastr.error(t('twitchBot.chatError'));
36 }, [channel, chatText, t]);
38 const randomChat = React.useCallback(async (category) => {
40 await axios.post(`/api/channels/${channel.id}/chat`, {
41 bot_nick: 'horstiebot',
44 toastr.success(t('twitchBot.chatSuccess'));
46 toastr.error(t('twitchBot.chatError'));
48 }, [channel, chatText, t]);
50 const join = React.useCallback(async (bot_nick) => {
52 const rsp = await axios.post(`/api/channels/${channel.id}/join`, { bot_nick });
54 toastr.success(t('twitchBot.joinSuccess'));
56 toastr.error(t('twitchBot.joinError'));
60 const part = React.useCallback(async (bot_nick) => {
62 const rsp = await axios.post(`/api/channels/${channel.id}/part`, { bot_nick });
64 toastr.success(t('twitchBot.partSuccess'));
66 toastr.error(t('twitchBot.partError'));
70 const saveChatSettings = React.useCallback(async (values) => {
72 const rsp = await axios.post(`/api/channels/${channel.id}/chat-settings`, values);
74 toastr.success(t('twitchBot.saveSuccess'));
76 toastr.error(t('twitchBot.saveError'));
80 const onAddCommand = React.useCallback(() => {
82 setEditCommandSettings({});
83 setShowCommandDialog(true);
86 const onEditCommand = React.useCallback((name, settings) => {
88 setEditCommandSettings(settings);
89 setShowCommandDialog(true);
92 const onRemoveCommand = React.useCallback(async (name) => {
94 const rsp = await axios.delete(`/api/channels/${channel.id}/commands/${name}`);
96 toastr.success(t('twitchBot.saveSuccess'));
98 toastr.error(t('twitchBot.saveError'));
102 const saveCommand = React.useCallback(async (values) => {
104 const rsp = await axios.put(
105 `/api/channels/${channel.id}/commands/${values.name}`,
108 setChannel(rsp.data);
109 setShowCommandDialog(false);
111 setEditCommandSettings({});
112 toastr.success(t('twitchBot.saveSuccess'));
114 toastr.error(t('twitchBot.saveError'));
119 const saveGuessingGame = React.useCallback(async (values) => {
121 const rsp = await axios.put(
122 `/api/channels/${channel.id}/guessing-game/${values.name}`,
125 setChannel(rsp.data);
126 toastr.success(t('twitchBot.saveSuccess'));
128 toastr.error(t('twitchBot.saveError'));
134 <Row className="mb-4">
135 <Form.Group as={Col} md={6}>
136 <Form.Label>{t('twitchBot.channel')}</Form.Label>
142 onChange={({ channel }) => { setChannel(channel); }}
143 value={channel ? channel.id : ''}
147 <Form.Group as={Col} md={3}>
148 <Form.Label>{t('twitchBot.joinApp')}</Form.Label>
152 onChange={({ target: { value } }) => {
154 join('localhorsttv');
156 part('localhorsttv');
163 <Form.Group as={Col} md={3}>
164 <Form.Label>{t('twitchBot.joinChat')}</Form.Label>
168 onChange={({ target: { value } }) => {
183 <Col className="mt-5" md={6}>
184 <h3>{t('twitchBot.chat')}</h3>
186 <Form.Label>{t('twitchBot.chat')}</Form.Label>
189 onChange={({ target: { value } }) => {
194 <div className="button-bar">
197 disabled={!chatText || !channel.join}
199 if (chatText) chat(chatText, 'localhorsttv');
203 {t('twitchBot.sendApp')}
207 disabled={!chatText || !channel.chat}
209 if (chatText) chat(chatText, 'horstiebot');
213 {t('twitchBot.sendChat')}
217 <h3 className="mt-3">{t('twitchBot.randomChat')}</h3>
218 <div className="button-bar">
219 {CHAT_CATEGORIES.map(category =>
222 onClick={() => { randomChat(category); }}
223 variant="outline-secondary"
225 {t(`twitchBot.chatCategories.${category}`)}
230 <Col className="mt-5" md={6}>
231 <h3>{t('twitchBot.chatSettings')}</h3>
232 <ChatSettingsForm channel={channel} onSubmit={saveChatSettings} />
234 <Col className="mt-5" md={12}>
235 <h3>{t('twitchBot.commands')}</h3>
238 onEditCommand={onEditCommand}
239 onRemoveCommand={onRemoveCommand}
244 setShowCommandDialog(false);
246 setEditCommandSettings({});
248 onSubmit={saveCommand}
249 settings={editCommandSettings}
250 show={showCommandDialog}
253 <Button onClick={onAddCommand} variant="primary">
254 {t('twitchBot.addCommand')}
258 <Col className="mt-5" md={12}>
259 <div className="d-flex align-items-end justify-content-between">
260 <h3>{t('twitchBot.guessingGame.settings')}</h3>
261 <div className="button-bar">
262 {channel.access_key ?
264 href={`/guessing-game/monitor/${channel.access_key}`}
266 title={t('button.browserSource')}
267 variant="outline-secondary"
269 <Icon.BROWSER_SOURCE title="" />
275 `/guessing-game/controls/${channel.id}`,
277 'width=640,height=800,titlebar=0,menubar=0,toolbar=0',
280 title={t('twitchBot.guessingGame.popoutControls')}
281 variant="outline-secondary"
283 <Icon.OPEN title="" />
287 <GuessingSettingsForm
289 onSubmit={saveGuessingGame}
290 settings={channel.guessing_settings?.gtbk || {}}
295 <Alert variant="info">
296 {t('twitchBot.selectChannel')}
302 export default Controls;