hyper-bot 0.74__tar.gz → 0.75__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.
@@ -0,0 +1,337 @@
1
+ import json
2
+ import os
3
+ import shutil
4
+ import traceback
5
+ import asyncio
6
+ import aiohttp
7
+ import time
8
+ import requests
9
+
10
+ from Hyper import Logger
11
+
12
+
13
+ class Cacher:
14
+ def __init__(self, cache_time: int = 5):
15
+ self.cache_time: int = cache_time
16
+ self.cached: dict = {}
17
+
18
+ def cache(self, func):
19
+ def wrapper(*args, **kwargs):
20
+ if kwargs.get("no_cache", False):
21
+ kwargs.pop("no_cache")
22
+ return func(*args, **kwargs)
23
+ if str(kwargs) not in self.cached:
24
+ ret = func(*args, **kwargs)
25
+ self.cached[str(kwargs)] = ret
26
+ if len(self.cached) >= self.cache_time:
27
+ for i in self.cached:
28
+ del self.cached[i]
29
+ break
30
+ return ret
31
+ else:
32
+ return self.cached[str(kwargs)]
33
+
34
+ return wrapper
35
+
36
+ def cache_async(self, func):
37
+ async def wrapper(*args, **kwargs):
38
+ if kwargs.get("no_cache", False):
39
+ kwargs.pop("no_cache")
40
+ return await func(*args, **kwargs)
41
+ if str(kwargs) not in self.cached:
42
+ ret = await func(*args, **kwargs)
43
+ self.cached[str(kwargs)] = ret
44
+ if len(self.cached) >= self.cache_time:
45
+ for i in self.cached:
46
+ del self.cached[i]
47
+ break
48
+ return ret
49
+ else:
50
+ return self.cached[str(kwargs)]
51
+
52
+ return wrapper
53
+
54
+
55
+ class ErrorHandler:
56
+ def __init__(self, level=Logger.levels.ERROR, retries: int = 0):
57
+ self.level = level
58
+ self.logger = Logger.Logger()
59
+ self.retries = retries
60
+
61
+ def handle(self, func):
62
+ def wrapper(*args, **kwargs):
63
+ try:
64
+ return func(*args, **kwargs)
65
+ except:
66
+ self.logger.log(f"出现错误:\n{str(traceback.format_exc())}", level=self.level)
67
+
68
+ return wrapper
69
+
70
+ def handle_async(self, func):
71
+ async def wrapper(*args, **kwargs):
72
+ try:
73
+ return await func(*args, **kwargs)
74
+ except:
75
+ self.logger.log(f"出现错误:\n{str(traceback.format_exc())}", level=self.level)
76
+
77
+ return wrapper
78
+
79
+ def auto_retry(self, func):
80
+ def wrapper(*args, **kwargs):
81
+ retried = 0
82
+ while retried < self.retries:
83
+ retried += 1
84
+ try:
85
+ return func(*args, **kwargs)
86
+ except Exception as e:
87
+ self.logger.log(f"出现错误:\n{str(e)}, 正在重试...", level=self.level)
88
+ self.logger.log(f"错误在{retried}次重试后失败", level=self.level)
89
+
90
+ return wrapper
91
+
92
+ def auto_retry_async(self, func):
93
+ async def wrapper(*args, **kwargs):
94
+ retried = 0
95
+ while retried < self.retries:
96
+ retried += 1
97
+ try:
98
+ return await func(*args, **kwargs)
99
+ except Exception as e:
100
+ self.logger.log(f"出现错误:\n{str(e)}, 正在重试...", level=self.level)
101
+ self.logger.log(f"错误在{retried}次重试后失败", level=self.level)
102
+
103
+ return wrapper
104
+
105
+
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
+ class FileManager:
120
+ @staticmethod
121
+ def create(path: str) -> bool:
122
+ try:
123
+ with open(path, "w") as f:
124
+ f.write("")
125
+ except (FileExistsError | OSError | IOError):
126
+ return False
127
+
128
+ return True
129
+
130
+ @staticmethod
131
+ def exists(path: str) -> bool:
132
+ try:
133
+ with open(path, "r") as f:
134
+ f.read()
135
+ return True
136
+ except FileNotFoundError:
137
+ return False
138
+
139
+ @staticmethod
140
+ @Cacher(7).cache
141
+ def read_as_text(path: str, encoding: str = "utf-8") -> str:
142
+ with open(path, "r", encoding=encoding) as f:
143
+ return f.read()
144
+
145
+ @staticmethod
146
+ @Cacher(7).cache
147
+ def read_as_json(path: str, encoding: str = "utf-8") -> dict | list:
148
+ with open(path, "r", encoding=encoding) as f:
149
+ return json.load(f)
150
+
151
+ @staticmethod
152
+ @Cacher(7).cache
153
+ def read_raw(path: str) -> bytes:
154
+ with open(path, "rb") as f:
155
+ return f.read()
156
+
157
+ @staticmethod
158
+ def delete(path: str) -> bool:
159
+ try:
160
+ os.remove(path)
161
+ return True
162
+ except (FileNotFoundError | OSError | IOError):
163
+ return False
164
+
165
+ @staticmethod
166
+ def copy(path1: str, path2: str) -> bool:
167
+ try:
168
+ shutil.copy(path1, path2)
169
+ return True
170
+ except (FileNotFoundError | OSError | IOError):
171
+ return False
172
+
173
+
174
+ class ProgressBar:
175
+ def __init__(self, p_iter,
176
+ total: int = 0, num_per_time: int = 1,
177
+ desc: str = "", on_done: str = "Done",
178
+ empty: str = "\033[38;5;243m━\033[0m", full: str = "\033[31m━\033[0m", done: str = "\033[32m━\033[0m"):
179
+ self.iter = p_iter
180
+ self.total = total
181
+ self.num_per_time = num_per_time
182
+ self.desc = desc
183
+ self.start_time = 0
184
+ self.empty = empty
185
+ self.full = full
186
+ self.done = done
187
+ self.on_done = on_done
188
+
189
+ def __update(self, progress: int):
190
+ time_spent = time.time() - self.start_time
191
+ if self.total == 0:
192
+ progress_percents = ""
193
+ eta = "unknown"
194
+ speed = "unknown"
195
+ else:
196
+ progress_percents = str(float(format(progress / self.total, ".3f")) * 100)[:5]
197
+ if time_spent == 0:
198
+ speed = 1
199
+ else:
200
+ speed = progress / time_spent
201
+ eta = str(format((self.total - progress) / speed, ".2f"))[:5]
202
+
203
+ if float(progress_percents) >= 100.0:
204
+ progress_percents = "100.0"
205
+ bar = f"|{self.done * 25}|"
206
+ else:
207
+ bar = f"|{self.full * int(float(progress_percents) * 0.25)}{self.empty * (25 - int(float(progress_percents) * 0.25))}|"
208
+ if speed == "unknown":
209
+ speed_text = ""
210
+ elif speed > 100:
211
+ speed_text = f"\033[36m{int(speed)}\033[0m it/s "
212
+ elif 100 >= speed >= 50:
213
+ speed_text = f"\033[32m{int(speed)}\033[0m it/s "
214
+ elif 50 > speed >= 20:
215
+ speed_text = f"\033[33m{int(speed)}\033[0m it/s "
216
+ else:
217
+ speed_text = f"\033[31m{int(speed)}\033[0m it/s "
218
+ print(
219
+ f"\r{self.desc}: {bar} {progress_percents}% [{speed_text}\033[31m{int(time_spent)}s\033[0m spent, \033[36m{eta}s\033[0m eta]",
220
+ end="")
221
+
222
+ def __iter__(self):
223
+ self.start_time = time.time()
224
+ progress = 0
225
+ for i in self.iter:
226
+ progress += self.num_per_time
227
+ yield i
228
+ self.__update(progress)
229
+ print(f"\n{self.on_done}")
230
+
231
+ async def __aiter__(self):
232
+ self.start_time = time.time()
233
+ progress = 0
234
+ async for i in self.iter:
235
+ progress += self.num_per_time
236
+ yield i
237
+ self.__update(progress)
238
+ print(f"\n{self.on_done}")
239
+
240
+
241
+ class TempDownloader:
242
+ def __init__(self, url: str, part: list[int], index: int, silent: bool = False):
243
+ self.url = url
244
+ self.part = part
245
+ self.index = index
246
+ self.silent = silent
247
+
248
+ async def get_bytes(self) -> dict[str, bytes]:
249
+ result_to_re = {}
250
+ this: bytes = bytes()
251
+ headers = {"Range": f"bytes={self.part[0]}-{self.part[1]}"}
252
+
253
+ async with aiohttp.ClientSession() as session:
254
+ async with session.get(self.url, headers=headers) as resp:
255
+ if not self.silent:
256
+ async for chunk in ProgressBar(resp.content.iter_chunked(1024 * 64),
257
+ total=self.part[1] - self.part[0],
258
+ num_per_time=1024 * 64,
259
+ desc=f"In thread {self.index}"
260
+ ):
261
+ this += chunk
262
+ else:
263
+ async for chunk in resp.content.iter_chunked(1024 * 64):
264
+ this += chunk
265
+
266
+ result_to_re[str(self.index)] = this
267
+ return result_to_re
268
+
269
+
270
+ class Downloader:
271
+ def __init__(self, url: str, path_to: str, threads: int = 1, silent: bool = False):
272
+ self.url = url
273
+ self.path = path_to
274
+ self.threads = threads
275
+ self.silent = silent
276
+
277
+ def check(self) -> bool:
278
+ if not isinstance(self.threads, int) or not self.threads >= 1:
279
+ return False
280
+
281
+ return True
282
+
283
+ def __get_file_size(self) -> int:
284
+ response = requests.head(self.url)
285
+ size = response.headers["Content-Length"]
286
+ return int(size)
287
+
288
+ def __get_parts(self) -> list[list[int]]:
289
+ size = self.__get_file_size()
290
+ step = size // self.threads
291
+ arr = list(range(0, size, step))
292
+ result: list = []
293
+ for i in range(len(arr) - 1):
294
+ s_pos, e_pos = arr[i], arr[i + 1] - 1
295
+ result.append([s_pos, e_pos])
296
+ result[-1][-1] = size - 1
297
+ return result
298
+
299
+ async def download(self):
300
+ if not self.check():
301
+ raise Exception
302
+ response = requests.get(self.url, stream=True, verify=False)
303
+ if response.status_code != 200:
304
+ raise ConnectionError
305
+
306
+ if self.threads == 1:
307
+ with open(self.path, "wb") as f:
308
+ if not self.silent:
309
+ for chunk in ProgressBar(response.iter_content(chunk_size=1024 * 64),
310
+ total=int(response.headers.get("Content-Length")),
311
+ num_per_time=1024 * 64
312
+ ):
313
+ if chunk:
314
+ f.write(chunk)
315
+ else:
316
+ for chunk in response.iter_content(chunk_size=1024 * 64):
317
+ if chunk:
318
+ f.write(chunk)
319
+ else:
320
+ with open(self.path, "wb"):
321
+ pass
322
+ with open(self.path, "rb+") as f:
323
+ parts = self.__get_parts()
324
+ result = {}
325
+ tasks = []
326
+ for i in parts:
327
+ _ = TempDownloader(url=self.url, part=i, index=parts.index(i), silent=self.silent)
328
+
329
+ tasks.append(asyncio.create_task(_.get_bytes()))
330
+
331
+ await asyncio.gather(*tasks)
332
+ for i in tasks:
333
+ result[list(i.result().keys())[0]] = i.result()[list(i.result().keys())[0]]
334
+ r: bytes = bytes()
335
+ for i in range(0, len(result)):
336
+ r += result[str(i)]
337
+ f.write(r)
@@ -18,7 +18,7 @@ class ModuleInfo:
18
18
 
