nonebot-plugin-l4d2-server 0.5.1__py3-none-any.whl → 0.5.3__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.
Files changed (63) hide show
  1. LICENSE +674 -674
  2. README.md +373 -359
  3. nonebot_plugin_l4d2_server/__init__.py +13 -13
  4. nonebot_plugin_l4d2_server/command.py +232 -232
  5. nonebot_plugin_l4d2_server/config.py +209 -210
  6. nonebot_plugin_l4d2_server/data/L4D2/image/template/anne.html +60 -60
  7. nonebot_plugin_l4d2_server/data/L4D2/image/template/fingerprint.svg +15 -15
  8. nonebot_plugin_l4d2_server/data/L4D2/image/template/help.html +233 -233
  9. nonebot_plugin_l4d2_server/data/L4D2/image/template/help_dack.html +231 -231
  10. nonebot_plugin_l4d2_server/data/L4D2/image/template/ip.html +48 -48
  11. nonebot_plugin_l4d2_server/data/L4D2/image/template/l.svg +9 -9
  12. nonebot_plugin_l4d2_server/l4d2_anne/__init__.py +251 -251
  13. nonebot_plugin_l4d2_server/l4d2_anne/analysis.py +51 -51
  14. nonebot_plugin_l4d2_server/l4d2_anne/anne_telecom.py +75 -75
  15. nonebot_plugin_l4d2_server/l4d2_anne/server.py +65 -65
  16. nonebot_plugin_l4d2_server/l4d2_anne/startand.py +17 -17
  17. nonebot_plugin_l4d2_server/l4d2_data/__init__.py +91 -91
  18. nonebot_plugin_l4d2_server/l4d2_data/config.py +17 -17
  19. nonebot_plugin_l4d2_server/l4d2_data/database.py +0 -0
  20. nonebot_plugin_l4d2_server/l4d2_data/players.py +87 -87
  21. nonebot_plugin_l4d2_server/l4d2_data/serverip.py +32 -32
  22. nonebot_plugin_l4d2_server/l4d2_file/__init__.py +122 -122
  23. nonebot_plugin_l4d2_server/l4d2_file/ayromote.py +56 -56
  24. nonebot_plugin_l4d2_server/l4d2_file/remote.py +63 -63
  25. nonebot_plugin_l4d2_server/l4d2_image/__init__.py +103 -103
  26. nonebot_plugin_l4d2_server/l4d2_image/download.py +101 -101
  27. nonebot_plugin_l4d2_server/l4d2_image/htmlimg.py +32 -32
  28. nonebot_plugin_l4d2_server/l4d2_image/image.py +292 -0
  29. nonebot_plugin_l4d2_server/l4d2_image/send_image_tool.py +32 -32
  30. nonebot_plugin_l4d2_server/l4d2_image/steam.py +83 -83
  31. nonebot_plugin_l4d2_server/l4d2_image/vtfs.py +40 -40
  32. nonebot_plugin_l4d2_server/l4d2_queries/__init__.py +114 -114
  33. nonebot_plugin_l4d2_server/l4d2_queries/api.py +43 -43
  34. nonebot_plugin_l4d2_server/l4d2_queries/ohter.py +35 -35
  35. nonebot_plugin_l4d2_server/l4d2_queries/qqgroup.py +288 -288
  36. nonebot_plugin_l4d2_server/l4d2_server/__init__.py +61 -61
  37. nonebot_plugin_l4d2_server/l4d2_server/index.py +0 -0
  38. nonebot_plugin_l4d2_server/l4d2_server/rcon.py +28 -28
  39. nonebot_plugin_l4d2_server/l4d2_server/workshop.py +50 -50
  40. nonebot_plugin_l4d2_server/l4d2_update/__init__.py +143 -0
  41. nonebot_plugin_l4d2_server/l4d2_update/draw_update_log.py +41 -0
  42. nonebot_plugin_l4d2_server/l4d2_update/restart.py +67 -0
  43. nonebot_plugin_l4d2_server/l4d2_update/texture2d/art.png +0 -0
  44. nonebot_plugin_l4d2_server/l4d2_update/texture2d/bento.png +0 -0
  45. nonebot_plugin_l4d2_server/l4d2_update/texture2d/bug.png +0 -0
  46. nonebot_plugin_l4d2_server/l4d2_update/texture2d/feat.png +0 -0
  47. nonebot_plugin_l4d2_server/l4d2_update/texture2d/log_title.png +0 -0
  48. nonebot_plugin_l4d2_server/l4d2_update/texture2d/other.png +0 -0
  49. nonebot_plugin_l4d2_server/l4d2_update/texture2d/zap.png +0 -0
  50. nonebot_plugin_l4d2_server/l4d2_update/update.py +65 -0
  51. nonebot_plugin_l4d2_server/l4d2_web/web.py +234 -252
  52. nonebot_plugin_l4d2_server/l4d2_web/webUI.py +241 -245
  53. nonebot_plugin_l4d2_server/message.py +58 -58
  54. nonebot_plugin_l4d2_server/rule.py +15 -0
  55. nonebot_plugin_l4d2_server/seach.py +33 -33
  56. nonebot_plugin_l4d2_server/txt_to_img.py +64 -64
  57. nonebot_plugin_l4d2_server/utils.py +297 -272
  58. {nonebot_plugin_l4d2_server-0.5.1.dist-info → nonebot_plugin_l4d2_server-0.5.3.dist-info}/LICENSE +674 -674
  59. {nonebot_plugin_l4d2_server-0.5.1.dist-info → nonebot_plugin_l4d2_server-0.5.3.dist-info}/METADATA +19 -4
  60. nonebot_plugin_l4d2_server-0.5.3.dist-info/RECORD +68 -0
  61. {nonebot_plugin_l4d2_server-0.5.1.dist-info → nonebot_plugin_l4d2_server-0.5.3.dist-info}/WHEEL +1 -1
  62. nonebot_plugin_l4d2_server/chrome.py +0 -45
  63. nonebot_plugin_l4d2_server-0.5.1.dist-info/RECORD +0 -54
