]> git.localhorst.tv Git - alttp.git/blob - resources/js/components/twitch-bot/Controls.js
f3f551cb9ca4e1fd8ca4f1ffe320ef162bb9649d
[alttp.git] / resources / js / components / twitch-bot / Controls.js
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';
6
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';
15
16 const CHAT_CATEGORIES = [
17         'unclassified',
18         'hi',
19         'gl',
20         'gg',
21         'eyes',
22         'love',
23         'lol',
24         'rage',
25         'sad',
26         'sweat',
27         'wtf',
28         'pog',
29         'hype',
30         'o7',
31         'question',
32         'thx',
33 ];
34
35 const Controls = () => {
36         const [channel, setChannel] = React.useState(null);
37         const [chatText, setChatText] = React.useState('');
38         const [editCommand, setEditCommand] = React.useState('');
39         const [editCommandSettings, setEditCommandSettings] = React.useState({});
40         const [showCommandDialog, setShowCommandDialog] = React.useState(false);
41
42         const { t } = useTranslation();
43
44         const chat = React.useCallback(async (text, bot_nick) => {
45                 try {
46                         await axios.post(`/api/channels/${channel.id}/chat`, {
47                                 text,
48                                 bot_nick,
49                         });
50                         toastr.success(t('twitchBot.chatSuccess'));
51                 } catch (e) {
52                         toastr.error(t('twitchBot.chatError'));
53                 }
54         }, [channel, chatText, t]);
55
56         const randomChat = React.useCallback(async (category) => {
57                 try {
58                         await axios.post(`/api/channels/${channel.id}/chat`, {
59                                 bot_nick: 'horstiebot',
60                                 category,
61                         });
62                         toastr.success(t('twitchBot.chatSuccess'));
63                 } catch (e) {
64                         toastr.error(t('twitchBot.chatError'));
65                 }
66         }, [channel, chatText, t]);
67
68         const join = React.useCallback(async (bot_nick) => {
69                 try {
70                         const rsp = await axios.post(`/api/channels/${channel.id}/join`, { bot_nick });
71                         setChannel(rsp.data);
72                         toastr.success(t('twitchBot.joinSuccess'));
73                 } catch (e) {
74                         toastr.error(t('twitchBot.joinError'));
75                 }
76         }, [channel, t]);
77
78         const part = React.useCallback(async (bot_nick) => {
79                 try {
80                         const rsp = await axios.post(`/api/channels/${channel.id}/part`, { bot_nick });
81                         setChannel(rsp.data);
82                         toastr.success(t('twitchBot.partSuccess'));
83                 } catch (e) {
84                         toastr.error(t('twitchBot.partError'));
85                 }
86         }, [channel, t]);
87
88         const saveChatSettings = React.useCallback(async (values) => {
89                 try {
90                         const rsp = await axios.post(`/api/channels/${channel.id}/chat-settings`, values);
91                         setChannel(rsp.data);
92                         toastr.success(t('twitchBot.saveSuccess'));
93                 } catch (e) {
94                         toastr.error(t('twitchBot.saveError'));
95                 }
96         }, [channel, t]);
97
98         const onAddCommand = React.useCallback(() => {
99                 setEditCommand('');
100                 setEditCommandSettings({});
101                 setShowCommandDialog(true);
102         }, [channel]);
103
104         const onEditCommand = React.useCallback((name, settings) => {
105                 setEditCommand(name);
106                 setEditCommandSettings(settings);
107                 setShowCommandDialog(true);
108         }, [channel]);
109
110         const onRemoveCommand = React.useCallback(async (name) => {
111                 try {
112                         const rsp = await axios.delete(`/api/channels/${channel.id}/commands/${name}`);
113                         setChannel(rsp.data);
114                         toastr.success(t('twitchBot.saveSuccess'));
115                 } catch (e) {
116                         toastr.error(t('twitchBot.saveError'));
117                 }
118         }, [channel]);
119
120         const saveCommand = React.useCallback(async (values) => {
121                 try {
122                         const rsp = await axios.put(
123                                 `/api/channels/${channel.id}/commands/${values.name}`,
124                                 values,
125                         );
126                         setChannel(rsp.data);
127                         setShowCommandDialog(false);
128                         setEditCommand('');
129                         setEditCommandSettings({});
130                         toastr.success(t('twitchBot.saveSuccess'));
131                 } catch (e) {
132                         toastr.error(t('twitchBot.saveError'));
133                         throw e;
134                 }
135         }, [channel]);
136
137         const saveGuessingGame = React.useCallback(async (values) => {
138                 try {
139                         const rsp = await axios.put(
140                                 `/api/channels/${channel.id}/guessing-game/${values.name}`,
141                                 values,
142                         );
143                         setChannel(rsp.data);
144                         toastr.success(t('twitchBot.saveSuccess'));
145                 } catch (e) {
146                         toastr.error(t('twitchBot.saveError'));
147                         throw e;
148                 }
149         }, [channel]);
150
151         return <>
152                 <Row className="mb-4">
153                         <Form.Group as={Col} md={6}>
154                                 <Form.Label>{t('twitchBot.channel')}</Form.Label>
155                                 <Form.Control
156                                         as={ChannelSelect}
157                                         autoSelect
158                                         joinable
159                                         manageable
160                                         onChange={({ channel }) => { setChannel(channel); }}
161                                         value={channel ? channel.id : ''}
162                                 />
163                         </Form.Group>
164                         {channel ? <>
165                                 <Form.Group as={Col} md={3}>
166                                         <Form.Label>{t('twitchBot.joinApp')}</Form.Label>
167                                         <div>
168                                                 <Form.Control
169                                                         as={ToggleSwitch}
170                                                         onChange={({ target: { value } }) => {
171                                                                 if (value) {
172                                                                         join('localhorsttv');
173                                                                 } else {
174                                                                         part('localhorsttv');
175                                                                 }
176                                                         }}
177                                                         value={channel.join}
178                                                 />
179                                         </div>
180                                 </Form.Group>
181                                 <Form.Group as={Col} md={3}>
182                                         <Form.Label>{t('twitchBot.joinChat')}</Form.Label>
183                                         <div>
184                                                 <Form.Control
185                                                         as={ToggleSwitch}
186                                                         onChange={({ target: { value } }) => {
187                                                                 if (value) {
188                                                                         join('horstiebot');
189                                                                 } else {
190                                                                         part('horstiebot');
191                                                                 }
192                                                         }}
193                                                         value={channel.chat}
194                                                 />
195                                         </div>
196                                 </Form.Group>
197                         </> : null}
198                 </Row>
199                 {channel ?
200                         <Row>
201                                 <Col className="mt-5" md={6}>
202                                         <h3>{t('twitchBot.chat')}</h3>
203                                         <Form.Group>
204                                                 <Form.Label>{t('twitchBot.chat')}</Form.Label>
205                                                 <Form.Control
206                                                         as="textarea"
207                                                         onChange={({ target: { value } }) => {
208                                                                 setChatText(value);
209                                                         }}
210                                                         value={chatText}
211                                                 />
212                                                 <div className="button-bar">
213                                                         <Button
214                                                                 className="mt-2"
215                                                                 disabled={!chatText || !channel.join}
216                                                                 onClick={() => {
217                                                                         if (chatText) chat(chatText, 'localhorsttv');
218                                                                 }}
219                                                                 variant="twitch"
220                                                         >
221                                                                 {t('twitchBot.sendApp')}
222                                                         </Button>
223                                                         <Button
224                                                                 className="mt-2"
225                                                                 disabled={!chatText || !channel.chat}
226                                                                 onClick={() => {
227                                                                         if (chatText) chat(chatText, 'horstiebot');
228                                                                 }}
229                                                                 variant="twitch"
230                                                         >
231                                                                 {t('twitchBot.sendChat')}
232                                                         </Button>
233                                                 </div>
234                                         </Form.Group>
235                                         <h3 className="mt-3">{t('twitchBot.randomChat')}</h3>
236                                         <div className="button-bar">
237                                                 {CHAT_CATEGORIES.map(category =>
238                                                         <Button
239                                                                 key={category}
240                                                                 onClick={() => { randomChat(category); }}
241                                                                 variant="outline-secondary"
242                                                         >
243                                                                 {t(`twitchBot.chatCategories.${category}`)}
244                                                         </Button>
245                                                 )}
246                                         </div>
247                                 </Col>
248                                 <Col className="mt-5" md={6}>
249                                         <div className="d-flex justify-content-between">
250                                                 <h3>{t('twitchBot.chatSettings')}</h3>
251                                                 <div className="button-bar">
252                                                         <ChatBotLog id={channel.id} />
253                                                 </div>
254                                         </div>
255                                         <ChatSettingsForm channel={channel} onSubmit={saveChatSettings} />
256                                 </Col>
257                                 <Col className="mt-5" md={12}>
258                                         <h3>{t('twitchBot.commands')}</h3>
259                                         <Commands
260                                                 channel={channel}
261                                                 onEditCommand={onEditCommand}
262                                                 onRemoveCommand={onRemoveCommand}
263                                         />
264                                         <CommandDialog
265                                                 name={editCommand}
266                                                 onHide={() => {
267                                                         setShowCommandDialog(false);
268                                                         setEditCommand('');
269                                                         setEditCommandSettings({});
270                                                 }}
271                                                 onSubmit={saveCommand}
272                                                 settings={editCommandSettings}
273                                                 show={showCommandDialog}
274                                         />
275                                         <div>
276                                                 <Button onClick={onAddCommand} variant="primary">
277                                                         {t('twitchBot.addCommand')}
278                                                 </Button>
279                                         </div>
280                                 </Col>
281                                 <Col className="mt-5" md={12}>
282                                         <div className="d-flex align-items-end justify-content-between">
283                                                 <h3>{t('twitchBot.guessingGame.settings')}</h3>
284                                                 <div className="button-bar">
285                                                         {channel.access_key ?
286                                                                 <Button
287                                                                         href={`/guessing-game/monitor/${channel.access_key}`}
288                                                                         target="_blank"
289                                                                         title={t('button.browserSource')}
290                                                                         variant="outline-secondary"
291                                                                 >
292                                                                         <Icon.BROWSER_SOURCE title="" />
293                                                                 </Button>
294                                                         : null}
295                                                         <Button
296                                                                 onClick={() => {
297                                                                         window.open(
298                                                                                 `/guessing-game/controls/${channel.id}`,
299                                                                                 '',
300                                                                                 'width=640,height=800,titlebar=0,menubar=0,toolbar=0',
301                                                                         );
302                                                                 }}
303                                                                 title={t('twitchBot.guessingGame.popoutControls')}
304                                                                 variant="outline-secondary"
305                                                         >
306                                                                 <Icon.OPEN title="" />
307                                                         </Button>
308                                                 </div>
309                                         </div>
310                                         <GuessingSettingsForm
311                                                 name="gtbk"
312                                                 onSubmit={saveGuessingGame}
313                                                 settings={channel.guessing_settings?.gtbk || {}}
314                                         />
315                                 </Col>
316                         </Row>
317                 :
318                         <Alert variant="info">
319                                 {t('twitchBot.selectChannel')}
320                         </Alert>
321                 }
322         </>;
323 };
324
325 export default Controls;