hyper-bot 0.7__py3-none-any.whl

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/Network.py ADDED
@@ -0,0 +1,70 @@
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
+ def connect(self) -> None:
45
+ @self.app.route("/", methods=["POST"])
46
+ def listener():
47
+ self.reports.put(flask.request.json)
48
+ return {}
49
+
50
+ # self.app.run(host=self.listener_url, port=self.port)
51
+
52
+ threading.Thread(target=lambda: self.app.run(host=self.listener_url, port=self.port)).start()
53
+ httpx.post(self.url)
54
+ traceback.print_exc()
55
+
56
+ def recv(self) -> dict:
57
+ return self.reports.get()
58
+
59
+ def send(self, endpoint: str, data: dict, echo: str) -> None:
60
+ response = httpx.post(f"{self.url}/{endpoint}", json=data)
61
+ res = response.json()
62
+ res["echo"] = echo
63
+ self.reports.put(res)
64
+
65
+ @staticmethod
66
+ def close() -> None:
67
+ shutdown_func = flask.request.environ.get('werkzeug.server.shutdown')
68
+ if shutdown_func is None:
69
+ raise RuntimeError('Not running with the Werkzeug Server')
70
+ shutdown_func()
Hyper/Segments.py ADDED
@@ -0,0 +1,289 @@
1
+ import json
2
+ import typing
3
+ import uuid
4
+
5
+ from Hyper.Errors import *
6
+
7
+ message_types = {}
8
+
9
+
10
+ def segment_builder(sg_type: str, summary_tmp: str = None):
11
+ # print(inspect.get_annotations(cls))
12
+ def inner_builder(cls):
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
+ arg[i] = kwargs[i]
25
+ new_arg = arg.copy()
26
+
27
+ if len(anns) > len(arg):
28
+ for i in anns.keys():
29
+ if i not in arg.keys():
30
+ if i not in var.keys():
31
+ new_arg[i] = None
32
+ continue
33
+ new_arg[i] = anns[i](var[i])
34
+
35
+ for i in new_arg:
36
+ setattr(self, i, new_arg[i])
37
+
38
+ cls.__init__ = init
39
+
40
+ def to_json(self) -> dict:
41
+ base = {"type": sg_type, "data": {}}
42
+ for i in anns:
43
+ base["data"][i] = getattr(self, i)
44
+
45
+ return base
46
+
47
+ cls.to_json = to_json
48
+
49
+ def to_str(self) -> str:
50
+ text = summary_tmp
51
+ if text is None:
52
+ text = "[]"
53
+ if "<" not in text and ">" not in text:
54
+ return text
55
+
56
+ for i in anns:
57
+ if f"<{i}>" in summary_tmp:
58
+ try:
59
+ v = self.__getattribute__(i)
60
+ except AttributeError:
61
+ v = None
62
+ text = text.replace(f"<{i}>", str(v))
63
+
64
+ return text
65
+ cls.__str__ = to_str if cls().__str__() == "__not_set__" else cls.__str__
66
+
67
+ message_types[sg_type] = {
68
+ "type": cls,
69
+ "args": list(anns.keys())
70
+ }
71
+
72
+ return cls
73
+
74
+ return inner_builder
75
+
76
+
77
+ class Base:
78
+ def __init__(self, *args, **kwargs): ...
79
+
80
+ def to_json(self) -> dict: ...
81
+
82
+ def __str__(self) -> str: return "__not_set__"
83
+
84
+
85
+ @segment_builder("text", "<text>")
86
+ class Text(Base):
87
+ text: str
88
+
89
+
90
+ @segment_builder("image", "[图片]")
91
+ class Image(Base):
92
+ file: str
93
+ url: str = ""
94
+ summary: str = "[图片]"
95
+
96
+
97
+ @segment_builder("at", f"@<qq>")
98
+ class At(Base):
99
+ qq: str
100
+
101
+
102
+ @segment_builder("reply", "")
103
+ class Reply(Base):
104
+ id: str
105
+
106
+
107
+ @segment_builder("face", "[表情: <id>]")
108
+ class Faces(Base):
109
+ id: str
110
+
111
+
112
+ @segment_builder("location", "[位置: <lat>, <lon>]")
113
+ class Location(Base):
114
+ lat: str
115
+ lon: str
116
+
117
+
118
+ @segment_builder("record", "[语音]")
119
+ class Record(Base):
120
+ file: str
121
+
122
+
123
+ @segment_builder("video", "[视频]")
124
+ class Video(Base):
125
+ file: str
126
+
127
+
128
+ @segment_builder("poke", "[拍一拍]")
129
+ class Poke(Base):
130
+ type: str
131
+ id: str
132
+
133
+
134
+ @segment_builder("contact")
135
+ class Contact(Base):
136
+ type: str
137
+ id: str
138
+
139
+ def __str__(self) -> str:
140
+ return f"[推荐{'群' if self.type == 'group' else '用户'}: {self.id}]"
141
+
142
+
143
+ @segment_builder("forward", "[转发消息]")
144
+ class Forward(Base):
145
+ id: str
146
+
147
+
148
+ @segment_builder("node", "[转发消息]")
149
+ class Node(Base):
150
+ id: str
151
+
152
+
153
+ class CustomNode:
154
+ def __init__(self, user_id: str, nick_name: str, content):
155
+ self.content = {"type": "node",
156
+ "data": {"user_id": user_id, "nick_name": nick_name, "content": content.get_sync()}}
157
+
158
+ def to_json(self) -> dict:
159
+ return self.content
160
+
161
+ def __str__(self) -> str:
162
+ return f"[自定义节点]"
163
+
164
+
165
+ class KeyBoardButton:
166
+ def __init__(self,
167
+ text: str,
168
+ style: int = 1,
169
+ button_type: int = 2,
170
+ data: str = "Hello World",
171
+ enter: bool = False,
172
+ permission: int = 2,
173
+ specify_user_ids=None):
174
+ self.content = {
175
+ "id": str(uuid.uuid4()),
176
+ "render_data": {
177
+ "label": text,
178
+ "visited_label": text,
179
+ "style": style
180
+ },
181
+ "action": {
182
+ "type": button_type,
183
+ "permission": {
184
+ "type": permission,
185
+ "specify_user_ids": specify_user_ids
186
+ },
187
+ "enter": enter,
188
+ "unsupport_tips": "Harcic",
189
+ "data": data
190
+ }
191
+ }
192
+
193
+ def get(self) -> dict:
194
+ return self.content
195
+
196
+ def __str__(self) -> str:
197
+ return f"[按键{self.content['render_data']['label']}]"
198
+
199
+
200
+ class KeyBoardRow:
201
+ def __init__(self, buttons: list[KeyBoardButton] = None):
202
+ self.content = {
203
+ "buttons": []
204
+ }
205
+ buttons = [] if buttons is None else buttons
206
+ for i in buttons:
207
+ self.content["buttons"].append(i.get())
208
+
209
+ def add(self, button: KeyBoardButton) -> None:
210
+ if len(self.content["buttons"]) < 5:
211
+ self.content["buttons"].append(button.get())
212
+ else:
213
+ raise ButtonRowFulledError("This button row is full")
214
+
215
+ def get(self) -> dict:
216
+ return self.content
217
+
218
+
219
+ class KeyBoard:
220
+ def __init__(self, button_rows: list[KeyBoardRow]):
221
+ self.content = {"type": "keyboard",
222
+ "data": {"content": {"rows": [i.get() for i in button_rows]}, "bot_appid": 0}}
223
+
224
+ def to_json(self) -> dict:
225
+ return self.content
226
+
227
+ def __str__(self) -> str:
228
+ return f"[自定按键版]"
229
+
230
+
231
+ class MarkdownContent:
232
+ def __init__(self, raw_content: str):
233
+ self.content = (
234
+ raw_content
235
+ .replace('"', r'\\\"')
236
+ .replace(r"\`", r"\`")
237
+ )
238
+
239
+
240
+ class MarkDown:
241
+ def __init__(self, content: MarkdownContent):
242
+ self.content = {"type": "markdown",
243
+ "data": {"content": json.dumps({"content": content.content}).replace('"', '"')}}
244
+
245
+ def set(self, content: MarkdownContent) -> None:
246
+ self.__init__(content)
247
+
248
+ def to_json(self) -> dict:
249
+ return self.content
250
+
251
+ def __str__(self) -> str:
252
+ return f"[MarkDown]"
253
+
254
+
255
+ @segment_builder("longmsg", "[<id>]")
256
+ class LongMessage(Base):
257
+ id: str
258
+
259
+
260
+ @segment_builder("json", "[Json]")
261
+ class Json(Base):
262
+ data: typing.Union[dict, list, str]
263
+
264
+
265
+ @segment_builder("mface", "[表情]")
266
+ class MarketFace(Base):
267
+ face_id: str
268
+ tab_id: str
269
+ key: str
270
+
271
+
272
+ @segment_builder("dice", "[骰子]")
273
+ class Dice(Base):
274
+ pass
275
+
276
+
277
+ @segment_builder("rps", "[猜拳]")
278
+ class Rps(Base):
279
+ pass
280
+
281
+
282
+ @segment_builder("music", "[音乐]")
283
+ class Music(Base):
284
+ type: str
285
+ id: str = None
286
+ url: str = None
287
+ audio: str = None
288
+ title: str = None
289
+
Hyper/WordSafety.py ADDED
@@ -0,0 +1,68 @@
1
+ import jieba
2
+ import logging
3
+ import asyncio
4
+
5
+ from Hyper import Logic
6
+
7
+ logging.getLogger("jieba").setLevel(logging.ERROR)
8
+
9
+
10
+ class Result:
11
+ def __init__(self, message: str, result: bool):
12
+ self.message = message
13
+ self.result = result
14
+
15
+
16
+ class AsyncChecker:
17
+ def __init__(self, hot_words: list[dict[str, str]]):
18
+ self.hot_words = hot_words
19
+
20
+ async def check(self, text: list) -> Result:
21
+ for j in self.hot_words:
22
+ if j["word"] in text:
23
+ ret = Result(f"检测到类型为{j['type']}的敏感用词", False)
24
+ return ret
25
+
26
+ ret = Result("未检出敏感词", True)
27
+ return ret
28
+
29
+
30
+ with open("assets/dict.txt", "r", encoding="utf-8") as f:
31
+ words: list[dict[str, str]] = []
32
+ word = f.read()
33
+ word = word.split("\n")
34
+ inner_words: list[AsyncChecker] = []
35
+ tmp: list[dict[str, str]] = []
36
+ for i in word:
37
+ temp = i.split(" ")
38
+ words.append({"word": temp[0], "type": temp[1]})
39
+ tmp.append({"word": temp[0], "type": temp[1]})
40
+ if len(tmp) == 50:
41
+ inner_words.append(AsyncChecker(tmp))
42
+ tmp = []
43
+
44
+
45
+ @Logic.Cacher().cache
46
+ def check(text: str) -> Result:
47
+ texts = jieba.lcut(text)
48
+ for j in words:
49
+ if j["word"] in texts:
50
+ ret = Result(f"检测到类型为{j['type']}的敏感用词", False)
51
+ return ret
52
+
53
+ ret = Result("未检出敏感词", True)
54
+ return ret
55
+
56
+
57
+ @Logic.Cacher().cache
58
+ async def check_async(text: str) -> Result:
59
+ texts = jieba.lcut(text)
60
+ __tasks: list[asyncio.Task] = []
61
+ for j in inner_words:
62
+ __tasks.append(asyncio.create_task(j.check(texts)))
63
+ await asyncio.gather(*__tasks)
64
+ for j in __tasks:
65
+ if not j.result().result:
66
+ return j.result()
67
+ ret = Result("未检出敏感词", True)
68
+ return ret