Skip to content
This repository was archived by the owner on Dec 2, 2024. It is now read-only.

Commit 7e4890c

Browse files
forgot to update tests
1 parent d0c5e2f commit 7e4890c

File tree

16 files changed

+363
-43
lines changed

16 files changed

+363
-43
lines changed

.vscode/settings.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
{
2-
"python.formatting.provider": "black",
2+
"python.formatting.provider": "none",
33
"python.linting.banditEnabled": true,
4-
"python.linting.enabled": true
4+
"python.linting.enabled": true,
5+
"[python]": {
6+
"editor.defaultFormatter": "ms-python.autopep8"
7+
}
58
}

MeowerBot/Bot.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import threading
22
import shlex
33

4-
from .cloudlink import CloudLink
4+
from .cl import CloudLink
55
import sys
66

77
import json
@@ -145,6 +145,15 @@ def __handle_error__(self, e):
145145
self.__handle_close__()
146146
return
147147

148+
if (type(e)) == KeyboardInterrupt:
149+
#kill all bot threads
150+
self.bad_exit = True
151+
152+
self.wss = None # effectively kill the bot
153+
self.__handle_close__( )
154+
return
155+
156+
148157

149158

150159

@@ -154,16 +163,18 @@ def _debug_fix(self, packet):
154163

155164
try:
156165
self.__handle_packet__(packet)
157-
except Exception as e: # cq: skip #IDC ABOUT GENERAL EXCP
158-
166+
except BaseException as e: # cq: skip #IDC ABOUT GENERAL EXCP
167+
self.__handle_error__(e)
159168
self.logger.error(traceback.format_exc())
160169
self.run_cb("error", args=(e, ))
161170

162171
try:
163172
self.run_cb("__raw__", args=(packet, )) # raw packets
164-
except Exception as e: # cq: skip #IDC ABOUT GENERAL EXCP
173+
except BaseException as e: # cq: skip #IDC ABOUT GENERAL EXCP
174+
self.__handle_error__(e)
165175
self.logger.error(traceback.format_exc())
166176
self.run_cb("error", args=(e, ))
177+
167178

168179
def __handle_on_connect__(self):
169180
self.wss.sendPacket(
@@ -240,7 +251,8 @@ def _handle_status(self, status, listener):
240251
)
241252
print("CRITICAL ERROR! ACCOUNT SOFTLOCKED!!!!.", file=sys.__stdout__)
242253
self.bad_exit = True
243-
self.wss.stop()
254+
del self.wss
255+
244256
return
245257

246258
if status != "I:100 | OK":
File renamed without changes.

MeowerBot/Cloudlink/cloudlink.py renamed to MeowerBot/cl/cloudlink.py

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ def client(self, ip="ws://127.0.0.1:3000/"): # Runs CloudLink in client mode.
7676

7777
# Run the client
7878
self.wss.run_forever()
79-
except Exception as e:
79+
except BaseException as e:
8080
self.logging.error(f"Error at client: {e}")
81+
self._on_error_client(self.wss, e)
8182