19
19
 
20
20
  class Module:
21
- def __init__(self, actions, event):
21
+ def __init__(self, actions: Listener.Actions, event):
22
22
  self.actions = actions
23
23
  self.event = event
24
24
 
@@ -21,7 +21,10 @@ def segment_builder(sg_type: str, summary_tmp: str = None):
21
21
 
22
22
  if len(kwargs) > 0:
23
23
  for i in kwargs:
24
- arg[i] = kwargs[i]
24
+ try:
25
+ arg[i] = anns[i](kwargs[i])
26
+ except TypeError:
27
+ arg[i] = kwargs[i]
25
28
  new_arg = arg.copy()
26
29
 
27
30
  if len(anns) > len(arg):
@@ -30,7 +33,10 @@ def segment_builder(sg_type: str, summary_tmp: str = None):
30
33
  if i not in var.keys():
31
34
  new_arg[i] = None
32
35
  continue
33
- new_arg[i] = anns[i](var[i])
36
+ if not isinstance(var[i], anns[i]):
37
+ new_arg[i] = anns[i](var[i])
38
+ else:
39
+ new_arg[i] = var[i]
34
40
 
35
41
  for i in new_arg:
36
42
  setattr(self, i, new_arg[i])
@@ -40,7 +46,14 @@ def segment_builder(sg_type: str, summary_tmp: str = None):
40
46
  def to_json(self) -> dict:
