· 5 years ago · Aug 18, 2020, 02:18 PM
1<!DOCTYPE html>
2<html>
3<head>
4 <title></title>
5 <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
6 <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
7 <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
8</head>
9<body>
10 <div id="root"></div>
11 <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
12 <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
13
14 <script>
15 window.jQuery = window.$ = require('jquery');
16
17 const OBSWebSocket = require('obs-websocket-js');
18 const fs = require('fs');
19 const TeemoJS = require('teemojs');
20 const obs = new OBSWebSocket();
21
22 const e = React.createElement;
23
24 window.onload = () => {
25 //CONTEXT
26 const ScenesContext = React.createContext();
27 const StatusContext = React.createContext();
28 //CONTROLS
29 const Controls = (props) => {
30 const [status, setStatus] = React.useContext(StatusContext);
31 const [scenes, setScenes] = React.useContext(ScenesContext);
32 const connect = async() => {
33 try{
34 await obs.connect();
35 setStatus({connected: true});
36 } catch(err){
37 if(err.status==='error'){
38 setStatus({connected: false});
39 }
40 console.log(err);
41 } finally{
42 console.log(status);
43 }
44 }
45
46 const getScenes = async() => {
47 try{
48 let sceneList = await obs.send('GetSceneList');
49 setScenes(sceneList.scenes);
50 console.log(sceneList);
51 }catch(e){
52 console.error(e);
53 }
54 }
55
56 const statusDiv = e('div', {key:'status'}, 'Connected : ' + status.connected);
57 const connectButton = e('button', { onClick: connect, key: 'connectButton' }, 'Connect');
58 const scenesButton = e('button', { onClick: getScenes, key: 'scenesButton'}, 'Get scenes');
59
60 const div = e('div', null, [statusDiv, connectButton, scenesButton]);
61
62 return div;
63 }
64
65 //SCENES
66 const Scenes = (props) => {
67 const [scenes, setScenes] = React.useContext(ScenesContext);
68 const { selectedScene, setSelectedScene } = props;
69 const containerDiv = e('ul', { className: 'list-group' }, scenes.map((elem, index)=>{
70 return e('li', { key: index, className: 'list-group-item'+(selectedScene===elem.name?' active':''), onClick: ()=>setSelectedScene(elem.name) }, elem.name)
71 }));
72
73 return containerDiv;
74 }
75
76 //SOURCES
77 const Sources = (props) => {
78 const { selectedScene, selectedSources, setSelectedSources } = props
79 const [scenes, setScenes] = React.useContext(ScenesContext);
80
81 const selectSource = (name) => {
82 const index = selectedSources.indexOf(name);
83 if(index > -1){
84 setSelectedSources(selectedSources.map(elem=>elem.name!==name));
85 }else{
86 setSelectedSources([...selectedSources, name]);
87 }
88 }
89
90 let sourceList=null;
91 try{
92 sourceList = scenes.find(elem=>elem.name===selectedScene).sources.map((elem, index)=>{
93 return e('li', { key: index, className: 'list-group-item' + (selectedSources.includes(elem.name)?' active':''), onClick: () => selectSource(elem.name) }, elem.name)
94 });
95 }catch{}
96 const containerDiv = e('ul', { className: 'list-group' }, sourceList);
97 return containerDiv;
98 }
99
100 //TOP1
101 const Top1 = (props) => {
102 const [totalTop1, setTotalTop1] = React.useState(0);
103 const [dailyTop1, setDailyTop1] = React.useState(0);
104
105 const [validated, setValidated] = React.useState(false);
106
107 const { selectedSources } = props;
108
109 console.log(selectedSources);
110
111 const updateTotal = (e) => {
112 setTotalTop1(e.target.value);
113 }
114
115 const updateDaily = (e) => {
116 setDailyTop1(e.target.value);
117 }
118
119 const plus = () => {
120 try{
121 const newDailyValue = parseInt(dailyTop1) + 1;
122 setDailyTop1(newDailyValue);
123 obs.send('SetTextFreetype2Properties',{
124 source:selectedSources[1],
125 text:'Daily top1 : '+newDailyValue
126 });
127 const newTotalValue = parseInt(totalTop1) + 1;
128 setTotalTop1(newTotalValue);
129 obs.send('SetTextFreetype2Properties',{
130 source:selectedSources[0],
131 text:'Total top1 : '+newTotalValue
132 });
133 }catch(e){}
134 }
135 const minus = () => {
136 try{
137 const newDailyValue = parseInt(dailyTop1) - 1;
138 setDailyTop1(newDailyValue);
139 obs.send('SetTextFreetype2Properties',{
140 source:selectedSources[1],
141 text:'Daily top1 : '+newDailyValue
142 });
143 const newTotalValue = parseInt(totalTop1) - 1;
144 setTotalTop1(newTotalValue);
145 obs.send('SetTextFreetype2Properties',{
146 source:selectedSources[0],
147 text:'Total top1 : '+newTotalValue
148 });
149 }catch(e){}
150 }
151
152
153 const totalInput = e(
154 'input',
155 { key:'inputTop1', disabled: validated, onChange: updateTotal, value: totalTop1, type: 'text', className: 'form-control', 'aria-describedby': 'totalTop1' },
156 null
157 );
158 const totalInputGroup = e(
159 'div',
160 { key: 'totalInputGroup', className: 'input-group-prepend' },
161 e(
162 'span',
163 { className:'input-group-text', id:'totalTop1' },
164 'Total top 1'
165 )
166 );
167 const totalInputForm = e(
168 'div',
169 {
170 key: 'totalInputForm',
171 className: 'input-group mb-2'
172 },
173 [totalInputGroup, totalInput]
174 )
175
176 const dailyInput = e(
177 'input',
178 { key:'inputTop1', disabled: validated ,onChange: updateDaily, value: dailyTop1, type: 'text', className: 'form-control', 'aria-describedby': 'dailyTop1' },
179 null
180 );
181 const dailyInputGroup = e(
182 'div',
183 { key: 'totalInputGroup', className: 'input-group-prepend' },
184 e(
185 'span',
186 { className:'input-group-text', id:'dailyTop1' },
187 'Daily top 1'
188 )
189 );
190 const dailyInputForm = e(
191 'div',
192 {
193 key: 'dailyInputForm',
194 className: 'input-group mb-2'
195 },
196 [dailyInputGroup, dailyInput]
197 )
198
199 const validateButton = e(
200 'button',
201 {
202 key:'validateButton',
203 onClick: ()=>setValidated(true)
204 },
205 'Set'
206 )
207
208 const plusButton = e(
209 'button',
210 {
211 key:'plusButton',
212 onClick: plus,
213 className: 'p-2'
214 },
215 '+'
216 );
217 const minusButton = e(
218 'button',
219 {
220 key:'minusButton',
221 onClick: minus,
222 className: 'p-2'
223 },
224 '-'
225 );
226 const actionsDiv = e(
227 'div',
228 {
229 key: 'actionsDiv',
230 className: 'd-flex flex-column'
231 },
232 [plusButton, minusButton]
233 )
234
235 const forms = e(
236 'div',
237 {
238 key: 'forms',
239 className: 'd-flex flex-column'
240 },
241 [totalInputForm, dailyInputForm, validateButton]
242 )
243
244 return e(
245 'div',
246 {
247 className: 'd-flex flex-row'
248 },
249 [ forms, actionsDiv ]
250 );
251
252 }
253
254 //HOME
255 const Home = (props) => {
256 const [selectedScene, setSelectedScene] = React.useState(null);
257 const [selectedSources, setSelectedSources] = React.useState([]);
258
259 const [scenes, setScenes] = React.useContext(ScenesContext);
260
261 const controlPanel = e(
262 Controls, { key: 'controlPanel', className: 'p-2', width:'20%' }, null
263 );
264
265 const scenesPanel = e(
266 Scenes, { key: 'scenesPanel', selectedScene, setSelectedScene, className: 'p-2', width:'20%' }, null
267 );
268
269 const sourcesPanel = e(
270 Sources, { key: 'sourcesPanel', selectedScene, selectedSources, setSelectedSources, className: 'p-2', width: '20%' }, null
271 );
272
273 const top1Panel = e(
274 Top1, { key: 'top1Panel', selectedSources, className: 'p-2', width: '40%'}, null
275 );
276
277 return e('div', { className: 'd-flex flex-row' }, [controlPanel, scenesPanel, sourcesPanel, top1Panel]);
278 }
279
280
281 const KeyManager = (props) => {
282 const { apiKey, updateApiKey } = props;
283 const [tmpKey, setTmpKey] = React.useState(apiKey);
284
285
286 const keyInput = e(
287 'input',
288 {
289 key: 'keyInput',
290 className: 'form-control',
291 'aria-describedby': 'rgkey',
292 type:'text',
293 onChange: (e)=>{setTmpKey(e.target.value)},
294 value:tmpKey
295 },
296 null
297 );
298 const keyInputGroup = e(
299 'div',
300 {
301 key: 'keyInputGroup',
302 className: 'input-group-prepend'
303 },
304 e(
305 'span',
306 {
307 className: 'input-group-text',
308 id: 'rgkey'
309 },
310 'Api key'
311 )
312 );
313 const keyInputForm = e(
314 'div',
315 {
316 key: 'keyInputForm',
317 className: 'input-group mb-2 p-2'
318 },
319 [keyInputGroup, keyInput]
320 );
321 const validateButton = e(
322 'button',
323 {
324 key:'validateButton',
325 className: 'p-2',
326 onClick: ()=>updateApiKey(tmpKey)
327 },
328 'Set'
329 );
330 const form = e(
331 'div',
332 {
333 key: 'apiKey-form',
334 className: 'd-flex flex-column'
335 },
336 [keyInputForm, validateButton]
337 );
338 return form;
339 }
340
341 const EloApp = (props) => {
342 const summonerId = '0qJZ4l1m4XOumee8Uyvs0O9Y31oSSy7300EloCfkx1QLnMM';
343 let existingKey='';
344 let api;
345 try{
346 existingKey=fs.readFileSync('./key');
347 api = TeemoJS(existingKey.toString());
348 }catch(e){
349
350 }
351 const [apiKey, setApiKey] = React.useState(existingKey);
352 const [on, setOn] = React.useState(false);
353 const [elo, setElo] = React.useState('not retrieved yet');
354 const [message, setMessage] = React.useState('');
355 const [retrieving, setRetrieving] = React.useState(null);
356 const [OBSStatus, setOBSStatus] = React.useState({connected:false});
357 console.log('update', elo);
358
359 const updateApiKey = (key) => {
360 setApiKey(key);
361 fs.writeFileSync('./key', key);
362 api = TeemoJS(key.toString());
363 console.log(api);
364 }
365
366 const updateStatus = (status) => {
367 setOn(status);
368 console.log('should retrieve : '+status);
369 if(status){
370 setRetrieving(setInterval(retrieve, 10000));
371 }else{
372 clearInterval(retrieving);
373 }
374 }
375
376 const updateElo = (newElo) => {
377 setElo(newElo);
378 if(OBSStatus.connected){
379 try{
380 obs.send('SetTextFreetype2Properties',{
381 source:'elo',
382 text:newElo
383 });
384 }catch(e){}
385 }
386 }
387
388 const connectObs = async() => {
389 try{
390 await obs.connect();
391 setOBSStatus({connected: true});
392 } catch(err){
393 if(err.status==='error'){
394 setOBSStatus({connected: false});
395 }
396 console.log(err);
397 } finally{
398 console.log(OBSStatus);
399 }
400 }
401
402 const retrieve = async() => {
403 console.log('retrieving');
404 if(api){
405 let data = await api.get('euw1', 'league.getLeagueEntriesForSummoner', summonerId);
406 console.log(data);
407 let soloQ = data.find(elem=>elem.queueType==="RANKED_SOLO_5x5");
408 if(soloQ){
409 let rank;
410 switch(soloQ.rank){
411 case 'I':
412 rank = '1';
413 break;
414 case 'II':
415 rank = '2';
416 break;
417 case 'II':
418 rank = '3';
419 break;
420 case 'IV':
421 rank = '4';
422 break;
423 }
424 let tmpElo = soloQ.tier.substring(0,1) + rank + ' ' + soloQ.leaguePoints + 'LP';
425 console.log(tmpElo);
426 updateElo(tmpElo);
427 }
428 }
429 }
430
431 const onButton = e(
432 'button',
433 {
434 key:'onButton',
435 className:'p-2',
436 style:{width:'20%'},
437 onClick: ()=>{updateStatus(!on)}
438 },
439 (on?'On':'Off')
440 );
441
442 const keyManager = e(
443 KeyManager,
444 {
445 key: 'keyManager',
446 className: 'p-2',
447 apiKey,
448 updateApiKey
449 },
450 null
451 );
452
453 const currentElo = e(
454 'div',
455 {
456 key: 'currentElo',
457 className: 'p-2'
458 },
459 e(
460 'h3',
461 null,
462 elo
463 )
464 );
465 const connectDiv = e(
466 'div',
467 {
468 key:'connectDiv',
469 className:'p-2'
470 },
471 e(
472 'button',
473 {
474 onClick: connectObs
475 },
476 'Connect OBS'
477 )
478 )
479
480 return e(
481 'div',
482 {
483 className: 'p-2 d-flex flex-row'
484 },
485 [connectDiv, keyManager, onButton, currentElo]
486 );
487 }
488
489 //APP
490 const FGApp = (props) => {
491 const [scenes, setScenes] = React.useState([]);
492 const [status, setStatus] = React.useState({connected: false});
493
494 const div = e(
495 ScenesContext.Provider,
496 {
497 value: [scenes, setScenes]
498 },
499 e(Home)
500 )
501
502 return (
503 e(
504 StatusContext.Provider,
505 {
506 className: 'p-2',
507 value: [status, setStatus]
508 },
509 div
510 )
511 );
512 }
513
514
515 const App = (props) => {
516 const fgTitle = e(
517 'div',
518 {
519 key: 'FGTitle',
520 className:'p-2',
521 style:{width:'100%'}
522 },
523 e(
524 'h2',
525 { style: { textAlign: 'center' } },
526 'Fall Guys'
527 )
528 );
529
530 const lolTitle = e(
531 'div',
532 {
533 key: 'lolTitle',
534 className:'p-2',
535 style:{width:'100%'}
536 },
537 e(
538 'h2',
539 { style: { textAlign: 'center' } },
540 'LoL'
541 )
542 );
543
544
545 const container = e(
546 'div',
547 {
548 className: 'd-flex flex-column'
549 },
550 [
551 fgTitle,
552 e(FGApp, { key: 'fgapp' }),
553 e(
554 'div',
555 {
556 className: 'p-2',
557 key: 'divider',
558 style: {width:'100%', borderTop:'1px solid black', marginTop:'10px' }
559 },
560 null
561 ),
562 lolTitle,
563 e(EloApp, { key: 'eloapp' })
564 ]
565 )
566
567 return container;
568 }
569
570 ReactDOM.render(
571 e(App),
572 document.querySelector('#root')
573 );
574 }
575 </script>
576
577</body>
578</html>