@@ -0,0 +1,292 @@
1
+ from io import BytesIO
2
+ from pathlib import Path
3
+ from base64 import b64encode
4
+ from typing import Union, overload
5
+ from typing import Union,Tuple,Optional
6
+ import math
7
+ import random
8
+
9
+ import aiofiles
10
+ from PIL import Image
11
+ from httpx import get
12
+ import sys
13
+ from pathlib import Path
14
+
15
+ MAIN_PATH = Path() / 'data' / 'GenshinUID'
16
+ sys.path.append(str(MAIN_PATH))
17
+ CONFIG_PATH = MAIN_PATH / 'config.json'
18
+ RESOURCE_PATH = MAIN_PATH / 'resource'
19
+ WIKI_PATH = MAIN_PATH / 'wiki'
20
+ CU_BG_PATH = MAIN_PATH / 'bg'
21
+ CU_CHBG_PATH = MAIN_PATH / 'chbg'
22
+ WEAPON_PATH = RESOURCE_PATH / 'weapon'
23
+ GACHA_IMG_PATH = RESOURCE_PATH / 'gacha_img'
24
+ CHAR_PATH = RESOURCE_PATH / 'chars'
25
+ CHAR_STAND_PATH = RESOURCE_PATH / 'char_stand'
26
+ CHAR_SIDE_PATH = RESOURCE_PATH / 'char_side'
27
+ CHAR_NAMECARD_PATH = RESOURCE_PATH / 'char_namecard'
28
+ REL_PATH = RESOURCE_PATH / 'reliquaries'
29
+ ICON_PATH = RESOURCE_PATH / 'icon'
30
+ TEMP_PATH = RESOURCE_PATH / 'temp'
31
+ CARD_PATH = RESOURCE_PATH / 'card'
32
+ GUIDE_PATH = WIKI_PATH / 'guide'
33
+ TEXT2D_PATH = Path(__file__).parents[2] / 'resource' / 'texture2d'
34
+
35
+ PLAYER_PATH = MAIN_PATH / 'players'
36
+
37
+
38
+ TEXT2D_PATH = Path(__file__).parents[2] / 'resource' / 'texture2d'
39
+ FETTER_PATH = TEXT2D_PATH / 'fetter'
40
+ TALENT_PATH = TEXT2D_PATH / 'talent'
41
+ WEAPON_BG_PATH = TEXT2D_PATH / 'weapon'
42
+ WEAPON_AFFIX_PATH = TEXT2D_PATH / 'weapon_affix'
43
+ LEVEL_PATH = TEXT2D_PATH / 'level'
44
+
45
+ BG_PATH = Path(__file__).parent / 'bg'
46
+ TEXT_PATH = Path(__file__).parent / 'texture2d'
47
+ ring_pic = Image.open(TEXT_PATH / 'ring.png')
48
+ mask_pic = Image.open(TEXT_PATH / 'mask.png')
49
+ NM_BG_PATH = BG_PATH / 'nm_bg'
50
+ SP_BG_PATH = BG_PATH / 'sp_bg'@overload
51
+
52
+ if list(CU_BG_PATH.iterdir()) != []:
53
+ bg_path = CU_BG_PATH
54
+ else:
55
+ bg_path = NM_BG_PATH
56
+
57
+ async def convert_img(img: Image.Image, is_base64: bool = False) -> bytes:
58
+ ...
59
+
60
+
61
+ @overload
62
+ async def convert_img(img: Image.Image, is_base64: bool = True) -> str:
63
+ ...
64
+
65
+
66
+ @overload
67
+ async def convert_img(img: bytes, is_base64: bool = False) -> str:
68
+ ...
69
+
70
+
71
+ @overload
72
+ async def convert_img(img: Path, is_base64: bool = False) -> str:
73
+ ...
74
+
75
+
76
+ async def convert_img(
77
+ img: Union[Image.Image, str, Path, bytes], is_base64: bool = False
78
+ ):
79
+ """
80
+ :说明:
81
+ 将PIL.Image对象转换为bytes或者base64格式。
82
+ :参数:
83
+ * img (Image): 图片。
84
+ * is_base64 (bool): 是否转换为base64格式, 不填默认转为bytes。
85
+ :返回:
86
+ * res: bytes对象或base64编码图片。
87
+ """
88
+ if isinstance(img, Image.Image):
89
+ img = img.convert('RGB')
90
+ result_buffer = BytesIO()
91
+ img.save(result_buffer, format='PNG', quality=80, subsampling=0)
92
+ res = result_buffer.getvalue()
93
+ if is_base64:
94
+ res = 'base64://' + b64encode(res).decode()
95
+ return res
96
+ elif isinstance(img, bytes):
97
+ pass
98
+ else:
99
+ async with aiofiles.open(img, 'rb') as fp:
100
+ img = await fp.read()
101
+ return f'[CQ:image,file=base64://{b64encode(img).decode()}]'
102
+
103
+
104
+ async def get_color_bg(
105
+ based_w: int, based_h: int, bg: Optional[str] = None
106
+ ) -> Image.Image:
107
+ image = ''
108
+ if bg:
109
+ path = SP_BG_PATH / f'{bg}.jpg'
110
+ if path.exists():
111
+ image = Image.open(path)
112
+ CI_img = CustomizeImage(image, based_w, based_h)
113
+ img = CI_img.bg_img
114
+ color = CI_img.bg_color
115
+ color_mask = Image.new('RGBA', (based_w, based_h), color)
116
+ enka_mask = Image.open(TEXT2D_PATH / 'mask.png').resize((based_w, based_h))
117
+ img.paste(color_mask, (0, 0), enka_mask)
118
+ return img
119
+
120
+
121
+
122
+ class CustomizeImage:
123
+ def __init__(
124
+ self, image: Union[str, Image.Image], based_w: int, based_h: int
125
+ ) -> None:
126
+
127
+ self.bg_img = self.get_image(image, based_w, based_h)
128
+ self.bg_color = self.get_bg_color(self.bg_img, is_light=True)
129
+ self.text_color = self.get_text_color(self.bg_color)
130
+ self.highlight_color = self.get_highlight_color(self.bg_color)
131
+ self.char_color = self.get_char_color(self.bg_color)
132
+ self.bg_detail_color = self.get_bg_detail_color(self.bg_color)
133
+ self.char_high_color = self.get_char_high_color(self.bg_color)
134
+
135
+ @staticmethod
136
+ def get_image(
137
+ image: Union[str, Image.Image], based_w: int, based_h: int
138
+ ) -> Image.Image:
139
+ # 获取背景图片
140
+ if isinstance(image, Image.Image):
141
+ edit_bg = image
142
+ elif image:
143
+ edit_bg = Image.open(BytesIO(get(image).content)).convert('RGBA')
144
+ else:
145
+ path = random.choice(list(bg_path.iterdir()))
146
+ edit_bg = Image.open(path).convert('RGBA')
147
+
148
+ # 确定图片的长宽
149
+ bg_img = crop_center_img(edit_bg, based_w, based_h)
150
+ return bg_img
151
+
152
+ @staticmethod
153
+ def get_dominant_color(pil_img: Image.Image) -> Tuple[int, int, int]:
154
+ img = pil_img.copy()
155
+ img = img.convert("RGBA")
156
+ img = img.resize((1, 1), resample=0)
157
+ dominant_color = img.getpixel((0, 0))
158
+ return dominant_color
159
+
160
+ @staticmethod
161
+ def get_bg_color(
162
+ edit_bg: Image.Image, is_light: Optional[bool] = False
163
+ ) -> Tuple[int, int, int]:
164
+ # 获取背景主色
165
+ color = 8
166
+ q = edit_bg.quantize(colors=color, method=2)
167
+ bg_color = (0, 0, 0)
168
+ if is_light:
169
+ based_light = 195
170
+ else:
171
+ based_light = 120
172
+ temp = 9999
173
+ for i in range(color):
174
+ bg = tuple(
175
+ q.getpalette()[ # type:ignore
176
+ i * 3 : (i * 3) + 3 # noqa:E203
177
+ ]
178
+ )
179
+ light_value = bg[0] * 0.3 + bg[1] * 0.6 + bg[2] * 0.1
180
+ if abs(light_value - based_light) < temp:
181
+ bg_color = bg
182
+ temp = abs(light_value - based_light)
183
+ return bg_color
184
+
185
+ @staticmethod
186
+ def get_text_color(bg_color: Tuple[int, int, int]) -> Tuple[int, int, int]:
187
+ # 通过背景主色(bg_color)确定文字主色
188
+ r = 125
189
+ if max(*bg_color) > 255 - r:
190
+ r *= -1
191
+ text_color = (
192
+ math.floor(bg_color[0] + r if bg_color[0] + r <= 255 else 255),
193
+ math.floor(bg_color[1] + r if bg_color[1] + r <= 255 else 255),
194
+ math.floor(bg_color[2] + r if bg_color[2] + r <= 255 else 255),
195
+ )
196
+ return text_color
197
+
198
+ @staticmethod
199
+ def get_char_color(bg_color: Tuple[int, int, int]) -> Tuple[int, int, int]:
200
+ r = 140
201
+ if max(*bg_color) > 255 - r:
202
+ r *= -1
203
+ char_color = (
204
+ math.floor(bg_color[0] + 5 if bg_color[0] + r <= 255 else 255),
205
+ math.floor(bg_color[1] + 5 if bg_color[1] + r <= 255 else 255),
206
+ math.floor(bg_color[2] + 5 if bg_color[2] + r <= 255 else 255),
207
+ )
208
+ return char_color
209
+
210
+ @staticmethod
211
+ def get_char_high_color(
212
+ bg_color: Tuple[int, int, int]
213
+ ) -> Tuple[int, int, int]:
214
+ r = 140
215
+ d = 20
216
+ if max(*bg_color) > 255 - r:
217
+ r *= -1
218
+ char_color = (
219
+ math.floor(bg_color[0] + d if bg_color[0] + r <= 255 else 255),
220
+ math.floor(bg_color[1] + d if bg_color[1] + r <= 255 else 255),
221
+ math.floor(bg_color[2] + d if bg_color[2] + r <= 255 else 255),
222
+ )
223
+ return char_color
224
+
225
+ @staticmethod
226
+ def get_bg_detail_color(
227
+ bg_color: Tuple[int, int, int]
228
+ ) -> Tuple[int, int, int]:
229
+ r = 140
230
+ if max(*bg_color) > 255 - r:
231
+ r *= -1
232
+ bg_detail_color = (
233
+ math.floor(bg_color[0] - 20 if bg_color[0] + r <= 255 else 255),
234
+ math.floor(bg_color[1] - 20 if bg_color[1] + r <= 255 else 255),
235
+ math.floor(bg_color[2] - 20 if bg_color[2] + r <= 255 else 255),
236
+ )
237
+ return bg_detail_color
238
+
239
+ @staticmethod
240
+ def get_highlight_color(
241
+ color: Tuple[int, int, int]
242
+ ) -> Tuple[int, int, int]:
243
+ red_color = color[0]
244
+ green_color = color[1]
245
+ blue_color = color[2]
246
+
247
+ highlight_color = {
248
+ 'red': red_color - 127 if red_color > 127 else 127,
249
+ 'green': green_color - 127 if green_color > 127 else 127,
250
+ 'blue': blue_color - 127 if blue_color > 127 else 127,
251
+ }
252
+
253
+ max_color = max(highlight_color.values())
254
+
255
+ name = ''
256
+ for _highlight_color in highlight_color:
257
+ if highlight_color[_highlight_color] == max_color:
258
+ name = str(_highlight_color)
259
+
260
+ if name == 'red':
261
+ return red_color, highlight_color['green'], highlight_color['blue']
262
+ elif name == 'green':
263
+ return highlight_color['red'], green_color, highlight_color['blue']
264
+ elif name == 'blue':
265
+ return highlight_color['red'], highlight_color['green'], blue_color
266
+ else:
267
+ return 0, 0, 0 # Error
268
+
269
+
270
+ def crop_center_img(
271
+ img: Image.Image, based_w: int, based_h: int
272
+ ) -> Image.Image:
273
+ # 确定图片的长宽
274
+ based_scale = '%.3f' % (based_w / based_h)
275
+ w, h = img.size
276
+ scale_f = '%.3f' % (w / h)
277
+ new_w = math.ceil(based_h * float(scale_f))
278
+ new_h = math.ceil(based_w / float(scale_f))
279
+ if scale_f > based_scale:
280
+ resize_img = img.resize((new_w, based_h), Image.ANTIALIAS)
281
+ x1 = int(new_w / 2 - based_w / 2)
282
+ y1 = 0
283
+ x2 = int(new_w / 2 + based_w / 2)
284
+ y2 = based_h
285
+ else:
286
+ resize_img = img.resize((based_w, new_h), Image.ANTIALIAS)
287
+ x1 = 0
288
+ y1 = int(new_h / 2 - based_h / 2)
289
+ x2 = based_w
290
+ y2 = int(new_h / 2 + based_h / 2)
291
+ crop_img = resize_img.crop((x1, y1, x2, y2))
292
+ return crop_img
@@ -1,32 +1,32 @@
1
- from io import BytesIO
2
- from pathlib import Path
3
- from typing import Union
4
- from base64 import b64encode
5
-
6
- from PIL import Image
7
-
8
-
9
- async def convert_img(
10
- img: Union[Image.Image, str, Path, bytes], is_base64: bool = False
11
- ):
12
- """
13
- :说明:
14
- 将PIL.Image对象转换为bytes或者base64格式。
15
- :参数:
16
- * img (Image): 图片。
17
- * is_base64 (bool): 是否转换为base64格式, 不填默认转为bytes。
18
- :返回:
19
- * res: bytes对象或base64编码图片。
20
- """
21
- if isinstance(img, Image.Image):
22
- img = img.convert('RGBA')
23
- result_buffer = BytesIO()
24
- img.save(result_buffer, format='PNG', quality=80, subsampling=0)
25
- res = result_buffer.getvalue()
26
- if is_base64:
27
- res = b64encode(res).decode()
28
- return res
29
- elif isinstance(img, bytes):
30
- return b64encode(img).decode()
31
- else:
32
- return f'[CQ:image,file=file:///{str(img)}]'
1
+ from io import BytesIO
2
+ from pathlib import Path
3
+ from typing import Union
4
+ from base64 import b64encode
5
+
6
+ from PIL import Image
7
+
8
+
9
+ async def convert_img(
10
+ img: Union[Image.Image, str, Path, bytes], is_base64: bool = False
11
+ ):
12
+ """
13
+ :说明:
14
+ 将PIL.Image对象转换为bytes或者base64格式。
15
+ :参数:
16
+ * img (Image): 图片。
17
+ * is_base64 (bool): 是否转换为base64格式, 不填默认转为bytes。
18
+ :返回:
19
+ * res: bytes对象或base64编码图片。
20
+ """
21
+ if isinstance(img, Image.Image):
22
+ img = img.convert('RGBA')
23
+ result_buffer = BytesIO()
24
+ img.save(result_buffer, format='PNG', quality=80, subsampling=0)
25
+ res = result_buffer.getvalue()
26
+ if is_base64:
27
+ res = b64encode(res).decode()
28
+ return res
29
+ elif isinstance(img, bytes):
30
+ return b64encode(img).decode()
31
+ else:
32
+ return f'[CQ:image,file=file:///{str(img)}]'
@@ -1,83 +1,83 @@
1
- # from PIL import Image
2
- import httpx
3
- import aiohttp
4
- # from bs4 import BeautifulSoup
5
- from urllib.parse import unquote
6
-
7
-
8
- # async def web_player(url) -> Image :
9
- # """steam个人资料获取头像"""
10
- # data = BeautifulSoup(await url_for_byte(url), 'html.parser')
11
- # print(data)
12
- # head = data.find("div", class_="playerAvatarAutoSizeInner")
13
- # img_elements = head.find_all("img")
14
- # if len(img_elements)== 1:
15
- # for img_element in img_elements:
16
- # head = await url_for_byte(img_element["src"])
17
- # im = Image.open(io.BytesIO(head)).resize((225, 225)).convert("RGBA")
18
- # if len(img_elements) == 2:
19
- # head,headd = img_elements
20
- # head = await url_for_byte(img_element["src"])
21
- # head = await url_for_byte(img_element["src"])
22
- # # 下面是边框,不一定有
23
- # try:
24
- # headd = data.select("html.responsive body.flat_page.profile_page.has_profile_background.GhostTheme.responsive_page div.responsive_page_frame.with_header div.responsive_page_content div#responsive_page_template_content.responsive_page_template_content div.no_header.profile_page.has_profile_background div.profile_header_bg div.profile_header_bg_texture div.profile_header div.profile_header_content div.playerAvatar.profile_header_size.in-game div.playerAvatarAutoSizeInner div.profile_avatar_frame img")
25
- # im2 = Image.open(io.BytesIO(headd)).resize((185, 185)).convert("RGBA")
26
- # r, g, b, a2 = im2.split()
27
- # # im.paste(im2,(20,20),mask=a2)
28
- # except IndexError:
29
- # pass
30
- # return im
31
-
32
- # async def url_for_byte(url):
33
- # """所有代理_url终将绳之以法"""
34
- # if not l4_proxies:
35
- # print("代理不存在")
36
- # data = await url_to_byte(url)
37
- # headers = {
38
- # 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0'
39
- # }
40
- # data = httpx.get(url,headers=headers,proxies=l4_proxies,timeout=60,verify=False).content
41
- # return data
42
- async def url_to_byte(url:str,filename:str =''):
43
- """获取URL数据的字节流"""
44
- headers = {
45
- 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0'
46
- }
47
- async with aiohttp.ClientSession() as session:
48
- async with session.get(url, headers=headers, timeout=600) as response:
49
- if response.status == 200:
50
- return await response.read()
51
- else:
52
- return None
53
-
54
- async def url_to_byte_name(url:str,filename:str =''):
55
- """获取URL数据的字节流"""
56
- headers = {
57
- 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0'
58
- }
59
- if filename == "htp":
60
- response = httpx.get(url,headers=headers,timeout=600)
61
- content_disposition:str = response.headers.get("Content-Disposition")
62
- if not content_disposition:
63
- return None
64
- elif "''" in content_disposition:
65
- file_name = content_disposition.split("''")[-1]
66
- else:
67
- file_name = content_disposition
68
- file_name = unquote(file_name)
69
- return [response.read(),file_name]
70
- else:
71
- async with aiohttp.ClientSession() as session:
72
- async with session.get(url, headers=headers, timeout=600) as response:
73
- content_disposition:str = response.headers.get("Content-Disposition")
74
- if "''" in content_disposition:
75
- file_name = content_disposition.split("''")[-1]
76
- else:
77
- file_name = content_disposition
78
- file_name = unquote(file_name)
79
- if response.status == 200:
80
- return [await response.read(),file_name]
81
- else:
82
- return None
83
-
1
+ # from PIL import Image
2
+ import httpx
3
+ import aiohttp
4
+ # from bs4 import BeautifulSoup
5
+ from urllib.parse import unquote
6
+
7
+
8
+ # async def web_player(url) -> Image :
9
+ # """steam个人资料获取头像"""
10
+ # data = BeautifulSoup(await url_for_byte(url), 'html.parser')
11
+ # print(data)
12
+ # head = data.find("div", class_="playerAvatarAutoSizeInner")
13
+ # img_elements = head.find_all("img")
14
+ # if len(img_elements)== 1:
15
+ # for img_element in img_elements:
16
+ # head = await url_for_byte(img_element["src"])
17
+ # im = Image.open(io.BytesIO(head)).resize((225, 225)).convert("RGBA")
18
+ # if len(img_elements) == 2:
19
+ # head,headd = img_elements
20
+ # head = await url_for_byte(img_element["src"])
21
+ # head = await url_for_byte(img_element["src"])
22
+ # # 下面是边框,不一定有
23
+ # try:
24
+ # headd = data.select("html.responsive body.flat_page.profile_page.has_profile_background.GhostTheme.responsive_page div.responsive_page_frame.with_header div.responsive_page_content div#responsive_page_template_content.responsive_page_template_content div.no_header.profile_page.has_profile_background div.profile_header_bg div.profile_header_bg_texture div.profile_header div.profile_header_content div.playerAvatar.profile_header_size.in-game div.playerAvatarAutoSizeInner div.profile_avatar_frame img")
25
+ # im2 = Image.open(io.BytesIO(headd)).resize((185, 185)).convert("RGBA")
26
+ # r, g, b, a2 = im2.split()
27
+ # # im.paste(im2,(20,20),mask=a2)
28
+ # except IndexError:
29
+ # pass
30
+ # return im
31
+
32
+ # async def url_for_byte(url):
33
+ # """所有代理_url终将绳之以法"""
34
+ # if not l4_proxies:
35
+ # print("代理不存在")
36
+ # data = await url_to_byte(url)
37
+ # headers = {
38
+ # 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0'
39
+ # }
40
+ # data = httpx.get(url,headers=headers,proxies=l4_proxies,timeout=60,verify=False).content
41
+ # return data
42
+ async def url_to_byte(url:str,filename:str =''):
43
+ """获取URL数据的字节流"""
44
+ headers = {
45
+ 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0'
46
+ }
47
+ async with aiohttp.ClientSession() as session:
48
+ async with session.get(url, headers=headers, timeout=600) as response:
49
+ if response.status == 200:
50
+ return await response.read()
51
+ else:
52
+ return None
53
+
54
+ async def url_to_byte_name(url:str,filename:str =''):
55
+ """获取URL数据的字节流"""
56
+ headers = {
57
+ 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0'
58
+ }
59
+ if filename == "htp":
60
+ response = httpx.get(url,headers=headers,timeout=600)
61
+ content_disposition:str = response.headers.get("Content-Disposition")
62
+ if not content_disposition:
63
+ return None
64
+ elif "''" in content_disposition:
65
+ file_name = content_disposition.split("''")[-1]
66
+ else:
67
+ file_name = content_disposition
68
+ file_name = unquote(file_name)
69
+ return [response.read(),file_name]
70
+ else:
71
+ async with aiohttp.ClientSession() as session:
72
+ async with session.get(url, headers=headers, timeout=600) as response:
73
+ content_disposition:str = response.headers.get("Content-Disposition")
74
+ if "''" in content_disposition:
75
+ file_name = content_disposition.split("''")[-1]
76
+ else:
77
+ file_name = content_disposition
78
+ file_name = unquote(file_name)
79
+ if response.status == 200:
80
+ return [await response.read(),file_name]
81
+ else:
82
+ return None
83
+
@@ -1,40 +1,40 @@
1
-
2
- from PIL import Image
3
- from nonebot.log import logger
4
- from io import BytesIO
5
- # import sys
6
- # sys.modules["srctools._cy_vtf_readwrite"] = None
7
- from srctools.vtf import VTF, ImageFormats
8
-
9
- async def img_to_vtf(pic_byte:bytes,tag) -> BytesIO:
10
- pic = BytesIO(pic_byte)
11
- pic = Image.open(pic).convert('RGBA')
12
- vtf_io = BytesIO()
13
- vtf_ = VTF(1024, 1024, fmt = ImageFormats.DXT5,thumb_fmt = ImageFormats.DXT1,version=(7,2))
14
- if tag == '覆盖':
15
- logger.info(tag)
16
- img2 = Image.new('RGBA',(1024, 1024), (255, 255, 255,0))
17
- r, g, b, a = pic.split()
18
- img2.paste(pic,mask=a)
19
- pic = pic.resize((1024,1024))
20
- elif tag == '填充':
21
- w, h = pic.size
22
- if w > h:
23
- ratio = 1024/w
24
- new_width = 1024
25
- new_height = int(h * ratio)
26
- else:
27
- ratio = 1024/h
28
- new_height = 1024
29
- new_width = int(w * ratio)
30
- pic = pic.resize((new_width, new_height), Image.ANTIALIAS)
31
- background = Image.new('RGBA', (1024, 1024), (255, 255, 255, 0))
32
- background.paste(pic, ((1024-new_width)//2, (1024-new_height)//2))
33
- pic = background
34
- else:
35
- logger.info('拉伸')
36
- pic = pic.resize((1024,1024))
37
- largest_frame = vtf_.get()
38
- largest_frame.copy_from(pic.tobytes(), ImageFormats.RGBA8888)
39
- vtf_.save(vtf_io,version=(7,2))
40
- return vtf_io
1
+
2
+ from PIL import Image
3
+ from nonebot.log import logger
4
+ from io import BytesIO
5
+ # import sys
6
+ # sys.modules["srctools._cy_vtf_readwrite"] = None
7
+ from srctools.vtf import VTF, ImageFormats
8
+
9
+ async def img_to_vtf(pic_byte:bytes,tag) -> BytesIO:
10
+ pic = BytesIO(pic_byte)
11
+ pic = Image.open(pic).convert('RGBA')
12
+ vtf_io = BytesIO()
13
+ vtf_ = VTF(1024, 1024, fmt = ImageFormats.DXT5,thumb_fmt = ImageFormats.DXT1,version=(7,2))
14
+ if tag == '覆盖':
15
+ logger.info(tag)
16
+ img2 = Image.new('RGBA',(1024, 1024), (255, 255, 255,0))
17
+ r, g, b, a = pic.split()
18
+ img2.paste(pic,mask=a)
19
+ pic = pic.resize((1024,1024))
20
+ elif tag == '填充':
21
+ w, h = pic.size
22
+ if w > h:
23
+ ratio = 1024/w
24
+ new_width = 1024
25
+ new_height = int(h * ratio)
26
+ else:
27
+ ratio = 1024/h
28
+ new_height = 1024
29
+ new_width = int(w * ratio)
30
+ pic = pic.resize((new_width, new_height), Image.ANTIALIAS)
31
+ background = Image.new('RGBA', (1024, 1024), (255, 255, 255, 0))
32
+ background.paste(pic, ((1024-new_width)//2, (1024-new_height)//2))
33
+ pic = background
34
+ else:
35
+ logger.info('拉伸')
36
+ pic = pic.resize((1024,1024))
37
+ largest_frame = vtf_.get()
38
+ largest_frame.copy_from(pic.tobytes(), ImageFormats.RGBA8888)
39
+ vtf_.save(vtf_io,version=(7,2))
40
+ return vtf_io