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