8283
def stop(self, abrupt=False): # Stops CloudLink (not sure if working)
8384
self.wss.close()
@@ -94,8 +95,9 @@ def callback(
9495
self.logging.error(
9596
f"Error: Callback {callback_id} is not a valid callback id!"
9697
)
97-
except Exception as e:
98+
except BaseException as e:
9899
self.logging.error(f"Error at callback: {e}")
100+
self._on_error_client(self.wss, e)
99101

100102
def sendPacket(
101103
self, msg
@@ -104,8 +106,9 @@ def sendPacket(
104106

105107
self.logging.debug(f"Sending {json.dumps(msg)}")
106108
self.wss.send(json.dumps(msg))
107-
except Exception as e:
109+
except BaseException as e:
108110
self.logging.error(f"Error on sendPacket (client): {e}")
111+
self._on_error_client(self.wss, e)
109112

110113
def getUsernames(self): # Returns the username list.
111114
return self.statedata["ulist"]["usernames"]
@@ -149,12 +152,15 @@ def _on_connection_client(self, ws): # Client-side connection handler
149152
def run(*args):
150153
try:
151154
self.callback_function["on_connect"]()
152-
except Exception as e:
155+
except BaseException as e:
153156
self.logging.error(f"Error on _on_connection_client: {e}")
157+
self._on_error_client(self.wss, error)
154158

155159
threading.Thread(target=run).start()
156-
except Exception as e:
160+
except BaseException as e:
157161
self.logging.info(f"Error on _on_connection_client: {e}")
162+
self._on_error_client(self.wss, e)
163+
158164

159165
def _on_packet_client(self, ws, message): # Client-side packet handler
160166
try:
@@ -177,13 +183,15 @@ def _on_packet_client(self, ws, message): # Client-side packet handler
177183
def run(*args):
178184
try:
179185
self.callback_function["on_packet"](message)
180-
except Exception as e:
186+
except BaseException as e:
181187

182188
self.logging.error(f"Error on _on_packet_client: {e}")
189+
self._on_error_client(self.wss, e)
183190

184191
threading.Thread(target=run).start()
185-
except Exception as e:
192+
except BaseException as e:
186193
self.logging.error(f"Error on _on_packet_client: {e}")
194+
self._on_error_client(self.wss, e)
187195

188196
def _on_error_client(self, ws, error): # Client-side error handler
189197
try:
@@ -194,13 +202,16 @@ def _on_error_client(self, ws, error): # Client-side error handler
194202
def run(*args):
195203
try:
196204
self.callback_function["on_error"](error)
197-
except Exception as e:
205+
except BaseException as e:
198206
self.logging.error(f"Error on _on_error_client: {e}")
199207

208+
self._on_error_client(self.wss, e)
209+
200210
threading.Thread(target=run).start()
201-
except Exception as e:
211+
except BaseException as e:
202212

203213
self.logging.error(f"Error on _on_error_client: {e}")
214+
self._on_error_client(self.wss, e)
204215

205216
def _closed_connection_client(
206217
self, ws, close_status_code, close_msg
@@ -215,10 +226,12 @@ def _closed_connection_client(
215226
def run(*args):
216227
try:
217228
self.callback_function["on_close"]()
218-
except Exception as e:
229+
except BaseException as e:
219230

220231
self.logging.error(f"Error on _closed_connection_client: {e}")
232+
self._on_error_client(self.wss, e)
221233

222234
threading.Thread(target=run).start()
223-
except Exception as e:
235+
except BaseException as e:
224236
self.logging.error(f"Error on _closed_connection_client: {e}")
237+
self._on_error_client(self.wss, e)

MeowerBot/command.py

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import warnings
22
import inspect
3-
3+
import traceback
44
from logging import getLogger
55

66
logger = getLogger("MeowerBot")
@@ -9,16 +9,41 @@
99
class AppCommand:
1010
connected = None
1111

12-
def __init__(self, func, name=None, args=0):
12+
def __init__(self, func, name=None, args=0, is_subcommand=False):
1313
if name is None:
1414
name = func.__name__
1515

1616
self.name = name
1717
self.func = func
18-
self.args = args
18+
self.args_num = args
19+
20+
spec = inspect.signature(func)
21+
22+
# Get the names and annotations of the arguments
23+
self.args = [
24+
(param.name, param.annotation)
25+
for param in spec.parameters.values()
26+
if param.name not in ["self", "ctx"]
27+
]
28+
29+
# Check if the function has an arbitrary number of positional arguments
30+
self.has_unamed_args = any(
31+
param.kind == inspect.Parameter.VAR_POSITIONAL for param in spec.parameters.values()
32+
)
33+
34+
self.is_subcommand = is_subcommand
35+
36+
# Get the names, annotations, and default values of the keyword-only arguments
37+
self.optional_args = [
38+
(param.name, param.annotation, param.default)
39+
for param in spec.parameters.values()
40+
if param.kind == inspect.Parameter.KEYWORD_ONLY
41+
]
42+
43+
# Set the namespace based on whether the command is a subcommand or not
44+
self.namespace = self.is_subcommand if type(self.is_subcommand) is str else self.name
45+
1946

20-
self.arg_names = inspect.getfullargspec(func)[0]
21-
self.arg_types = func.__annotations__
2247
self.subcommands = {}
2348

2449
def __call__(self, *args):
@@ -31,6 +56,7 @@ def register_class(self, con):
3156
subcommand.register_class(con)
3257

3358

59+
3460
def subcommand(self, name=None, args=0):
3561
def inner(func):
3662

@@ -55,10 +81,10 @@ def run_cmd(self, ctx, *args):
5581
logger.debug(f"Cant find subcommand {args[0]}")
5682

5783
except IndexError:
58-
logger.debug(f"IndexError: {args}")
84+
logger.debug(traceback.format_exc())
5985

60-
if not self.args == 0:
61-
args = args[: self.args]
86+
if not self.args_num == 0:
87+
args = args[:self.args_num]
6288

6389
if self.connected is None:
6490
self.func(ctx, *args)
@@ -69,8 +95,10 @@ def info(self):
6995
return {
7096
self.name: {
7197
"args": self.args,
72-
"arg_names": self.arg_names,
73-
"arg_types": self.arg_types,
98+
"args_num": self.args_num,
99+
"optional_args": self.optional_args,
100+
"has_unamed_args": self.has_unamed_args,
101+
"subcommands": self.subcommands,
74102
"command": self,
75103
"func": self.func,
76104

MeowerBot/ext/help.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
from MeowerBot.cog import Cog
2+
from MeowerBot.command import command
3+
import inspect
4+
5+
def _get_index_or(l, i, d):
6+
try:
7+
r = l[i]
8+
if str(r) == str(inspect._empty):
9+
return d
10+
return r
11+
except IndexError:
12+
return d
13+
14+
class Help(Cog):
15+
def __init__(self, bot, *args, **kwargs):
16+
self.bot = bot
17+
self.page = ""
18+
Cog.__init__(self)
19+
20+
21+
22+
def generate_help(self):
23+
self.pages = []
24+
self.page = ""
25+
page_size = 0
26+
for name, cog in self.bot.cogs.items():
27+
28+
self.page+= f"-- [ {name} ] --\n"
29+
page_size = len(self.page)
30+
31+
for command in cog.__commands__.values():
32+
self.handle_command(command["command"].name, command["command"])
33+
34+
if page_size >= 500:
35+
self.pages.append(page)
36+
self.page = f"-- [ {name} ] --\n"
37+
page_size = len(self.page)
38+
39+
self.page += "-- [ Unsorted ] --\n"
40+
page_size = len(self.page)
41+
42+
43+
44+
for name, comamnd in self.bot.commands.items():
45+
if comamnd["command"].connected is not None: continue #skip cog based commands
46+
47+
self.handle_command(name, comamnd["command"])
48+
49+
if page_size >= 500:
50+
self.pages.append(page)
51+
self.page = f"-- [ Unsorted ] --\n"
52+
page_size = len(self.page)
53+
54+
self.pages.append(self.page)
55+
56+
57+
def handle_command(self, name, cmd):
58+
self.page += (f"{self.bot.prefix}{name} ")
59+
60+
for arg in cmd.args:
61+
self.page += f"<{arg[0][0]}: {str(_get_index_or(arg, 1, 'any'))}> "
62+
63+
64+
for arg in cmd.optional_args:
65+
self.page += f"[{arg[0]}: {str(_get_index_or(arg, 1, 'any'))}: optional ] "
66+
67+
self.page += "\n"
68+
69+
for subcommand_name, command in cmd.subcommands.items():
70+
self.page += f"\t"
71+
self.handle_command(f"{name} {subcommand_name}", command["command"])
72+
self.page += "\n"
73+
74+
self.page += "\n"
75+
76+
@command(name="help")
77+
def help(self, ctx, page: int=0):
78+
79+
if page >= len(self.pages):
80+
page = len(self.pages) - 1
81+
82+
ctx.send_msg(self.pages[page])
83+
84+

0 commit comments

Comments
 (0)