Total Complexity | 175 |
Total Lines | 568 |
Duplicated Lines | 4.75 % |
Changes | 0 |
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like Portal_World often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | try: |
||
2 | import http.server |
||
3 | from twitchio.ext import commands |
||
4 | from twitchio.errors import AuthenticationError,EchoMessageWarning |
||
5 | import json |
||
6 | from re import search,findall,IGNORECASE,MULTILINE |
||
7 | from sys import argv |
||
8 | import os |
||
9 | import threading |
||
10 | import time |
||
11 | import ctypes |
||
12 | import steam |
||
13 | import socketserver |
||
14 | import webbrowser |
||
15 | except ImportError as e: |
||
16 | input(str(e)) |
||
17 | exit() |
||
18 | |||
19 | class Bot(commands.Bot): |
||
20 | |||
21 | def __init__(self): |
||
22 | with open(path3 + '/def.txt','r') as infile: |
||
23 | default = infile.read() |
||
24 | with open(path3 + '/settings.txt', 'r') as infile: |
||
25 | settings = infile.read() |
||
26 | mat = findall(r'"(.+?)"', settings) |
||
27 | if len(mat) < 6 or default == settings: |
||
28 | print('Error, please fill settings.txt completely in first.') |
||
29 | exit() |
||
30 | self.user_count = mat[3] |
||
31 | self.settings = mat |
||
32 | try: |
||
33 | super().__init__(irc_token=mat[0],prefix=mat[5], nick=mat[1], initial_channels=[mat[2]]) |
||
34 | except AuthenticationError: |
||
35 | print('settings.txt not filled in correctly. Please close this window and check you settings.') |
||
36 | |||
37 | def close(self): |
||
38 | os.system('exit') |
||
39 | |||
40 | # Events don't need decorators when subclassed |
||
41 | async def event_ready(self): |
||
42 | print(f'Ready | {self.nick}') |
||
43 | |||
44 | async def send_message(self,message,channel): |
||
45 | if len(message) == 0 or message == None: |
||
46 | return |
||
47 | if len(message) < 500: |
||
48 | await channel.send(message) |
||
49 | return |
||
50 | |||
51 | while len(message) >= 500: |
||
52 | await channel.send(message[:499]) |
||
53 | message = message[499:] |
||
54 | if len(message) != 0: |
||
55 | await channel.send(message) |
||
56 | |||
57 | async def event_message(self, message): |
||
58 | try: |
||
59 | if message.author == self.nick: |
||
60 | return |
||
61 | |||
62 | await self.handle_commands(message) |
||
63 | |||
64 | await self.help_command(message) |
||
65 | |||
66 | except Exception as e: |
||
67 | if isinstance(e,commands.errors.CommandNotFound) or isinstance(e,EchoMessageWarning): |
||
68 | return |
||
69 | await message.channel.send("Uncaught error: {}".format(e)) |
||
70 | |||
71 | async def event_command_error(self, ctx, error): |
||
72 | if isinstance(error, commands.errors.CommandNotFound) or isinstance(error,EchoMessageWarning): |
||
73 | return |
||
74 | raise error |
||
75 | |||
76 | async def help_command(self,ctx): |
||
77 | if len(self.settings) >= 8: |
||
78 | if ctx.content.startswith(str(self.settings[5]) + str(self.settings[7])): |
||
79 | await self.send_message('{0}add[submit] (level url), {0}remove[delete] (level name, url or id), {0}list[queue,q], {0}mylist[myqueue,myq], {0}current[np]'.format(self.settings[5]), ctx.channel) |
||
80 | |||
81 | # Commands use a different decorator |
||
82 | @commands.command(name='add',aliases=['submit']) |
||
83 | async def add(self, ctx): |
||
84 | with open(path,'r') as infile: |
||
85 | data = json.load(infile) |
||
86 | try: |
||
87 | if data[len(data) - 1] == False: |
||
88 | await self.send_message("Couldn't add level due to the queue being locked",ctx) |
||
89 | return |
||
90 | except IndexError: |
||
91 | pass |
||
92 | |||
93 | mat = search(r"""(?:(?:https?|ftp|file):\/\/|www\.|ftp\.)(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[-A-Z0-9+&@#\/%=~_|$?!:,.])*(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[A-Z0-9+&@#\/%=~_|$])\?id=(\d*)""", ctx.content, IGNORECASE) |
||
94 | if mat: |
||
95 | levelLink = mat.string |
||
96 | authId = mat.group(1) |
||
97 | |||
98 | levelJson = steam.webapi.post(interface='ISteamRemoteStorage',method='GetPublishedFileDetails',params={'itemcount': 1, 'publishedfileids[0]':authId}) |
||
99 | |||
100 | if levelJson: |
||
101 | levelName = levelJson['response']['publishedfiledetails'][0]['title'] |
||
102 | sId = levelJson['response']['publishedfiledetails'][0]['creator'] |
||
103 | |||
104 | try: |
||
105 | if int(levelJson['response']['publishedfiledetails'][0]['consumer_app_id']) != int(self.settings[6]): |
||
106 | await self.send_message("Couldn't add item due to it not being for the correct game",ctx) |
||
107 | return |
||
108 | except ValueError: |
||
109 | pass |
||
110 | |||
111 | uinfo = steam.webapi.get(interface='ISteamUser',method='GetPlayerSummaries',version=2,params={'key':'ABCE07D6D3E64ECBB4733E9E3DA30892','steamids':sId}) |
||
112 | if uinfo: |
||
113 | authorName = uinfo['response']['players'][0]['personaname'] |
||
114 | |||
115 | i = 0 |
||
116 | for level in data: |
||
117 | if len(data) > 2: |
||
118 | if level['twitchID'] == ctx.author.id: |
||
119 | i += 1 |
||
120 | if level['link'].lower() == levelLink.lower(): |
||
121 | await self.send_message('Unable to add level due to {0} already being in the queue!'.format(levelName),ctx) |
||
122 | return |
||
123 | |||
124 | if len(data) > int(self.user_count) - 1: |
||
125 | if i >= int(self.user_count): |
||
126 | await self.send_message('Unable to add level due to {0} already having {1} levels in the queue!'.format(ctx.author.display_name,self.user_count),ctx) |
||
127 | return |
||
128 | |||
129 | with open(path,'w') as outfile: |
||
130 | data.append({'link':levelLink,'levelName':levelName,'twitchID':ctx.author.id,'levelMakerName':authorName,'submitterName':ctx.author.display_name}) |
||
131 | json.dump(data,outfile) |
||
132 | await self.send_message(f'Succesfully added {levelName} to the queue at place {len(data)}!',ctx) |
||
133 | else: |
||
134 | await ctx.send('Error with steam api') |
||
135 | else: |
||
136 | await ctx.send('Error finding level, is the url correct?') |
||
137 | else: |
||
138 | mat = findall(f"{self.settings[5]}([\\w]+)\\s",ctx.content) |
||
139 | if mat: |
||
140 | await ctx.send(f'Invalid syntax, {self.settings[5]}{mat[0]} [level url]') |
||
141 | else: |
||
142 | await ctx.send('Invalid syntax') |
||
143 | |||
144 | @commands.command(name='remove', aliases=['delete']) |
||
145 | async def remove(self, ctx): |
||
146 | mat = findall(r"""(?:(?:https?|ftp|file):\/\/|www\.|ftp\.)(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[-A-Z0-9+&@#\/%=~_|$?!:,.])*(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[A-Z0-9+&@#\/%=~_|$])""", ctx.content, IGNORECASE) |
||
147 | if mat: |
||
148 | with open(path, 'r') as infile: |
||
149 | levels = json.load(infile) |
||
150 | i = 0 |
||
151 | for level in levels: |
||
152 | View Code Duplication | if level['link'].lower() == mat[0].lower(): |
|
|
|||
153 | if level['twitchID'] == ctx.author.id or ctx.author.is_mod: |
||
154 | if i == 0: |
||
155 | await ctx.send('Cannot remove level due to it currently being played.') |
||
156 | else: |
||
157 | lname = level['levelName'] |
||
158 | levels.pop(i) |
||
159 | with open(path, 'w') as outfile: |
||
160 | json.dump(levels, outfile) |
||
161 | |||
162 | await self.send_message(f'Succesfully removed {lname} from list!', ctx) |
||
163 | else: |
||
164 | await self.send_message('Cannot remove level because {0} submitted it, not {1}.'.format(level['submitterName'], ctx.author.display_name), ctx) |
||
165 | break |
||
166 | i += 1 |
||
167 | |||
168 | else: |
||
169 | mat = search(r"\s(\d)", ctx.content) |
||
170 | if mat: |
||
171 | with open(path, 'r') as infile: |
||
172 | levels = json.load(infile) |
||
173 | i = int(mat.group(1)) - 1 |
||
174 | if i == 0: |
||
175 | await ctx.send('Cannot remove level due to it currently being played.') |
||
176 | elif i + 1 > len(levels): |
||
177 | await ctx.send('Invalid level id') |
||
178 | else: |
||
179 | if level['twitchID'] == ctx.author.id or ctx.author.is_mod: |
||
180 | lname = level['levelName'] |
||
181 | levels.pop(i) |
||
182 | with open(path, 'w') as outfile: |
||
183 | json.dump(levels, outfile) |
||
184 | |||
185 | await self.send_message(f'Succesfully removed {lname} from list!', ctx) |
||
186 | else: |
||
187 | await self.send_message('Cannot remove level because {0} submitted it, not {1}.'.format(level['submitterName'], ctx.author.display_name), ctx) |
||
188 | else: |
||
189 | mat = search(r"\s(.+)", ctx.content) |
||
190 | if mat: |
||
191 | with open(path, 'r') as infile: |
||
192 | levels = json.load(infile) |
||
193 | i = 0 |
||
194 | for level in levels: |
||
195 | View Code Duplication | if level['levelName'].lower() == mat.group(1).lower(): |
|
196 | if level['twitchID'] == ctx.author.id or ctx.author.is_mod: |
||
197 | if i == 0: |
||
198 | await ctx.send('Cannot remove level due to it currently being played.') |
||
199 | else: |
||
200 | lname = level['levelName'] |
||
201 | levels.pop(i) |
||
202 | with open(path, 'w') as outfile: |
||
203 | json.dump(levels, outfile) |
||
204 | await self.send_message(f'Succesfully removed {lname} from list!', ctx) |
||
205 | else: |
||
206 | await self.send_message('Cannot remove level because {0} submitted it, not {1}.'.format(level['submitterName'], ctx.author.display_name), ctx) |
||
207 | break |
||
208 | i += 1 |
||
209 | else: |
||
210 | mat = findall(f"{self.settings[5]}([\\w]+)\\s", ctx.content) |
||
211 | if mat: |
||
212 | await ctx.send(f'Invalid syntax, {self.settings[5]}{mat[0]} [link, level name or level id]') |
||
213 | else: |
||
214 | await ctx.send('You should not be seeing this, something went terribly wrong. Anyways, incorrect syntax.') |
||
215 | |||
216 | @commands.command(name='promote') |
||
217 | async def promote(self,ctx): |
||
218 | mat = findall(r"""(?:(?:https?|ftp|file):\/\/|www\.|ftp\.)(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[-A-Z0-9+&@#\/%=~_|$?!:,.])*(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[A-Z0-9+&@#\/%=~_|$])""", ctx.content, IGNORECASE) |
||
219 | if mat: |
||
220 | with open(path, 'r') as infile: |
||
221 | levels = json.load(infile) |
||
222 | i = 0 |
||
223 | for level in levels: |
||
224 | if level['link'].lower() == mat[0].lower(): |
||
225 | if ctx.author.is_mod: |
||
226 | if i == 0: |
||
227 | await ctx.send('Cannot promote level due to it currently being played.') |
||
228 | else: |
||
229 | lname = level['levelName'] |
||
230 | levels.pop(i) |
||
231 | levels.insert(1, level) |
||
232 | with open(path, 'w') as outfile: |
||
233 | json.dump(levels, outfile) |
||
234 | |||
235 | await self.send_message(f'{lname} is now up next!', ctx) |
||
236 | break |
||
237 | i += 1 |
||
238 | else: |
||
239 | mat = search(r"\s(\d)", ctx.content) |
||
240 | if mat: |
||
241 | with open(path, 'r') as infile: |
||
242 | levels = json.load(infile) |
||
243 | i = int(mat.group(1)) - 1 |
||
244 | if ctx.author.is_mod: |
||
245 | if i == 0: |
||
246 | await ctx.send('Cannot promote level due to it currently being played.') |
||
247 | elif i + 1 > len(levels): |
||
248 | await ctx.send('Invalid level id') |
||
249 | else: |
||
250 | level = levels[i] |
||
251 | lname = level['levelName'] |
||
252 | levels.pop(i) |
||
253 | levels.insert(1, level) |
||
254 | with open(path, 'w') as outfile: |
||
255 | json.dump(levels, outfile) |
||
256 | await self.send_message(f'{lname} is now up next!', ctx) |
||
257 | else: |
||
258 | mat = search(r"\s(.+)", ctx.content) |
||
259 | if mat: |
||
260 | with open(path, 'r') as infile: |
||
261 | levels = json.load(infile) |
||
262 | i = 0 |
||
263 | for level in levels: |
||
264 | if level['levelName'].lower() == mat.group(1).lower(): |
||
265 | if ctx.author.is_mod: |
||
266 | if i == 0: |
||
267 | await ctx.send('Cannot promote level due to it currently being played.') |
||
268 | else: |
||
269 | lname = level['levelName'] |
||
270 | levels.pop(i) |
||
271 | levels.insert(1, level) |
||
272 | with open(path, 'w') as outfile: |
||
273 | json.dump(levels, outfile) |
||
274 | |||
275 | await self.send_message(f'{lname} is now up next!', ctx) |
||
276 | break |
||
277 | i += 1 |
||
278 | else: |
||
279 | self.send_message(f'Invalid syntax: {self.settings[5]}promote [level name, url or id]',ctx) |
||
280 | |||
281 | @commands.command(name='list',aliases=['queue','q']) |
||
282 | async def list(self,ctx): |
||
283 | with open(path,'r') as infile: |
||
284 | levels = json.load(infile) |
||
285 | out = "" |
||
286 | i = 1 |
||
287 | if len(levels) > 0: |
||
288 | if levels[len(levels) - 1] == False: |
||
289 | levels = levels[:len(levels) - 1] |
||
290 | if len(levels) <= int(self.settings[4]): |
||
291 | for level in levels: |
||
292 | out += "{3} - Level: '{0}' - Made by: '{1}' - Submitted by: '{2}' ".format(level['levelName'],level['levelMakerName'],level['submitterName'],i) |
||
293 | i += 1 |
||
294 | await self.send_message(out,ctx) |
||
295 | else: |
||
296 | for level in levels: |
||
297 | if i <= int(self.settings[4]): |
||
298 | out += "{3} - Level: '{0}' - Made by: '{1}' - Submitted by: '{2}' ".format(level['levelName'],level['levelMakerName'],level['submitterName'],i) |
||
299 | i += 1 |
||
300 | if i > int(self.settings[4]): |
||
301 | ileft = i - int(self.settings[4]) |
||
302 | out += f" And {ileft} more levels in queue." |
||
303 | await self.send_message(out,ctx) |
||
304 | else: |
||
305 | await ctx.send('The queue is currently empty.') |
||
306 | |||
307 | @commands.command(name='mylist',aliases=['myqueue','myq']) |
||
308 | async def mylist(self,ctx): |
||
309 | with open(path,'r') as infile: |
||
310 | levels = json.load(infile) |
||
311 | out = "" |
||
312 | lInQueue = False |
||
313 | i = 1 |
||
314 | if len(levels) > 0: |
||
315 | if levels[len(levels) - 1] == False: |
||
316 | levels = levels[:len(levels) - 1] |
||
317 | if len(levels) <= int(self.settings[4]): |
||
318 | for level in levels: |
||
319 | if level['twitchID'] == ctx.author.id: |
||
320 | out += "{3} - Level: '{0}' - Made by: '{1}' - Submitted by: '{2}' ".format(level['levelName'],level['levelMakerName'],level['submitterName'],i) |
||
321 | lInQueue = True |
||
322 | i += 1 |
||
323 | if out != "" and lInQueue: |
||
324 | await self.send_message(out,ctx) |
||
325 | else: |
||
326 | await self.send_message('{} has no levels in the queue.'.format(ctx.author.display_name),ctx) |
||
327 | else: |
||
328 | for level in levels: |
||
329 | if i <= int(self.settings[4]): |
||
330 | if level['twitchID'] == ctx.author.id: |
||
331 | out += "{3} - Level: '{0}' - Made by: '{1}' - Submitted by: '{2}' ".format(level['levelName'],level['levelMakerName'],level['submitterName'],i) |
||
332 | lInQueue = True |
||
333 | else: |
||
334 | ileft = i - int(self.settings[4]) |
||
335 | out += f" And {ileft} more levels in queue." |
||
336 | break |
||
337 | i += 1 |
||
338 | if out != "" and lInQueue: |
||
339 | await self.send_message(out,ctx) |
||
340 | else: |
||
341 | await self.send_message('{} has no levels in the queue.'.format(ctx.author.display_name),ctx) |
||
342 | else: |
||
343 | await ctx.send('The queue is currently empty.') |
||
344 | |||
345 | @commands.command(name='lock') |
||
346 | async def lock(self, ctx): |
||
347 | if ctx.author.is_mod: |
||
348 | with open(path, 'r') as infile: |
||
349 | levels = json.load(infile) |
||
350 | if len(levels) > 0: |
||
351 | if levels[len(levels) - 1] == False: |
||
352 | await self.send_message('Queue was already locked', ctx) |
||
353 | return |
||
354 | else: |
||
355 | levels.append(False) |
||
356 | with open(path, 'w') as outfile: |
||
357 | json.dump(levels, outfile) |
||
358 | await self.send_message('Succesfully locked queue', ctx) |
||
359 | else: |
||
360 | levels.append(False) |
||
361 | with open(path, 'w') as outfile: |
||
362 | json.dump(levels, outfile) |
||
363 | await self.send_message('Succesfully locked queue', ctx) |
||
364 | |||
365 | @commands.command(name='unlock') |
||
366 | async def unlock(self, ctx): |
||
367 | if ctx.author.is_mod: |
||
368 | with open(path, 'r') as infile: |
||
369 | levels = json.load(infile) |
||
370 | if len(levels) > 0: |
||
371 | if levels[len(levels) - 1] == False: |
||
372 | levels.pop(len(levels) - 1) |
||
373 | with open(path, 'w') as outfile: |
||
374 | json.dump(levels, outfile) |
||
375 | await self.send_message('Succesfully unlocked queue', ctx) |
||
376 | else: |
||
377 | await self.send_message('Queue was already unlocked', ctx) |
||
378 | else: |
||
379 | await self.send_message('Queue was already unlocked', ctx) |
||
380 | |||
381 | @commands.command(name='next', aliases=['skip']) |
||
382 | async def next(self, ctx): |
||
383 | if ctx.author.is_mod: |
||
384 | with open(path, 'r') as infile: |
||
385 | levels = json.load(infile) |
||
386 | if len(levels) > 0: |
||
387 | if levels[0] != False: |
||
388 | levels.pop(0) |
||
389 | with open(path, 'w') as outfile: |
||
390 | json.dump(levels, outfile) |
||
391 | await self.send_message('Succesfully skipped level', ctx) |
||
392 | return |
||
393 | await self.send_message("Couldn't skip level due to the queue being empty", ctx) |
||
394 | |||
395 | @commands.command(name='clear',aliases=['reset','empty','init']) |
||
396 | async def clear(self,ctx): |
||
397 | if ctx.author.is_mod: |
||
398 | with open(path,'w') as outfile: |
||
399 | outfile.write('[]') |
||
400 | await ctx.send('Succesfully cleared queue!') |
||
401 | |||
402 | @commands.command(name='current',aliases=['currentlevel','np','nowplaying','now']) |
||
403 | async def current(self,ctx): |
||
404 | with open(path,'r') as infile: |
||
405 | levels = json.load(infile) |
||
406 | if len(levels) > 0 and levels[0] != False: |
||
407 | await self.send_message('The current level is "{0}" by "{1}" submitted by "{2}" link {3}.'.format(levels[0]['levelName'],levels[0]['levelMakerName'],levels[0]['submitterName'],levels[0]['link']),ctx) |
||
408 | else: |
||
409 | await ctx.send('The queue is currently empty.') |
||
410 | |||
411 | |||
412 | if len(argv) < 2: |
||
413 | path = os.path.dirname(os.path.abspath(__file__)) + "/dir/levels.json" |
||
414 | else: |
||
415 | path = argv[1] |
||
416 | |||
417 | if len(argv) < 3: |
||
418 | path3 = os.path.dirname(os.path.abspath(__file__)) + '/dir' |
||
419 | else: |
||
420 | path3 = argv[2] |
||
421 | |||
422 | favicon = os.path.dirname(os.path.abspath(__file__)) + '/imgs/favicon.ico' |
||
423 | |||
424 | with open(path3 + '/def.txt', 'r') as infile: |
||
425 | default = infile.read() |
||
426 | |||
427 | with open(path3 + '/settings.txt', 'r') as infile: |
||
428 | settings = infile.read() |
||
429 | mat = findall(r'"(.+?)"', settings) |
||
430 | if len(mat) < 7 or default == settings: |
||
431 | input('Error, please fill settings.txt completely in first. ') |
||
432 | exit() |
||
433 | |||
434 | class run_bot(threading.Thread): |
||
435 | def __init__(self, name): |
||
436 | threading.Thread.__init__(self) |
||
437 | self.name = name |
||
438 | self.bot = Bot() |
||
439 | |||
440 | def run(self): |
||
441 | try: |
||
442 | self.bot.run() |
||
443 | finally: |
||
444 | exit() |
||
445 | |||
446 | def stop(self): |
||
447 | self.bot.close() |
||
448 | |||
449 | class run_serv(threading.Thread): |
||
450 | def __init__(self, name): |
||
451 | threading.Thread.__init__(self) |
||
452 | self.name = name |
||
453 | |||
454 | def run(self): |
||
455 | |||
456 | class getHandler(http.server.SimpleHTTPRequestHandler): |
||
457 | |||
458 | def do_GET(self): |
||
459 | try: |
||
460 | http.server.SimpleHTTPRequestHandler.do_GET(self) |
||
461 | except ConnectionAbortedError: |
||
462 | pass |
||
463 | except FileNotFoundError: |
||
464 | pass |
||
465 | try: |
||
466 | mat = findall(r"/dashboard.html\?removeLevelId=([\w]+)", self.path) |
||
467 | if mat: |
||
468 | try: |
||
469 | removeIndex = int(mat[0]) |
||
470 | except ValueError: |
||
471 | if mat[0] == 'all': |
||
472 | with open(path,'w') as outfile: |
||
473 | outfile.write('[]') |
||
474 | elif mat[0] == 'lock': |
||
475 | with open(path, 'r') as infile: |
||
476 | levels = json.loads(infile.read()) |
||
477 | try: |
||
478 | if levels[len(levels) - 1] == False: |
||
479 | levels.pop(len(levels) - 1) |
||
480 | else: |
||
481 | levels.append(False) |
||
482 | except IndexError: |
||
483 | levels.append(False) |
||
484 | with open(path, 'w') as outfile: |
||
485 | json.dump(levels, outfile) |
||
486 | else: |
||
487 | with open(path,'r') as infile: |
||
488 | levels = json.load(infile) |
||
489 | if levels[removeIndex] != False: |
||
490 | levels.pop(removeIndex) |
||
491 | with open(path,'w') as outfile: |
||
492 | json.dump(levels,outfile) |
||
493 | else: |
||
494 | mat = findall(r"/dashboard.html\?promoteLevelId=([\w]+)", self.path) |
||
495 | if mat: |
||
496 | with open(path, 'r') as infile: |
||
497 | levels = json.load(infile) |
||
498 | i = int(mat[0]) - 1 |
||
499 | if i != 0 or i + 1 < len(levels): |
||
500 | level = levels[i] |
||
501 | levels.pop(i) |
||
502 | levels.insert(1, level) |
||
503 | with open(path, 'w') as outfile: |
||
504 | json.dump(levels, outfile) |
||
505 | |||
506 | mat = findall(r"\/dashboard\.html\?levelName=(.*?)&levelMakerName=(.*?)&submitterName=(.*?)&link=(.*?)&d=", self.path) |
||
507 | if mat: |
||
508 | link = mat[0][3] |
||
509 | levelName = mat[0][0].replace('+',' ') |
||
510 | levelMakerName = mat[0][1].replace('+', ' ') |
||
511 | submitterName = mat[0][2].replace('+', ' ') |
||
512 | |||
513 | l = {'link':link,'levelName':levelName,'twitchID':None,'levelMakerName':levelMakerName,'submitterName':submitterName} |
||
514 | with open(path,'r') as infile: |
||
515 | levels = json.load(infile) |
||
516 | levels.append(l) |
||
517 | with open(path,'w') as outfile: |
||
518 | json.dump(levels,outfile) |
||
519 | |||
520 | except Exception: |
||
521 | pass |
||
522 | |||
523 | def do_HEAD(self): |
||
524 | http.server.SimpleHTTPRequestHandler.do_HEAD(self) |
||
525 | |||
526 | def log_message(self, format, *args): |
||
527 | return |
||
528 | |||
529 | def log_error(self, format, *args): |
||
530 | return |
||
531 | |||
532 | try: |
||
533 | Handler = getHandler |
||
534 | PORT = 8000 |
||
535 | os.chdir(str(path3)) |
||
536 | with socketserver.TCPServer(("", PORT), Handler) as httpd: |
||
537 | httpd.serve_forever() |
||
538 | finally: |
||
539 | while True: |
||
540 | try: |
||
541 | httpd.shutdown() |
||
542 | except Exception: |
||
543 | pass |
||
544 | else: |
||
545 | break |
||
546 | exit() |
||
547 | |||
548 | def get_id(self): |
||
549 | # returns id of the respective thread |
||
550 | for id, thread in threading._active.items(): |
||
551 | if thread is self: |
||
552 | return id |
||
553 | |||
554 | def stop(self): |
||
555 | thread_id = self.get_id() |
||
556 | res = ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id,ctypes.py_object(SystemExit)) |
||
557 | if res > 1: |
||
558 | ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, 0) |
||
559 | |||
560 | if __name__ == '__main__': |
||
561 | |||
562 | rbot = run_bot('twitch') |
||
563 | rserv = run_serv('localhost') |
||
564 | rbot.start() |
||
565 | rserv.start() |
||
566 | time.sleep(1) |
||
567 | webbrowser.open('http://localhost:8000/dashboard.html') |
||
568 |