hyper-bot 0.75__tar.gz → 0.772__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {hyper-bot-0.75 → hyper-bot-0.772}/Hyper/Adapters/OneBot.py +31 -43
- {hyper-bot-0.75 → hyper-bot-0.772}/Hyper/Adapters/OneBotLib/Manager.py +43 -9
- hyper-bot-0.772/Hyper/Adapters/OneBotLib/Res.py +90 -0
- hyper-bot-0.772/Hyper/Adapters/Satori.py +94 -0
- {hyper-bot-0.75 → hyper-bot-0.772}/Hyper/Configurator.py +5 -3
- {hyper-bot-0.75 → hyper-bot-0.772}/Hyper/Errors.py +6 -0
- {hyper-bot-0.75 → hyper-bot-0.772}/Hyper/Events.py +5 -1
- {hyper-bot-0.75 → hyper-bot-0.772}/Hyper/Listener.py +2 -0
- {hyper-bot-0.75 → hyper-bot-0.772}/Hyper/Manager.py +2 -0
- hyper-bot-0.772/Hyper/Network.py +156 -0
- {hyper-bot-0.75 → hyper-bot-0.772}/Hyper/Segments.py +32 -92
- {hyper-bot-0.75/Hyper → hyper-bot-0.772/Hyper/Utils}/Logic.py +17 -21
- hyper-bot-0.772/Hyper/Utils/TypeExt.py +177 -0
- {hyper-bot-0.75 → hyper-bot-0.772}/PKG-INFO +1 -1
- {hyper-bot-0.75 → hyper-bot-0.772}/hyper_bot.egg-info/PKG-INFO +1 -1
- {hyper-bot-0.75 → hyper-bot-0.772}/hyper_bot.egg-info/SOURCES.txt +4 -2
- {hyper-bot-0.75 → hyper-bot-0.772}/setup.py +2 -2
- hyper-bot-0.75/Hyper/ModuleClass.py +0 -67
- hyper-bot-0.75/Hyper/Network.py +0 -77
- {hyper-bot-0.75 → hyper-bot-0.772}/Hyper/DataBase.py +0 -0
- {hyper-bot-0.75 → hyper-bot-0.772}/Hyper/Logger.py +0 -0
- {hyper-bot-0.75 → hyper-bot-0.772}/LICENSE +0 -0
- {hyper-bot-0.75 → hyper-bot-0.772}/hyper_bot.egg-info/dependency_links.txt +0 -0
- {hyper-bot-0.75 → hyper-bot-0.772}/hyper_bot.egg-info/top_level.txt +0 -0
- {hyper-bot-0.75 → hyper-bot-0.772}/setup.cfg +0 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import json
|
|
2
|
-
import queue
|
|
3
2
|
import threading
|
|
4
3
|
import time
|
|
5
4
|
import asyncio
|
|
6
5
|
import os
|
|
7
6
|
from typing import Union
|
|
8
7
|
|
|
9
|
-
from Hyper import
|
|
8
|
+
from Hyper import Errors, Network, Events
|
|
9
|
+
from Hyper.Utils import Logic
|
|
10
|
+
from Hyper.Manager import reports
|
|
10
11
|
from Hyper.Events import *
|
|
11
12
|
|
|
12
|
-
reports = queue.Queue()
|
|
13
13
|
config = Configurator.cm.get_cfg()
|
|
14
14
|
logger = Logger.Logger()
|
|
15
15
|
logger.set_level(config.log_level)
|
|
@@ -24,20 +24,13 @@ class Actions:
|
|
|
24
24
|
self.connection = cnt_i
|
|
25
25
|
|
|
26
26
|
def __getattr__(self, item) -> callable:
|
|
27
|
-
def wrapper(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
else:
|
|
35
|
-
packet = Manager.Packet(
|
|
36
|
-
str(item),
|
|
37
|
-
**kwargs
|
|
38
|
-
)
|
|
39
|
-
packet.send_to(self.connection)
|
|
40
|
-
return get_ret(packet.echo)
|
|
27
|
+
def wrapper(**kwargs) -> str:
|
|
28
|
+
packet = Manager.Packet(
|
|
29
|
+
str(item),
|
|
30
|
+
**kwargs
|
|
31
|
+
)
|
|
32
|
+
packet.send_to(self.connection)
|
|
33
|
+
return packet.echo
|
|
41
34
|
|
|
42
35
|
return wrapper
|
|
43
36
|
|
|
@@ -59,8 +52,17 @@ class Actions:
|
|
|
59
52
|
)
|
|
60
53
|
else:
|
|
61
54
|
raise Errors.ArgsInvalidError("'send' API requires 'group_id' or 'user_id' but none of them are provided.")
|
|
62
|
-
|
|
63
|
-
|
|
55
|
+
retried = 0
|
|
56
|
+
while 1:
|
|
57
|
+
packet.send_to(self.connection)
|
|
58
|
+
result = Manager.Ret.fetch(packet.echo)
|
|
59
|
+
if result.ret_code != 0 or (4 <= len(str(result.data.message_id)) <= 6):
|
|
60
|
+
retried += 1
|
|
61
|
+
if retried >= 5:
|
|
62
|
+
return result
|
|
63
|
+
await asyncio.sleep(1)
|
|
64
|
+
else:
|
|
65
|
+
return result
|
|
64
66
|
|
|
65
67
|
@Logger.AutoLogAsync.register(Logger.AutoLog.templates().recall, logger)
|
|
66
68
|
async def del_message(self, message_id: int) -> None:
|
|
@@ -90,13 +92,13 @@ class Actions:
|
|
|
90
92
|
async def get_login_info(self) -> Manager.Ret:
|
|
91
93
|
packet = Manager.Packet("get_login_info")
|
|
92
94
|
packet.send_to(self.connection)
|
|
93
|
-
return
|
|
95
|
+
return Manager.Ret.fetch(packet.echo)
|
|
94
96
|
|
|
95
97
|
@Logic.Cacher().cache_async
|
|
96
98
|
async def get_version_info(self) -> Manager.Ret:
|
|
97
99
|
packet = Manager.Packet("get_version_info")
|
|
98
100
|
packet.send_to(self.connection)
|
|
99
|
-
return
|
|
101
|
+
return Manager.Ret.fetch(packet.echo)
|
|
100
102
|
|
|
101
103
|
async def send_forward_msg(self, message: Manager.Message) -> Manager.Ret:
|
|
102
104
|
packet = Manager.Packet(
|
|
@@ -104,7 +106,7 @@ class Actions:
|
|
|
104
106
|
messages=await message.get()
|
|
105
107
|
)
|
|
106
108
|
packet.send_to(self.connection)
|
|
107
|
-
return
|
|
109
|
+
return Manager.Ret.fetch(packet.echo)
|
|
108
110
|
|
|
109
111
|
async def send_group_forward_msg(self, group_id: int, message: Manager.Message) -> Manager.Ret:
|
|
110
112
|
packet = Manager.Packet(
|
|
@@ -113,7 +115,7 @@ class Actions:
|
|
|
113
115
|
messages=await message.get()
|
|
114
116
|
)
|
|
115
117
|
packet.send_to(self.connection)
|
|
116
|
-
return
|
|
118
|
+
return Manager.Ret.fetch(packet.echo)
|
|
117
119
|
|
|
118
120
|
@Logger.AutoLogAsync.register(Logger.AutoLog.templates().set_req, logger)
|
|
119
121
|
async def set_group_add_request(self, flag: str, sub_type: str, approve: bool, reason: str = "Refused") -> None:
|
|
@@ -133,7 +135,7 @@ class Actions:
|
|
|
133
135
|
no_cache=True,
|
|
134
136
|
)
|
|
135
137
|
packet.send_to(self.connection)
|
|
136
|
-
return
|
|
138
|
+
return Manager.Ret.fetch(packet.echo)
|
|
137
139
|
|
|
138
140
|
@Logic.Cacher().cache_async
|
|
139
141
|
async def get_group_member_info(self, group_id: int, user_id: int) -> Manager.Ret:
|
|
@@ -144,7 +146,7 @@ class Actions:
|
|
|
144
146
|
no_cache=True
|
|
145
147
|
)
|
|
146
148
|
packet.send_to(self.connection)
|
|
147
|
-
return
|
|
149
|
+
return Manager.Ret.fetch(packet.echo)
|
|
148
150
|
|
|
149
151
|
@Logic.Cacher().cache_async
|
|
150
152
|
async def get_group_info(self, group_id: int) -> Manager.Ret:
|
|
@@ -154,12 +156,12 @@ class Actions:
|
|
|
154
156
|
no_cache=True
|
|
155
157
|
)
|
|
156
158
|
packet.send_to(self.connection)
|
|
157
|
-
return
|
|
159
|
+
return Manager.Ret.fetch(packet.echo)
|
|
158
160
|
|
|
159
161
|
async def get_status(self) -> Manager.Ret:
|
|
160
162
|
packet = Manager.Packet("get_status")
|
|
161
163
|
packet.send_to(self.connection)
|
|
162
|
-
return
|
|
164
|
+
return Manager.Ret.fetch(packet.echo)
|
|
163
165
|
|
|
164
166
|
@Logger.AutoLogAsync.register(Logger.AutoLog.templates().set_ess, logger)
|
|
165
167
|
async def set_essence_msg(self, message_id: int) -> None:
|
|
@@ -182,7 +184,7 @@ class Actions:
|
|
|
182
184
|
message_id=msg_id
|
|
183
185
|
)
|
|
184
186
|
packet.send_to(self.connection)
|
|
185
|
-
return
|
|
187
|
+
return Manager.Ret.fetch(packet.echo)
|
|
186
188
|
|
|
187
189
|
|
|
188
190
|
async def tester(message_data: Event, actions: Actions) -> None:
|
|
@@ -191,7 +193,7 @@ async def tester(message_data: Event, actions: Actions) -> None:
|
|
|
191
193
|
|
|
192
194
|
async def __handler(data: dict, actions: Actions) -> None:
|
|
193
195
|
if data.get("echo") is not None:
|
|
194
|
-
reports.put(
|
|
196
|
+
reports.put(data)
|
|
195
197
|
elif data.get("post_type") == "meta_event" or data.get("user_id") == data.get("self_id"):
|
|
196
198
|
pass
|
|
197
199
|
else:
|
|
@@ -208,7 +210,6 @@ async def __handler(data: dict, actions: Actions) -> None:
|
|
|
208
210
|
|
|
209
211
|
|
|
210
212
|
handler: callable = tester
|
|
211
|
-
connection: callable = tester
|
|
212
213
|
|
|
213
214
|
|
|
214
215
|
def reg(func: callable):
|
|
@@ -216,20 +217,7 @@ def reg(func: callable):
|
|
|
216
217
|
handler = func
|
|
217
218
|
|
|
218
219
|
|
|
219
|
-
def get_ret(echo: str) -> Manager.Ret:
|
|
220
|
-
old = None
|
|
221
|
-
while True:
|
|
222
|
-
content: Manager.Ret = reports.get()
|
|
223
|
-
if old is not None:
|
|
224
|
-
reports.put(old)
|
|
225
|
-
if content.echo == echo:
|
|
226
|
-
return content
|
|
227
|
-
else:
|
|
228
|
-
old = content
|
|
229
|
-
|
|
230
|
-
|
|
231
220
|
def run():
|
|
232
|
-
global connection
|
|
233
221
|
try:
|
|
234
222
|
if handler is tester:
|
|
235
223
|
raise Errors.ListenerNotRegisteredError("No handler registered")
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
from Hyper
|
|
3
|
-
from Hyper.
|
|
1
|
+
import Hyper.Utils.TypeExt
|
|
2
|
+
from Hyper import Configurator, Logger, Network, Segments
|
|
3
|
+
from Hyper.Utils import Logic
|
|
4
4
|
|
|
5
5
|
from typing import Union
|
|
6
|
-
import
|
|
6
|
+
import queue
|
|
7
7
|
import random
|
|
8
|
+
import json
|
|
8
9
|
|
|
10
|
+
reports = queue.Queue()
|
|
9
11
|
config = Configurator.cm.get_cfg()
|
|
10
12
|
logger = Logger.Logger()
|
|
11
13
|
logger.set_level(config.log_level)
|
|
@@ -33,7 +35,30 @@ class Packet:
|
|
|
33
35
|
connection.send(self.endpoint, payload, self.echo)
|
|
34
36
|
|
|
35
37
|
|
|
38
|
+
class MessageBuilder:
|
|
39
|
+
def __init__(self):
|
|
40
|
+
self.sgs = []
|
|
41
|
+
|
|
42
|
+
def __getattr__(self, item):
|
|
43
|
+
if item == "build":
|
|
44
|
+
def build() -> Message:
|
|
45
|
+
return Message(*self.sgs)
|
|
46
|
+
|
|
47
|
+
return build
|
|
48
|
+
|
|
49
|
+
elif item in Segments.message_types.keys():
|
|
50
|
+
def wrapper(*args, **kwargs):
|
|
51
|
+
self.sgs.append(Segments.message_types[item]["type"](*args, **kwargs))
|
|
52
|
+
return self
|
|
53
|
+
|
|
54
|
+
return wrapper
|
|
55
|
+
else:
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
|
|
36
59
|
class Message:
|
|
60
|
+
builder = MessageBuilder()
|
|
61
|
+
|
|
37
62
|
def __init__(self, *args):
|
|
38
63
|
if len(args) == 1 and isinstance(args[0], list):
|
|
39
64
|
contents = args[0]
|
|
@@ -47,10 +72,7 @@ class Message:
|
|
|
47
72
|
self.contents.append(content)
|
|
48
73
|
|
|
49
74
|
async def get(self) -> list:
|
|
50
|
-
|
|
51
|
-
for i in self.contents:
|
|
52
|
-
ret.append(i.to_json())
|
|
53
|
-
return ret
|
|
75
|
+
return self.get_sync()
|
|
54
76
|
|
|
55
77
|
def get_sync(self) -> list:
|
|
56
78
|
ret = []
|
|
@@ -93,5 +115,17 @@ class Ret:
|
|
|
93
115
|
def __init__(self, json_data: dict):
|
|
94
116
|
self.status = json_data["status"]
|
|
95
117
|
self.ret_code = json_data["retcode"]
|
|
96
|
-
self.data = json_data.get("data")
|
|
118
|
+
self.data = Hyper.Utils.TypeExt.ObjectedDict(json_data.get("data"))
|
|
97
119
|
self.echo = json_data.get("echo")
|
|
120
|
+
|
|
121
|
+
@classmethod
|
|
122
|
+
def fetch(cls, echo: str) -> "Ret":
|
|
123
|
+
old = None
|
|
124
|
+
while True:
|
|
125
|
+
content = reports.get()
|
|
126
|
+
if old is not None:
|
|
127
|
+
reports.put(old)
|
|
128
|
+
if content["echo"] == echo:
|
|
129
|
+
return cls(content)
|
|
130
|
+
else:
|
|
131
|
+
old = content
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
message_types = {}
|
|
2
|
+
|
|
3
|
+
def segment_builder(sg_type: str, summary_tmp: str = None):
|
|
4
|
+
# print(inspect.get_annotations(cls))
|
|
5
|
+
def inner_builder(cls):
|
|
6
|
+
var = dict(vars(cls))
|
|
7
|
+
anns: dict = var.get("__annotations__", False) or dict()
|
|
8
|
+
|
|
9
|
+
def init(self, *args, **kwargs):
|
|
10
|
+
arg = {}
|
|
11
|
+
if len(args) > 0:
|
|
12
|
+
for i in args:
|
|
13
|
+
arg[list(anns.keys())[list(args).index(i)]] = i
|
|
14
|
+
|
|
15
|
+
if len(kwargs) > 0:
|
|
16
|
+
for i in kwargs:
|
|
17
|
+
try:
|
|
18
|
+
arg[i] = anns[i](kwargs[i])
|
|
19
|
+
except TypeError:
|
|
20
|
+
arg[i] = kwargs[i]
|
|
21
|
+
new_arg = arg.copy()
|
|
22
|
+
|
|
23
|
+
if len(anns) > len(arg):
|
|
24
|
+
for i in anns.keys():
|
|
25
|
+
if i not in arg.keys():
|
|
26
|
+
if i not in var.keys():
|
|
27
|
+
new_arg[i] = None
|
|
28
|
+
continue
|
|
29
|
+
if not isinstance(var[i], anns[i]):
|
|
30
|
+
new_arg[i] = anns[i](var[i])
|
|
31
|
+
else:
|
|
32
|
+
new_arg[i] = var[i]
|
|
33
|
+
|
|
34
|
+
for i in new_arg:
|
|
35
|
+
setattr(self, i, new_arg[i])
|
|
36
|
+
|
|
37
|
+
cls.__init__ = init
|
|
38
|
+
|
|
39
|
+
def to_json(self) -> dict:
|
|
40
|
+
base = {"type": sg_type, "data": {}}
|
|
41
|
+
for i in anns:
|
|
42
|
+
if getattr(self, i) is None:
|
|
43
|
+
continue
|
|
44
|
+
if not isinstance(getattr(self, i), anns[i]):
|
|
45
|
+
base["data"][i] = anns[i](getattr(self, i))
|
|
46
|
+
else:
|
|
47
|
+
base["data"][i] = getattr(self, i)
|
|
48
|
+
# try:
|
|
49
|
+
# base["data"][i] = anns[i](getattr(self, i))
|
|
50
|
+
# except TypeError:
|
|
51
|
+
# base["data"][i] = getattr(self, i)
|
|
52
|
+
return base
|
|
53
|
+
|
|
54
|
+
cls.to_json = to_json
|
|
55
|
+
|
|
56
|
+
def to_str(self) -> str:
|
|
57
|
+
text = summary_tmp
|
|
58
|
+
if text is None:
|
|
59
|
+
text = "[]"
|
|
60
|
+
if "<" not in text and ">" not in text:
|
|
61
|
+
return text
|
|
62
|
+
|
|
63
|
+
for i in anns:
|
|
64
|
+
if f"<{i}>" in summary_tmp:
|
|
65
|
+
try:
|
|
66
|
+
v = self.__getattribute__(i)
|
|
67
|
+
except AttributeError:
|
|
68
|
+
v = None
|
|
69
|
+
text = text.replace(f"<{i}>", str(v))
|
|
70
|
+
|
|
71
|
+
return text
|
|
72
|
+
|
|
73
|
+
cls.__str__ = to_str if cls().__str__() == "__not_set__" else cls.__str__
|
|
74
|
+
|
|
75
|
+
message_types[sg_type] = {
|
|
76
|
+
"type": cls,
|
|
77
|
+
"args": list(anns.keys())
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return cls
|
|
81
|
+
|
|
82
|
+
return inner_builder
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class Base:
|
|
86
|
+
def __init__(self, *args, **kwargs): ...
|
|
87
|
+
|
|
88
|
+
def to_json(self) -> dict: ...
|
|
89
|
+
|
|
90
|
+
def __str__(self) -> str: return "__not_set__"
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
from Hyper.Adapters.OneBot import *
|
|
2
|
+
from Hyper.Errors import *
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Actions(Actions):
|
|
6
|
+
def __init__(self, cnt: Union[Network.WebsocketConnection, Network.HTTPConnection, Network.SatoriConnection]):
|
|
7
|
+
self.connection = cnt
|
|
8
|
+
|
|
9
|
+
class CustomAction:
|
|
10
|
+
def __init__(self,
|
|
11
|
+
cnt_i: Union[Network.WebsocketConnection, Network.HTTPConnection, Network.SatoriConnection]):
|
|
12
|
+
self.connection = cnt_i
|
|
13
|
+
|
|
14
|
+
def __getattr__(self, item) -> callable:
|
|
15
|
+
def wrapper(**kwargs) -> str:
|
|
16
|
+
packet = Manager.Packet(
|
|
17
|
+
str(item),
|
|
18
|
+
**kwargs
|
|
19
|
+
)
|
|
20
|
+
packet.send_to(self.connection)
|
|
21
|
+
return packet.echo
|
|
22
|
+
|
|
23
|
+
return wrapper
|
|
24
|
+
|
|
25
|
+
self.custom = CustomAction(self.connection)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
async def __handler(data: dict, actions: Actions) -> None:
|
|
29
|
+
if data["op"] == 2:
|
|
30
|
+
pass
|
|
31
|
+
else:
|
|
32
|
+
# task = asyncio.create_task(handler(Events.em.new(data), actions))
|
|
33
|
+
# timed = 0
|
|
34
|
+
#
|
|
35
|
+
# while not task.done():
|
|
36
|
+
# await asyncio.sleep(0.1)
|
|
37
|
+
# timed += 0.1
|
|
38
|
+
# if timed >= 30:
|
|
39
|
+
# task.cancel()
|
|
40
|
+
# logger.log(f"处理{task.get_name()}超时", level=Logger.levels.ERROR)
|
|
41
|
+
# break
|
|
42
|
+
print(data)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def reg(func: callable):
|
|
46
|
+
global handler
|
|
47
|
+
handler = func
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def run():
|
|
51
|
+
try:
|
|
52
|
+
if handler is tester:
|
|
53
|
+
raise Errors.ListenerNotRegisteredError("No handler registered")
|
|
54
|
+
# connection = websocket.WebSocket()
|
|
55
|
+
if isinstance(config.connection, Configurator.WSConnectionC):
|
|
56
|
+
connection = Network.SatoriConnection(
|
|
57
|
+
config.connection.host, config.connection.port, config.connection.token
|
|
58
|
+
)
|
|
59
|
+
else:
|
|
60
|
+
raise ConfigError
|
|
61
|
+
retried = 0
|
|
62
|
+
while True:
|
|
63
|
+
try:
|
|
64
|
+
connection.connect()
|
|
65
|
+
except ConnectionRefusedError or TimeoutError:
|
|
66
|
+
if retried >= config.connection.retries:
|
|
67
|
+
logger.log(f"重试次数达到最大值({config.connection.retries}),退出", level=Logger.levels.CRITICAL)
|
|
68
|
+
break
|
|
69
|
+
|
|
70
|
+
logger.log(f"连接建立失败,3秒后重试({retried}/{config.connection.retries})",
|
|
71
|
+
level=Logger.levels.WARNING)
|
|
72
|
+
retried += 1
|
|
73
|
+
time.sleep(3)
|
|
74
|
+
continue
|
|
75
|
+
logger.log("成功建立连接", level=Logger.levels.INFO)
|
|
76
|
+
retried = 0
|
|
77
|
+
actions = Actions(connection)
|
|
78
|
+
while True:
|
|
79
|
+
try:
|
|
80
|
+
data = connection.recv()
|
|
81
|
+
except ConnectionResetError:
|
|
82
|
+
logger.log("连接断开", level=Logger.levels.ERROR)
|
|
83
|
+
break
|
|
84
|
+
except json.decoder.JSONDecodeError:
|
|
85
|
+
logger.log("收到错误的JSON内容", level=Logger.levels.ERROR)
|
|
86
|
+
threading.Thread(target=lambda: asyncio.run(__handler(data, actions))).start()
|
|
87
|
+
except KeyboardInterrupt:
|
|
88
|
+
logger.log("正在退出(Ctrl+C)", level=Logger.levels.WARNING)
|
|
89
|
+
try:
|
|
90
|
+
connection.close()
|
|
91
|
+
except:
|
|
92
|
+
pass
|
|
93
|
+
os._exit(0)
|
|
94
|
+
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import typing
|
|
2
2
|
|
|
3
|
-
from Hyper import Logic
|
|
3
|
+
from Hyper.Utils import Logic
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class WSConnectionC:
|
|
7
|
-
def __init__(self, host: str, port: int, retries: int = 0):
|
|
7
|
+
def __init__(self, host: str, port: int, retries: int = 0, satori_token: str = None):
|
|
8
8
|
self.host: str = host
|
|
9
9
|
self.port: int = port
|
|
10
10
|
self.retries: int = retries
|
|
11
|
+
self.token: str = satori_token
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
class HTTPConnectionC:
|
|
@@ -55,7 +56,8 @@ class Config:
|
|
|
55
56
|
self.connection = WSConnectionC(
|
|
56
57
|
config_json["Connection"]["host"],
|
|
57
58
|
config_json["Connection"]["port"],
|
|
58
|
-
config_json["Connection"]["retries"]
|
|
59
|
+
config_json["Connection"]["retries"],
|
|
60
|
+
config_json["Connection"]["satori_token"]
|
|
59
61
|
)
|
|
60
62
|
elif config_json["Connection"]["mode"] == "HTTP":
|
|
61
63
|
self.connection = HTTPConnectionC(
|
|
@@ -16,3 +16,9 @@ class ListenerNotRegisteredError(Exception):
|
|
|
16
16
|
class ArgsInvalidError(Exception):
|
|
17
17
|
def __init__(self, message: str = None):
|
|
18
18
|
super().__init__(message)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ConfigError(Exception):
|
|
22
|
+
def __init__(self, message: str = None):
|
|
23
|
+
super().__init__(message)
|
|
24
|
+
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from Hyper import Configurator, Logger, Manager
|
|
2
|
+
from Hyper.Utils.TypeExt import Integer
|
|
2
3
|
from Hyper.Segments import message_types
|
|
3
4
|
from Hyper.Logger import levels
|
|
4
5
|
|
|
@@ -14,10 +15,12 @@ class EventManager:
|
|
|
14
15
|
"notice": {},
|
|
15
16
|
"request": {}
|
|
16
17
|
}
|
|
18
|
+
self.events = []
|
|
17
19
|
|
|
18
20
|
def reg(self, type_of: str, str_eql: str) -> callable:
|
|
19
21
|
def wrapper(cls):
|
|
20
22
|
self.event_lis[type_of][str_eql] = cls
|
|
23
|
+
self.events.append(cls)
|
|
21
24
|
return cls
|
|
22
25
|
|
|
23
26
|
return wrapper
|
|
@@ -88,7 +91,7 @@ class Event:
|
|
|
88
91
|
self.user_id = data.get("user_id")
|
|
89
92
|
self.group_id = data.get("group_id")
|
|
90
93
|
|
|
91
|
-
self.is_owner =
|
|
94
|
+
self.is_owner = Integer.convert_from(self.user_id) in config.owner
|
|
92
95
|
self.servicing = False
|
|
93
96
|
self.blocked = True if self.user_id in config.black_list or self.group_id in config.black_list else False
|
|
94
97
|
self.is_silent = self.user_id in config.silents or self.group_id in config.silents or 0 in config.silents
|
|
@@ -103,6 +106,7 @@ class MessageEvent(Event):
|
|
|
103
106
|
self.sub_type = data.get("sub_type")
|
|
104
107
|
self.message_id = str(data.get("message_id"))
|
|
105
108
|
self.message = gen_message(data=data)
|
|
109
|
+
self.msg_str = str(self.message)
|
|
106
110
|
|
|
107
111
|
|
|
108
112
|
@em.reg("message", "private")
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import time
|
|
3
|
+
import websocket
|
|
4
|
+
import httpx
|
|
5
|
+
import queue
|
|
6
|
+
import flask
|
|
7
|
+
import traceback
|
|
8
|
+
import json
|
|
9
|
+
import logging
|
|
10
|
+
import threading
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class WebsocketConnection:
|
|
14
|
+
def __init__(self, url: str):
|
|
15
|
+
self.ws = websocket.WebSocket()
|
|
16
|
+
self.url = url
|
|
17
|
+
|
|
18
|
+
def connect(self) -> None:
|
|
19
|
+
self.ws.connect(self.url)
|
|
20
|
+
|
|
21
|
+
def send(self, message: str) -> None:
|
|
22
|
+
self.ws.send(message)
|
|
23
|
+
|
|
24
|
+
def close(self) -> None:
|
|
25
|
+
self.ws.close()
|
|
26
|
+
|
|
27
|
+
def recv(self) -> dict:
|
|
28
|
+
return json.loads(self.ws.recv())
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class HTTPConnection:
|
|
32
|
+
def __init__(self, url: str, listener_url: str):
|
|
33
|
+
self.url = url
|
|
34
|
+
listener_url = listener_url.replace("http://", "")
|
|
35
|
+
listener_url = listener_url.replace("https://", "")
|
|
36
|
+
self.listener_url = listener_url.split(":")[0]
|
|
37
|
+
try:
|
|
38
|
+
self.port = int(listener_url.split(":")[1])
|
|
39
|
+
except IndexError:
|
|
40
|
+
self.port = 8080
|
|
41
|
+
self.app = flask.Flask(__name__)
|
|
42
|
+
self.app.config["LOGGER_HANDLER_POLICY"] = "never"
|
|
43
|
+
logging.getLogger("werkzeug").setLevel(logging.ERROR)
|
|
44
|
+
self.reports = queue.Queue()
|
|
45
|
+
|
|
46
|
+
self.listener_started = False
|
|
47
|
+
|
|
48
|
+
def __start_listener(self) -> None:
|
|
49
|
+
@self.app.route("/", methods=["POST"])
|
|
50
|
+
def listener():
|
|
51
|
+
self.reports.put(flask.request.json)
|
|
52
|
+
return {}
|
|
53
|
+
|
|
54
|
+
# self.app.run(host=self.listener_url, port=self.port)
|
|
55
|
+
|
|
56
|
+
threading.Thread(target=lambda: self.app.run(host=self.listener_url, port=self.port)).start()
|
|
57
|
+
self.listener_started = True
|
|
58
|
+
|
|
59
|
+
def connect(self) -> None:
|
|
60
|
+
if not self.listener_started:
|
|
61
|
+
self.__start_listener()
|
|
62
|
+
httpx.post(self.url)
|
|
63
|
+
traceback.print_exc()
|
|
64
|
+
|
|
65
|
+
def recv(self) -> dict:
|
|
66
|
+
return self.reports.get()
|
|
67
|
+
|
|
68
|
+
def send(self, endpoint: str, data: dict, echo: str) -> None:
|
|
69
|
+
response = httpx.post(f"{self.url}/{endpoint}", json=data)
|
|
70
|
+
res = response.json()
|
|
71
|
+
res["echo"] = echo
|
|
72
|
+
self.reports.put(res)
|
|
73
|
+
|
|
74
|
+
@staticmethod
|
|
75
|
+
def close() -> None:
|
|
76
|
+
shutdown_func = flask.request.environ.get('werkzeug.server.shutdown')
|
|
77
|
+
if shutdown_func is None:
|
|
78
|
+
raise RuntimeError('Not running with the Werkzeug Server')
|
|
79
|
+
shutdown_func()
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class SatoriConnection:
|
|
83
|
+
def __init__(self, host: str, port: int, token: str = None):
|
|
84
|
+
self.ws = websocket.WebSocket()
|
|
85
|
+
self.host = host
|
|
86
|
+
self.port = port
|
|
87
|
+
self.token = token
|
|
88
|
+
self.reports = queue.Queue()
|
|
89
|
+
|
|
90
|
+
def heart_beat(self) -> None:
|
|
91
|
+
while 1:
|
|
92
|
+
time.sleep(10)
|
|
93
|
+
self.ws.send(json.dumps({"op": 1, "body": {}}))
|
|
94
|
+
|
|
95
|
+
def connect(self) -> None:
|
|
96
|
+
self.ws.connect(f"ws://{self.host}:{self.port}/v1/events")
|
|
97
|
+
payload = {
|
|
98
|
+
"op": 3,
|
|
99
|
+
"body": {
|
|
100
|
+
"token": self.token
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
self.ws.send(json.dumps(payload))
|
|
104
|
+
res = json.loads(self.ws.recv())
|
|
105
|
+
if res["op"] == 4:
|
|
106
|
+
threading.Thread(target=self.heart_beat).start()
|
|
107
|
+
else:
|
|
108
|
+
raise ConnectionError("连接失败")
|
|
109
|
+
|
|
110
|
+
def send(self, payload: dict, echo: str = None) -> None:
|
|
111
|
+
response = httpx.post(f"http://{self.host}:{self.port}", json=payload)
|
|
112
|
+
try:
|
|
113
|
+
data = response.json()
|
|
114
|
+
data["echo"] = echo
|
|
115
|
+
self.reports.put(data)
|
|
116
|
+
except:
|
|
117
|
+
pass
|
|
118
|
+
|
|
119
|
+
def close(self) -> None:
|
|
120
|
+
pass
|
|
121
|
+
|
|
122
|
+
def recv(self) -> dict:
|
|
123
|
+
return json.loads(self.ws.recv())
|
|
124
|
+
|
|
125
|
+
#
|
|
126
|
+
# class KritorConnection:
|
|
127
|
+
# def __init__(self, host: str, port: int, account: str, ticket: str):
|
|
128
|
+
# self.channel = grpc.insecure_channel(f"{host}:{port}")
|
|
129
|
+
# self.account = account
|
|
130
|
+
# self.ticket = ticket
|
|
131
|
+
#
|
|
132
|
+
# def connect(self) -> None:
|
|
133
|
+
# auth_stub = AuthenticationServiceStub(self.channel)
|
|
134
|
+
# response = auth_stub.Authenticate(
|
|
135
|
+
# AuthenticateRequest(
|
|
136
|
+
# account=self.account,
|
|
137
|
+
# ticket=self.ticket
|
|
138
|
+
# )
|
|
139
|
+
# )
|
|
140
|
+
# if response.AuthenticateResponseCode != 0:
|
|
141
|
+
# raise ConnectionError("鉴权失败")
|
|
142
|
+
#
|
|
143
|
+
# def send(self, stub, payload: dict, echo: str = None) -> None:
|
|
144
|
+
# response = httpx.post(f"http://{self.host}:{self.port}", json=payload)
|
|
145
|
+
# try:
|
|
146
|
+
# data = response.json()
|
|
147
|
+
# data["echo"] = echo
|
|
148
|
+
# self.reports.put(data)
|
|
149
|
+
# except:
|
|
150
|
+
# pass
|
|
151
|
+
#
|
|
152
|
+
# def close(self) -> None:
|
|
153
|
+
# pass
|
|
154
|
+
#
|
|
155
|
+
# def recv(self) -> dict:
|
|
156
|
+
# return json.loads(self.ws.recv())
|
|
@@ -1,98 +1,36 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import os.path
|
|
2
3
|
import typing
|
|
3
4
|
import uuid
|
|
4
5
|
|
|
5
6
|
from Hyper.Errors import *
|
|
7
|
+
from Hyper.Configurator import cm
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
#
|
|
12
|
-
|
|
13
|
-
var = dict(vars(cls))
|
|
14
|
-
anns: dict = var.get("__annotations__", False) or dict()
|
|
15
|
-
arg = {}
|
|
16
|
-
|
|
17
|
-
def init(self, *args, **kwargs):
|
|
18
|
-
if len(args) > 0:
|
|
19
|
-
for i in args:
|
|
20
|
-
arg[list(anns.keys())[list(args).index(i)]] = i
|
|
21
|
-
|
|
22
|
-
if len(kwargs) > 0:
|
|
23
|
-
for i in kwargs:
|
|
24
|
-
try:
|
|
25
|
-
arg[i] = anns[i](kwargs[i])
|
|
26
|
-
except TypeError:
|
|
27
|
-
arg[i] = kwargs[i]
|
|
28
|
-
new_arg = arg.copy()
|
|
29
|
-
|
|
30
|
-
if len(anns) > len(arg):
|
|
31
|
-
for i in anns.keys():
|
|
32
|
-
if i not in arg.keys():
|
|
33
|
-
if i not in var.keys():
|
|
34
|
-
new_arg[i] = None
|
|
35
|
-
continue
|
|
36
|
-
if not isinstance(var[i], anns[i]):
|
|
37
|
-
new_arg[i] = anns[i](var[i])
|
|
38
|
-
else:
|
|
39
|
-
new_arg[i] = var[i]
|
|
40
|
-
|
|
41
|
-
for i in new_arg:
|
|
42
|
-
setattr(self, i, new_arg[i])
|
|
43
|
-
|
|
44
|
-
cls.__init__ = init
|
|
45
|
-
|
|
46
|
-
def to_json(self) -> dict:
|
|
47
|
-
base = {"type": sg_type, "data": {}}
|
|
48
|
-
for i in anns:
|
|
49
|
-
if not isinstance(getattr(self, i), anns[i]):
|
|
50
|
-
base["data"][i] = anns[i](getattr(self, i))
|
|
51
|
-
else:
|
|
52
|
-
base["data"][i] = getattr(self, i)
|
|
53
|
-
# try:
|
|
54
|
-
# base["data"][i] = anns[i](getattr(self, i))
|
|
55
|
-
# except TypeError:
|
|
56
|
-
# base["data"][i] = getattr(self, i)
|
|
57
|
-
return base
|
|
58
|
-
|
|
59
|
-
cls.to_json = to_json
|
|
60
|
-
|
|
61
|
-
def to_str(self) -> str:
|
|
62
|
-
text = summary_tmp
|
|
63
|
-
if text is None:
|
|
64
|
-
text = "[]"
|
|
65
|
-
if "<" not in text and ">" not in text:
|
|
66
|
-
return text
|
|
67
|
-
|
|
68
|
-
for i in anns:
|
|
69
|
-
if f"<{i}>" in summary_tmp:
|
|
70
|
-
try:
|
|
71
|
-
v = self.__getattribute__(i)
|
|
72
|
-
except AttributeError:
|
|
73
|
-
v = None
|
|
74
|
-
text = text.replace(f"<{i}>", str(v))
|
|
75
|
-
|
|
76
|
-
return text
|
|
77
|
-
|
|
78
|
-
cls.__str__ = to_str if cls().__str__() == "__not_set__" else cls.__str__
|
|
79
|
-
|
|
80
|
-
message_types[sg_type] = {
|
|
81
|
-
"type": cls,
|
|
82
|
-
"args": list(anns.keys())
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return cls
|
|
86
|
-
|
|
87
|
-
return inner_builder
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
class Base:
|
|
91
|
-
def __init__(self, *args, **kwargs): ...
|
|
9
|
+
config = cm.get_cfg()
|
|
10
|
+
if config.protocol == "OneBot":
|
|
11
|
+
from Hyper.Adapters.OneBotLib.Res import segment_builder, Base, message_types
|
|
12
|
+
elif config.protocol == "Satori":
|
|
13
|
+
# from Hyper.Adapters.SatoriLib.Res import segment_builder, Base, message_types
|
|
14
|
+
pass
|
|
92
15
|
|
|
93
|
-
def to_json(self) -> dict: ...
|
|
94
16
|
|
|
95
|
-
|
|
17
|
+
class MediaSeg(Base):
|
|
18
|
+
@classmethod
|
|
19
|
+
def build(cls, file: str):
|
|
20
|
+
if file.startswith("http") or file.startswith("file:") or file.startswith("base64:"):
|
|
21
|
+
return cls(file=file)
|
|
22
|
+
else:
|
|
23
|
+
if os.path.isfile(file):
|
|
24
|
+
if os.path.isabs(file):
|
|
25
|
+
res = cls()
|
|
26
|
+
res.file = f"file://{file}"
|
|
27
|
+
return res
|
|
28
|
+
else:
|
|
29
|
+
res = cls()
|
|
30
|
+
res.file = f"file://{os.path.abspath(file)}"
|
|
31
|
+
return res
|
|
32
|
+
else:
|
|
33
|
+
return None
|
|
96
34
|
|
|
97
35
|
|
|
98
36
|
@segment_builder("text", "<text>")
|
|
@@ -101,9 +39,9 @@ class Text(Base):
|
|
|
101
39
|
|
|
102
40
|
|
|
103
41
|
@segment_builder("image", "[图片]")
|
|
104
|
-
class Image(
|
|
42
|
+
class Image(MediaSeg):
|
|
105
43
|
file: str
|
|
106
|
-
url: str
|
|
44
|
+
url: str
|
|
107
45
|
summary: str = "[图片]"
|
|
108
46
|
|
|
109
47
|
|
|
@@ -129,13 +67,15 @@ class Location(Base):
|
|
|
129
67
|
|
|
130
68
|
|
|
131
69
|
@segment_builder("record", "[语音]")
|
|
132
|
-
class Record(
|
|
70
|
+
class Record(MediaSeg):
|
|
133
71
|
file: str
|
|
72
|
+
url: str
|
|
134
73
|
|
|
135
74
|
|
|
136
75
|
@segment_builder("video", "[视频]")
|
|
137
|
-
class Video(
|
|
76
|
+
class Video(MediaSeg):
|
|
138
77
|
file: str
|
|
78
|
+
url: str
|
|
139
79
|
|
|
140
80
|
|
|
141
81
|
@segment_builder("poke", "[拍一拍]")
|
|
@@ -296,6 +236,6 @@ class Rps(Base):
|
|
|
296
236
|
class Music(Base):
|
|
297
237
|
type: str
|
|
298
238
|
id: str = None
|
|
299
|
-
url: str
|
|
239
|
+
url: str
|
|
300
240
|
audio: str = None
|
|
301
241
|
title: str = None
|
|
@@ -3,6 +3,7 @@ import os
|
|
|
3
3
|
import shutil
|
|
4
4
|
import traceback
|
|
5
5
|
import asyncio
|
|
6
|
+
from typing import Union
|
|
6
7
|
import aiohttp
|
|
7
8
|
import time
|
|
8
9
|
import requests
|
|
@@ -103,26 +104,13 @@ class ErrorHandler:
|
|
|
103
104
|
return wrapper
|
|
104
105
|
|
|
105
106
|
|
|
106
|
-
class Random:
|
|
107
|
-
def __init__(self, seed: int = None):
|
|
108
|
-
self.seed = seed
|
|
109
|
-
|
|
110
|
-
def random(self) -> int:
|
|
111
|
-
self.seed = self.seed ** 2
|
|
112
|
-
self.seed = int(str(self.seed)[:7])
|
|
113
|
-
return int(str(self.seed)[1:5])
|
|
114
|
-
|
|
115
|
-
def __call__(self) -> int:
|
|
116
|
-
return self.random()
|
|
117
|
-
|
|
118
|
-
|
|
119
107
|
class FileManager:
|
|
120
108
|
@staticmethod
|
|
121
109
|
def create(path: str) -> bool:
|
|
122
110
|
try:
|
|
123
111
|
with open(path, "w") as f:
|
|
124
112
|
f.write("")
|
|
125
|
-
except (FileExistsError
|
|
113
|
+
except (FileExistsError, OSError, IOError):
|
|
126
114
|
return False
|
|
127
115
|
|
|
128
116
|
return True
|
|
@@ -144,7 +132,7 @@ class FileManager:
|
|
|
144
132
|
|
|
145
133
|
@staticmethod
|
|
146
134
|
@Cacher(7).cache
|
|
147
|
-
def read_as_json(path: str, encoding: str = "utf-8") -> dict
|
|
135
|
+
def read_as_json(path: str, encoding: str = "utf-8") -> Union[list, dict]:
|
|
148
136
|
with open(path, "r", encoding=encoding) as f:
|
|
149
137
|
return json.load(f)
|
|
150
138
|
|
|
@@ -159,7 +147,7 @@ class FileManager:
|
|
|
159
147
|
try:
|
|
160
148
|
os.remove(path)
|
|
161
149
|
return True
|
|
162
|
-
except (FileNotFoundError
|
|
150
|
+
except (FileNotFoundError, OSError, IOError):
|
|
163
151
|
return False
|
|
164
152
|
|
|
165
153
|
@staticmethod
|
|
@@ -167,7 +155,7 @@ class FileManager:
|
|
|
167
155
|
try:
|
|
168
156
|
shutil.copy(path1, path2)
|
|
169
157
|
return True
|
|
170
|
-
except (FileNotFoundError
|
|
158
|
+
except (FileNotFoundError, OSError, IOError):
|
|
171
159
|
return False
|
|
172
160
|
|
|
173
161
|
|
|
@@ -245,10 +233,12 @@ class TempDownloader:
|
|
|
245
233
|
self.index = index
|
|
246
234
|
self.silent = silent
|
|
247
235
|
|
|
248
|
-
async def get_bytes(self) -> dict[str, bytes]:
|
|
236
|
+
async def get_bytes(self, ua: str = None) -> dict[str, bytes]:
|
|
249
237
|
result_to_re = {}
|
|
250
238
|
this: bytes = bytes()
|
|
251
239
|
headers = {"Range": f"bytes={self.part[0]}-{self.part[1]}"}
|
|
240
|
+
if ua:
|
|
241
|
+
headers["User-Agent"] = ua
|
|
252
242
|
|
|
253
243
|
async with aiohttp.ClientSession() as session:
|
|
254
244
|
async with session.get(self.url, headers=headers) as resp:
|
|
@@ -296,10 +286,16 @@ class Downloader:
|
|
|
296
286
|
result[-1][-1] = size - 1
|
|
297
287
|
return result
|
|
298
288
|
|
|
299
|
-
async def download(self):
|
|
289
|
+
async def download(self, ua: str = None):
|
|
300
290
|
if not self.check():
|
|
301
291
|
raise Exception
|
|
302
|
-
|
|
292
|
+
if ua:
|
|
293
|
+
headers = {
|
|
294
|
+
"User-Agent": ua
|
|
295
|
+
}
|
|
296
|
+
response = requests.get(self.url, stream=True, verify=False, headers=headers)
|
|
297
|
+
else:
|
|
298
|
+
response = requests.get(self.url, stream=True, verify=False)
|
|
303
299
|
if response.status_code != 200:
|
|
304
300
|
raise ConnectionError
|
|
305
301
|
|
|
@@ -326,7 +322,7 @@ class Downloader:
|
|
|
326
322
|
for i in parts:
|
|
327
323
|
_ = TempDownloader(url=self.url, part=i, index=parts.index(i), silent=self.silent)
|
|
328
324
|
|
|
329
|
-
tasks.append(asyncio.create_task(_.get_bytes()))
|
|
325
|
+
tasks.append(asyncio.create_task(_.get_bytes(ua=ua)))
|
|
330
326
|
|
|
331
327
|
await asyncio.gather(*tasks)
|
|
332
328
|
for i in tasks:
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import json
|
|
3
|
+
from typing import Union
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ObjectedDict:
|
|
7
|
+
def __init__(self, content: dict = None):
|
|
8
|
+
if content is None:
|
|
9
|
+
self.__content = dict()
|
|
10
|
+
else:
|
|
11
|
+
self.__content = content
|
|
12
|
+
|
|
13
|
+
def __getattr__(self, attr):
|
|
14
|
+
if attr == "_ObjectedDict__content" or attr == "raw":
|
|
15
|
+
return self.__content
|
|
16
|
+
else:
|
|
17
|
+
att = self.__content.get(attr)
|
|
18
|
+
if isinstance(att, dict):
|
|
19
|
+
return ObjectedDict(att)
|
|
20
|
+
else:
|
|
21
|
+
return att
|
|
22
|
+
|
|
23
|
+
def __setattr__(self, attr, value):
|
|
24
|
+
if attr == "_ObjectedDict__content":
|
|
25
|
+
super().__setattr__(attr, value)
|
|
26
|
+
else:
|
|
27
|
+
self.__content[attr] = value
|
|
28
|
+
|
|
29
|
+
def __getitem__(self, item):
|
|
30
|
+
return self.__content.get(item)
|
|
31
|
+
|
|
32
|
+
def __setitem__(self, key, value):
|
|
33
|
+
if self.__content.get(key):
|
|
34
|
+
self.__content[key] = value
|
|
35
|
+
|
|
36
|
+
def __str__(self) -> str:
|
|
37
|
+
return self.__content.__str__()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class Char(str):
|
|
41
|
+
@classmethod
|
|
42
|
+
def convert_from(cls, obj: Union[str, "String"]):
|
|
43
|
+
if len(obj) != 1:
|
|
44
|
+
raise TypeError("Char is not fxxking String!")
|
|
45
|
+
else:
|
|
46
|
+
return cls(obj)
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def width(self) -> int:
|
|
50
|
+
char = self
|
|
51
|
+
if len(char) != 1:
|
|
52
|
+
raise TypeError("String too long")
|
|
53
|
+
o = ord(char)
|
|
54
|
+
widths = [
|
|
55
|
+
(126, 1), (159, 0), (687, 1), (710, 0), (711, 1),
|
|
56
|
+
(727, 0), (733, 1), (879, 0), (1154, 1), (1161, 0),
|
|
57
|
+
(4347, 1), (4447, 1.75), (7467, 1), (7521, 0), (8369, 1),
|
|
58
|
+
(8426, 0), (9000, 1), (9002, 1.75), (11021, 1), (12350, 1.75),
|
|
59
|
+
(12351, 1), (12438, 1.75), (12442, 0), (19893, 1.75), (19967, 1),
|
|
60
|
+
(55203, 1.75), (63743, 1), (64106, 1.75), (65039, 1), (65059, 0),
|
|
61
|
+
(65131, 1.75), (65279, 1), (65376, 1.75), (65500, 1), (65510, 1.75),
|
|
62
|
+
(120831, 1), (262141, 1.75), (1114109, 1),
|
|
63
|
+
]
|
|
64
|
+
if o == 0xe or o == 0xf:
|
|
65
|
+
return 0
|
|
66
|
+
for num, wid in widths:
|
|
67
|
+
if o <= num:
|
|
68
|
+
return wid
|
|
69
|
+
return 1
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class String(str):
|
|
73
|
+
def cmdl_parse(self) -> list:
|
|
74
|
+
args = []
|
|
75
|
+
temp = ""
|
|
76
|
+
in_sub = False
|
|
77
|
+
last_sig = ""
|
|
78
|
+
for i in (self if self.endswith(" ") else self + " "):
|
|
79
|
+
if in_sub and i == " ":
|
|
80
|
+
temp += i
|
|
81
|
+
elif not in_sub and i == " ":
|
|
82
|
+
args.append(temp)
|
|
83
|
+
temp = ""
|
|
84
|
+
elif i == '"' or i == "'":
|
|
85
|
+
if not in_sub:
|
|
86
|
+
in_sub = True
|
|
87
|
+
last_sig = i
|
|
88
|
+
elif i == last_sig:
|
|
89
|
+
in_sub = False
|
|
90
|
+
else:
|
|
91
|
+
temp += i
|
|
92
|
+
|
|
93
|
+
res = []
|
|
94
|
+
|
|
95
|
+
for i in args:
|
|
96
|
+
if "=" in i:
|
|
97
|
+
if " " in i:
|
|
98
|
+
continue
|
|
99
|
+
index = args.index(i)
|
|
100
|
+
new = args[index].split("=", 1)
|
|
101
|
+
args[index] = {new[0]: new[1]}
|
|
102
|
+
|
|
103
|
+
for i in args:
|
|
104
|
+
if str(i) != "":
|
|
105
|
+
if isinstance(i, dict):
|
|
106
|
+
res.append(i)
|
|
107
|
+
else:
|
|
108
|
+
res.append(String(i))
|
|
109
|
+
|
|
110
|
+
del temp, in_sub, last_sig, args
|
|
111
|
+
|
|
112
|
+
return res
|
|
113
|
+
|
|
114
|
+
def match(self, par: str) -> bool:
|
|
115
|
+
return True if re.match(par, self) else False
|
|
116
|
+
|
|
117
|
+
def clear(self) -> "String":
|
|
118
|
+
if len(self) != 0:
|
|
119
|
+
return String("")
|
|
120
|
+
else:
|
|
121
|
+
return self
|
|
122
|
+
|
|
123
|
+
def to_json(self) -> Union[list, dict]:
|
|
124
|
+
return json.loads(self)
|
|
125
|
+
|
|
126
|
+
def format(self, w_p_l: int = 110) -> "String":
|
|
127
|
+
c_lis = list(map(Char.convert_from, list(self)))
|
|
128
|
+
lines = []
|
|
129
|
+
temp_line = ""
|
|
130
|
+
temp_length = 0
|
|
131
|
+
for i in c_lis:
|
|
132
|
+
if i == "\n":
|
|
133
|
+
lines.append(temp_line)
|
|
134
|
+
temp_line = ""
|
|
135
|
+
temp_length = 0
|
|
136
|
+
temp_line += i
|
|
137
|
+
temp_length += i.width
|
|
138
|
+
if temp_length >= w_p_l:
|
|
139
|
+
lines.append(temp_line)
|
|
140
|
+
temp_line = ""
|
|
141
|
+
temp_length = 0
|
|
142
|
+
|
|
143
|
+
lines.append(temp_line)
|
|
144
|
+
|
|
145
|
+
return String("\n".join(lines))
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class List(list):
|
|
149
|
+
def __getitem__(self, item):
|
|
150
|
+
try:
|
|
151
|
+
return super().__getitem__(item)
|
|
152
|
+
except IndexError:
|
|
153
|
+
return None
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class Integer(int):
|
|
157
|
+
@classmethod
|
|
158
|
+
def convert_from(cls, target):
|
|
159
|
+
if isinstance(target, int):
|
|
160
|
+
return cls(target)
|
|
161
|
+
|
|
162
|
+
try:
|
|
163
|
+
return cls(int(target))
|
|
164
|
+
except:
|
|
165
|
+
return cls(-1)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
class Enum:
|
|
169
|
+
def __init__(self, *args):
|
|
170
|
+
self.items = list(args)
|
|
171
|
+
|
|
172
|
+
def __getattr__(self, item):
|
|
173
|
+
if item in self.items:
|
|
174
|
+
return self.items.index(item)
|
|
175
|
+
else:
|
|
176
|
+
return None
|
|
177
|
+
|
|
@@ -6,13 +6,15 @@ Hyper/Errors.py
|
|
|
6
6
|
Hyper/Events.py
|
|
7
7
|
Hyper/Listener.py
|
|
8
8
|
Hyper/Logger.py
|
|
9
|
-
Hyper/Logic.py
|
|
10
9
|
Hyper/Manager.py
|
|
11
|
-
Hyper/ModuleClass.py
|
|
12
10
|
Hyper/Network.py
|
|
13
11
|
Hyper/Segments.py
|
|
14
12
|
Hyper/Adapters/OneBot.py
|
|
13
|
+
Hyper/Adapters/Satori.py
|
|
15
14
|
Hyper/Adapters/OneBotLib/Manager.py
|
|
15
|
+
Hyper/Adapters/OneBotLib/Res.py
|
|
16
|
+
Hyper/Utils/Logic.py
|
|
17
|
+
Hyper/Utils/TypeExt.py
|
|
16
18
|
hyper_bot.egg-info/PKG-INFO
|
|
17
19
|
hyper_bot.egg-info/SOURCES.txt
|
|
18
20
|
hyper_bot.egg-info/dependency_links.txt
|
|
@@ -4,11 +4,11 @@ from setuptools import setup
|
|
|
4
4
|
|
|
5
5
|
setup(
|
|
6
6
|
name="hyper-bot",
|
|
7
|
-
version="0.
|
|
7
|
+
version="0.772",
|
|
8
8
|
description="稳定高效、易于开发的QQ Bot框架",
|
|
9
9
|
author="Harcic",
|
|
10
10
|
author_email="harcic@outlook.com",
|
|
11
11
|
url="https://github.com/HarcicYang/HypeR_Bot",
|
|
12
|
-
packages=["Hyper", "Hyper.Adapters", "Hyper.Adapters.OneBotLib"],
|
|
12
|
+
packages=["Hyper", "Hyper.Adapters", "Hyper.Adapters.OneBotLib", "Hyper.Utils"],
|
|
13
13
|
include_package_data=True,
|
|
14
14
|
)
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
from Hyper import Events, Listener, Logger, Configurator
|
|
2
|
-
|
|
3
|
-
import dataclasses
|
|
4
|
-
|
|
5
|
-
config = Configurator.cm.get_cfg()
|
|
6
|
-
logger = Logger.Logger()
|
|
7
|
-
logger.set_level(config.log_level)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
@dataclasses.dataclass
|
|
11
|
-
class ModuleInfo:
|
|
12
|
-
is_hidden: bool = True
|
|
13
|
-
module_name: str = "None"
|
|
14
|
-
author: str = "None"
|
|
15
|
-
version: str = "0.0"
|
|
16
|
-
desc: str = "None"
|
|
17
|
-
helps: str = "None"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class Module:
|
|
21
|
-
def __init__(self, actions: Listener.Actions, event):
|
|
22
|
-
self.actions = actions
|
|
23
|
-
self.event = event
|
|
24
|
-
|
|
25
|
-
async def handle(self):
|
|
26
|
-
pass
|
|
27
|
-
|
|
28
|
-
@staticmethod
|
|
29
|
-
def info() -> ModuleInfo:
|
|
30
|
-
return ModuleInfo()
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
class InnerHandler:
|
|
34
|
-
def __init__(self, module: Module, allowed: list):
|
|
35
|
-
self.module = module
|
|
36
|
-
self.allowed = allowed
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
register_modules: list[InnerHandler] = []
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class ModuleRegister:
|
|
43
|
-
@staticmethod
|
|
44
|
-
def register(*args):
|
|
45
|
-
def decorator(cls):
|
|
46
|
-
if len(args) < 1:
|
|
47
|
-
allowed = [Events.Event]
|
|
48
|
-
else:
|
|
49
|
-
allowed = list(args)
|
|
50
|
-
|
|
51
|
-
from typing import Union
|
|
52
|
-
|
|
53
|
-
def init(self, actions: Listener.Actions, event: Union[*allowed]):
|
|
54
|
-
self.actions = actions
|
|
55
|
-
self.event = event
|
|
56
|
-
|
|
57
|
-
cls.__init__ = init
|
|
58
|
-
|
|
59
|
-
register_modules.append(InnerHandler(cls, allowed))
|
|
60
|
-
|
|
61
|
-
return cls
|
|
62
|
-
|
|
63
|
-
return decorator
|
|
64
|
-
|
|
65
|
-
@staticmethod
|
|
66
|
-
def get_registered() -> list:
|
|
67
|
-
return register_modules
|
hyper-bot-0.75/Hyper/Network.py
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import websocket
|
|
2
|
-
import httpx
|
|
3
|
-
import queue
|
|
4
|
-
import flask
|
|
5
|
-
import traceback
|
|
6
|
-
import json
|
|
7
|
-
import logging
|
|
8
|
-
import threading
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class WebsocketConnection:
|
|
12
|
-
def __init__(self, url: str):
|
|
13
|
-
self.ws = websocket.WebSocket()
|
|
14
|
-
self.url = url
|
|
15
|
-
|
|
16
|
-
def connect(self) -> None:
|
|
17
|
-
self.ws.connect(self.url)
|
|
18
|
-
|
|
19
|
-
def send(self, message: str) -> None:
|
|
20
|
-
self.ws.send(message)
|
|
21
|
-
|
|
22
|
-
def close(self) -> None:
|
|
23
|
-
self.ws.close()
|
|
24
|
-
|
|
25
|
-
def recv(self) -> dict:
|
|
26
|
-
return json.loads(self.ws.recv())
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class HTTPConnection:
|
|
30
|
-
def __init__(self, url: str, listener_url: str):
|
|
31
|
-
self.url = url
|
|
32
|
-
listener_url = listener_url.replace("http://", "")
|
|
33
|
-
listener_url = listener_url.replace("https://", "")
|
|
34
|
-
self.listener_url = listener_url.split(":")[0]
|
|
35
|
-
try:
|
|
36
|
-
self.port = int(listener_url.split(":")[1])
|
|
37
|
-
except IndexError:
|
|
38
|
-
self.port = 8080
|
|
39
|
-
self.app = flask.Flask(__name__)
|
|
40
|
-
self.app.config["LOGGER_HANDLER_POLICY"] = "never"
|
|
41
|
-
logging.getLogger("werkzeug").setLevel(logging.ERROR)
|
|
42
|
-
self.reports = queue.Queue()
|
|
43
|
-
|
|
44
|
-
self.listener_started = False
|
|
45
|
-
|
|
46
|
-
def __start_listener(self) -> None:
|
|
47
|
-
@self.app.route("/", methods=["POST"])
|
|
48
|
-
def listener():
|
|
49
|
-
self.reports.put(flask.request.json)
|
|
50
|
-
return {}
|
|
51
|
-
|
|
52
|
-
# self.app.run(host=self.listener_url, port=self.port)
|
|
53
|
-
|
|
54
|
-
threading.Thread(target=lambda: self.app.run(host=self.listener_url, port=self.port)).start()
|
|
55
|
-
self.listener_started = True
|
|
56
|
-
|
|
57
|
-
def connect(self) -> None:
|
|
58
|
-
if not self.listener_started:
|
|
59
|
-
self.__start_listener()
|
|
60
|
-
httpx.post(self.url)
|
|
61
|
-
traceback.print_exc()
|
|
62
|
-
|
|
63
|
-
def recv(self) -> dict:
|
|
64
|
-
return self.reports.get()
|
|
65
|
-
|
|
66
|
-
def send(self, endpoint: str, data: dict, echo: str) -> None:
|
|
67
|
-
response = httpx.post(f"{self.url}/{endpoint}", json=data)
|
|
68
|
-
res = response.json()
|
|
69
|
-
res["echo"] = echo
|
|
70
|
-
self.reports.put(res)
|
|
71
|
-
|
|
72
|
-
@staticmethod
|
|
73
|
-
def close() -> None:
|
|
74
|
-
shutdown_func = flask.request.environ.get('werkzeug.server.shutdown')
|
|
75
|
-
if shutdown_func is None:
|
|
76
|
-
raise RuntimeError('Not running with the Werkzeug Server')
|
|
77
|
-
shutdown_func()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|