41
47
  base = {"type": sg_type, "data": {}}
42
48
  for i in anns:
43
- base["data"][i] = anns[i](getattr(self, i))
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)
44
57
  return base
45
58
 
46
59
  cls.to_json = to_json
@@ -61,6 +74,7 @@ def segment_builder(sg_type: str, summary_tmp: str = None):
61
74
  text = text.replace(f"<{i}>", str(v))
62
75
 
63
76
  return text
77
+
64
78
  cls.__str__ = to_str if cls().__str__() == "__not_set__" else cls.__str__
65
79
 
66
80
  message_types[sg_type] = {
@@ -285,4 +299,3 @@ class Music(Base):
285
299
  url: str = None
286
300
  audio: str = None
287
301
  title: str = None
288
-
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hyper-bot
3
- Version: 0.74
3
+ Version: 0.75
4
4
  Summary: 稳定高效、易于开发的QQ Bot框架
5
5
  Home-page: https://github.com/HarcicYang/HypeR_Bot
6
6
  Author: Harcic
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hyper-bot
3
- Version: 0.74
3
+ Version: 0.75
4
4
  Summary: 稳定高效、易于开发的QQ Bot框架
5
5
  Home-page: https://github.com/HarcicYang/HypeR_Bot
6
6
  Author: Harcic
@@ -11,7 +11,6 @@ Hyper/Manager.py
11
11
  Hyper/ModuleClass.py
12
12
  Hyper/Network.py
13
13
  Hyper/Segments.py
14
- Hyper/WordSafety.py
15
14
  Hyper/Adapters/OneBot.py
16
15
  Hyper/Adapters/OneBotLib/Manager.py
17
16
  hyper_bot.egg-info/PKG-INFO
@@ -4,7 +4,7 @@ from setuptools import setup
4
4
 
5
5
  setup(
6
6
  name="hyper-bot",
7
- version="0.74",
7
+ version="0.75",
8
8
  description="稳定高效、易于开发的QQ Bot框架",
9
9
  author="Harcic",
10
10
  author_email="harcic@outlook.com",
@@ -1,167 +0,0 @@
1
- import json
2
- import os
3
- import shutil
4
- import traceback
5
-
6
- from Hyper import Logger
7
-
8
-
9
- class Cacher:
10
- def __init__(self, cache_time: int = 5):
11
- self.cache_time: int = cache_time
12
- self.cached: dict = {}
13
-
14
- def cache(self, func):
15
- def wrapper(*args, **kwargs):
16
- if kwargs.get("no_cache", False):
17
- kwargs.pop("no_cache")
18
- return func(*args, **kwargs)
19
- if str(kwargs) not in self.cached:
20
- ret = func(*args, **kwargs)
21
- self.cached[str(kwargs)] = ret
22
- if len(self.cached) >= self.cache_time:
23
- for i in self.cached:
24
- del self.cached[i]
25
- break
26
- return ret
27
- else:
28
- return self.cached[str(kwargs)]
29
-
30
- return wrapper
31
-
32
- def cache_async(self, func):
33
- async def wrapper(*args, **kwargs):
34
- if kwargs.get("no_cache", False):
35
- kwargs.pop("no_cache")
36
- return await func(*args, **kwargs)
37
- if str(kwargs) not in self.cached:
38
- ret = await func(*args, **kwargs)
39
- self.cached[str(kwargs)] = ret
40
- if len(self.cached) >= self.cache_time:
41
- for i in self.cached:
42
- del self.cached[i]
43
- break
44
- return ret
45
- else:
46
- return self.cached[str(kwargs)]
47
-
48
- return wrapper
49
-
50
-
51
- class ErrorHandler:
52
- def __init__(self, level=Logger.levels.ERROR, retries: int = 0):
53
- self.level = level
54
- self.logger = Logger.Logger()
55
- self.retries = retries
56
-
57
- def handle(self, func):
58
- def wrapper(*args, **kwargs):
59
- try:
60
- return func(*args, **kwargs)
61
- except:
62
- self.logger.log(f"出现错误:\n{str(traceback.format_exc())}", level=self.level)
63
-
64
- return wrapper
65
-
66
- def handle_async(self, func):
67
- async def wrapper(*args, **kwargs):
68
- try:
69
- return await func(*args, **kwargs)
70
- except:
71
- self.logger.log(f"出现错误:\n{str(traceback.format_exc())}", level=self.level)
72
-
73
- return wrapper
74
-
75
- def auto_retry(self, func):
76
- def wrapper(*args, **kwargs):
77
- retried = 0
78
- while retried < self.retries:
79
- retried += 1
80
- try:
81
- return func(*args, **kwargs)
82
- except Exception as e:
83
- self.logger.log(f"出现错误:\n{str(e)}, 正在重试...", level=self.level)
84
- self.logger.log(f"错误在{retried}次重试后失败", level=self.level)
85
-
86
- return wrapper
87
-
88
- def auto_retry_async(self, func):
89
- async def wrapper(*args, **kwargs):
90
- retried = 0
91
- while retried < self.retries:
92
- retried += 1
93
- try:
94
- return await func(*args, **kwargs)
95
- except Exception as e:
96
- self.logger.log(f"出现错误:\n{str(e)}, 正在重试...", level=self.level)
97
- self.logger.log(f"错误在{retried}次重试后失败", level=self.level)
98
-
99
- return wrapper
100
-
101
-
102
- class Random:
103
- def __init__(self, seed: int = None):
104
- self.seed = seed
105
-
106
- def random(self) -> int:
107
- self.seed = self.seed ** 2
108
- self.seed = int(str(self.seed)[:7])
109
- return int(str(self.seed)[1:5])
110
-
111
- def __call__(self) -> int:
112
- return self.random()
113
-
114
-
115
- class FileManager:
116
- @staticmethod
117
- def create(path: str) -> bool:
118
- try:
119
- with open(path, "w") as f:
120
- f.write("")
121
- except (FileExistsError | OSError | IOError):
122
- return False
123
-
124
- return True
125
-
126
- @staticmethod
127
- def exists(path: str) -> bool:
128
- try:
129
- with open(path, "r") as f:
130
- f.read()
131
- return True
132
- except FileNotFoundError:
133
- return False
134
-
135
- @staticmethod
136
- @Cacher(7).cache
137
- def read_as_text(path: str, encoding: str = "utf-8") -> str:
138
- with open(path, "r", encoding=encoding) as f:
139
- return f.read()
140
-
141
- @staticmethod
142
- @Cacher(7).cache
143
- def read_as_json(path: str, encoding: str = "utf-8") -> dict | list:
144
- with open(path, "r", encoding=encoding) as f:
145
- return json.load(f)
146
-
147
- @staticmethod
148
- @Cacher(7).cache
149
- def read_raw(path: str) -> bytes:
150
- with open(path, "rb") as f:
151
- return f.read()
152
-
153
- @staticmethod
154
- def delete(path: str) -> bool:
155
- try:
156
- os.remove(path)
157
- return True
158
- except (FileNotFoundError | OSError | IOError):
159
- return False
160
-
161
- @staticmethod
162
- def copy(path1: str, path2: str) -> bool:
163
- try:
164
- shutil.copy(path1, path2)
165
- return True
166
- except (FileNotFoundError | OSError | IOError):
167
- return False
@@ -1,40 +0,0 @@
1
- import logging
2
- from jieba import lcut, set_dictionary
3
-
4
- from Hyper import Logic
5
-
6
- logging.getLogger("jieba").setLevel(logging.ERROR)
7
- try:
8
- set_dictionary("./assets/jieba.dict.txt.small")
9
- except OSError:
10
- pass
11
-
12
-
13
- class Result:
14
- def __init__(self, message: str, result: bool):
15
- self.message = message
16
- self.result = result
17
-
18
-
19
- with open("assets/dict.txt", "r", encoding="utf-8") as f:
20
- words: list[dict[str, str]] = []
21
- word = f.read()
22
- word = word.split("\n")
23
- for i in word:
24
- temp = i.split(" ")
25
- words.append({"word": temp[0], "type": temp[1]})
26
-
27
- del i
28
-
29
-
30
- @Logic.Cacher().cache
31
- def check(text: str) -> Result:
32
- texts = lcut(text)
33
- for j in words:
34
- if j["word"] in texts:
35
- ret = Result(f"检测到类型为{j['type']}的敏感用词", False)
36
- del j
37
- return ret
38
- del j
39
- ret = Result("未检出敏感词", True)
40
- return ret
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes