· 4 years ago · Apr 06, 2021, 04:34 PM
1import {
2 Alert,
3 Badge,
4 Button,
5 Card,
6 Descriptions,
7 Divider,
8 Spin,
9 Tag,
10} from 'antd'
11import React from 'react'
12import {NavLink} from 'react-router-dom'
13
14import {
15 checkIrcCredsValidity,
16 checkApiKeyValidity,
17} from '../actions/checkCredsValidity'
18import {
19 tagTooltipMapping as modsMap,
20 teamModeStringMapping as teamMap,
21 teamModeIntMapping,
22} from '../actions/mapping'
23
24import Bot from 'osu-lobby-bot/src/bot/bot'
25const Bancho = require('bancho.js')
26const BotConnectionStatus = require('osu-lobby-bot/src/bot/enums/connectionStatus')
27
28const verify = async data => {
29 let errorMessages = []
30
31 const validApiCreds = await checkApiKeyValidity(data.apiKey)
32 if (!validApiCreds) {
33 errorMessages.push({
34 message: 'Invalid API Key.',
35 link: '/api',
36 })
37 }
38
39 const validIrcCreds = await checkIrcCredsValidity(
40 data.ircUsername,
41 data.ircPassword,
42 )
43 if (!validIrcCreds) {
44 errorMessages.push({
45 message: 'Invalid IRC Username / Password. Click to fix.',
46 link: '/api',
47 type: 'error',
48 loading: false,
49 })
50 }
51
52 if (!Boolean(data.lobbyName) || data.lobbyName.trim() === '') {
53 errorMessages.push({
54 message: 'You have to set up your game. Click to fix.',
55 link: '/game',
56 type: 'error',
57 loading: false,
58 })
59 }
60
61 return errorMessages
62}
63
64let ownRef
65
66export default function BotStatus({data, menuActive, setMenuActive}) {
67 const [errors, setErrors] = React.useState([])
68 const [started, setStarted] = React.useState(false)
69 const [running, setRunning] = React.useState(false)
70 const [currentHost, setCurrentHost] = React.useState('n/a')
71 const [currentPlayers, setCurrentPlayers] = React.useState(0)
72
73 React.useEffect(() => {
74 console.log('BotStatus deps: mount')
75
76 console.log('BOT CURRENT')
77 console.log(ownRef)
78
79 if (Boolean(ownRef)) {
80 ownRef.on('started', () => setRunning(true))
81 ownRef.on('error', () => {
82 setRunning(false)
83 setCurrentHost('n/a')
84 setCurrentPlayers(0)
85 })
86 ownRef.on('playerQueue', playerCount => {
87 setCurrentPlayers(playerCount)
88 })
89 ownRef.on('host', currentHost => {
90 setCurrentHost(currentHost)
91 })
92 }
93
94 if (started && !Boolean(ownRef)) {
95 console.log('BotStatus deps: start bot')
96 ownRef = new Bot(
97 new Bancho.BanchoClient({
98 username: data.ircUsername,
99 password: data.ircPassword,
100 apiKey: data.apiKey,
101 }),
102 {...data, teamMode: teamModeIntMapping[data.teamMode]},
103 )
104
105 ownRef.on('started', () => setRunning(true))
106 ownRef.on('error', () => {
107 setRunning(false)
108 setCurrentHost('n/a')
109 setCurrentPlayers(0)
110 })
111 ownRef.on('playerQueue', playerCount => {
112 setCurrentPlayers(playerCount)
113 })
114 ownRef.on('host', currentHost => {
115 setCurrentHost(currentHost)
116 })
117
118 ownRef.start()
119 setMenuActive(false)
120 }
121
122 if (
123 !started &&
124 Boolean(ownRef) &&
125 ownRef.connectionStatus === BotConnectionStatus.CONNECTED
126 ) {
127 console.log('BotStatus deps: stop bot')
128
129 ownRef.removeAllListeners('started')
130 ownRef.removeAllListeners('error')
131 ownRef.removeAllListeners('playerQueue')
132 ownRef.removeAllListeners('host')
133
134 ownRef.stop()
135
136 ownRef = null
137 setMenuActive(true)
138 }
139
140 return () => {
141 console.log('BotStatus deps: unmount')
142 if (Boolean(ownRef)) {
143 ownRef.removeAllListeners('started')
144 ownRef.removeAllListeners('error')
145 ownRef.removeAllListeners('playerQueue')
146 ownRef.removeAllListeners('host')
147 }
148 }
149 }, [started])
150
151 const asyncVerify = async () => {
152 setErrors([
153 {
154 message: 'Checking...',
155 link: '/bot',
156 type: 'warning',
157 loading: true,
158 },
159 ])
160 const errors = await verify(data)
161 setErrors(errors)
162 }
163 React.useEffect(() => asyncVerify(), [])
164
165 const handleBotStart = e => {
166 if (errors.length > 0) {
167 return
168 }
169 console.log('CLICK START')
170 setStarted(true)
171 e.preventDefault()
172 }
173
174 const handleBotStop = e => {
175 setStarted(false)
176 e.preventDefault()
177 }
178
179 return (
180 <>
181 <Card title="Bot status">
182 {errors.length > 0 ? (
183 errors.map(error => (
184 <React.Fragment key={error.message}>
185 <Spin spinning={error.loading}>
186 <NavLink to={error.link}>
187 <Alert type={error.type} message={error.message} />
188 </NavLink>
189 </Spin>
190 </React.Fragment>
191 ))
192 ) : (
193 <>
194 <Descriptions bordered>
195 <Descriptions.Item label="Status">
196 <Badge
197 status={running ? 'processing' : 'error'}
198 text={running ? 'Running' : 'Stopped'}
199 />
200 </Descriptions.Item>
201 <Descriptions.Item label="Current players">
202 {currentPlayers}/{data.size}
203 </Descriptions.Item>
204 <Descriptions.Item label="Current host">
205 {currentHost}
206 </Descriptions.Item>
207 </Descriptions>
208 <Divider />
209 <Descriptions bordered title="Game data">
210 <Descriptions.Item label="Lobby Name" span={3}>
211 {data.lobbyName}
212 </Descriptions.Item>
213 <Descriptions.Item label="Maximum Players" span={3}>
214 {data.size}
215 </Descriptions.Item>
216 <Descriptions.Item label="Team Mode" span={3}>
217 {teamMap[data.teamMode]}
218 </Descriptions.Item>
219 {data.minStars > 0 && (
220 <Descriptions.Item label="Minimum Stars" span={3}>
221 {data.minStars}
222 </Descriptions.Item>
223 )}
224 {data.maxStars > 0 && (
225 <Descriptions.Item label="Maximum Stars" span={3}>
226 {data.maxStars}
227 </Descriptions.Item>
228 )}
229 <Descriptions.Item label="Allowed Mods" span={3}>
230 {data.mods.map(modKey => (
231 <React.Fragment key={modKey}>
232 <Tag color="default">{modsMap[modKey]}</Tag>
233 </React.Fragment>
234 ))}
235 </Descriptions.Item>
236 </Descriptions>
237 {menuActive ? (
238 <Button onClick={handleBotStart}>Start Bot</Button>
239 ) : (
240 <Button onClick={handleBotStop}>Stop Bot</Button>
241 )}
242 </>
243 )}
244 </Card>
245 </>
246 )
247}