forked from QingMuCat/nonebot_plugin_xiuxian_2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.py
320 lines (276 loc) · 9.36 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
from .xiuxian2_handle import XiuxianDateManage
from nonebot.adapters.onebot.v11 import (
Bot,
MessageEvent,
GroupMessageEvent
)
import json
import random
import math
import datetime
import unicodedata
from nonebot.params import Depends
from base64 import b64encode
from io import BytesIO
from PIL import Image, ImageDraw, ImageFont
from wcwidth import wcwidth
import os
from .data_source import jsondata
from pathlib import Path
sql_message = XiuxianDateManage() # sql类
boss_img_path = Path() / "data" / "xiuxian" / "boss_img"
class MyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
return obj.strftime("%Y-%m-%d %H:%M:%S")
if isinstance(obj, bytes):
return str(obj, encoding='utf-8')
if isinstance(obj, int):
return int(obj)
elif isinstance(obj, float):
return float(obj)
else:
return super(MyEncoder, self).default(obj)
def check_user_type(user_id, need_type):
"""
:说明: `check_user_type`
> 匹配用户状态,返回是否状态一致
:返回参数:
* `isType: 是否一致
* `msg: 消息体
"""
isType = False
msg = ''
user_cd_message = sql_message.get_user_cd(user_id)
if user_cd_message is None:
user_type = 0
else:
user_type = user_cd_message.type
if user_type == need_type: # 状态一致
isType = True
else:
if user_type == 1:
msg = "道友现在在闭关呢,小心走火入魔!"
elif user_type == 2:
msg = "道友现在在做悬赏令呢,小心走火入魔!"
elif user_type == 3:
msg = "道友现在正在秘境中,分身乏术!"
elif user_type == 0:
msg = "道友现在什么都没干呢~"
return isType, msg
def check_user(event: GroupMessageEvent):
"""
判断用户信息是否存在
:返回参数:
* `isUser: 是否存在
* `user_info: 用户
* `msg: 消息体
"""
isUser = False
user_id = event.get_user_id()
user_info = sql_message.get_user_message(user_id)
if user_info is None:
msg = "修仙界没有道友的信息,请输入【我要修仙】加入!"
else:
isUser = True
msg = ''
return isUser, user_info, msg
async def send_forward_msg(
bot: Bot,
event: MessageEvent,
name: str, # 转发的用户名称
uin: str, # qq
msgs: list # 转发内容
):
"""合并消息转发"""
def to_json(msg):
return {"type": "node", "data": {"name": name, "uin": uin, "content": msg}}
messages = [to_json(msg) for msg in msgs]
if isinstance(event, GroupMessageEvent):
await bot.call_api(
"send_group_forward_msg", group_id=event.group_id, messages=messages
)
else:
await bot.call_api(
"send_private_forward_msg", user_id=event.user_id, messages=messages
)
async def send_forward_msg_list(
bot: Bot,
event: MessageEvent,
messages: list, # 格式[*dict] 例[*{"type": "node", "data": {"name": name, "uin": uin, "content": msg}}]
):
"""
合并消息转发
区分人
"""
if isinstance(event, GroupMessageEvent):
await bot.call_api(
"send_group_forward_msg", group_id=event.group_id, messages=messages
)
else:
await bot.call_api(
"send_private_forward_msg", user_id=event.user_id, messages=messages
)
class Txt2Img:
"""文字转图片"""
def __init__(self, size=32):
self.font = str(jsondata.FONT_FILE)
self.font_size = int(size)
self.use_font = ImageFont.truetype(font=self.font, size=self.font_size)
self.upper_size = 30
self.below_size = 30
self.left_size = 40
self.right_size = 55
self.padding = 12
self.img_width = 780
self.black_clor = (255, 255, 255)
self.line_num = 0
def prepare(self, text, scale):
text = unicodedata.normalize('NFKC', text)
if scale:
max_text_len = self.img_width - self.left_size -self.right_size
else:
max_text_len = 1080 - self.left_size -self.right_size
use_font = self.use_font
line_num = self.line_num
text_len = 0
text_new = ""
for x in text:
text_new += x
text_len += use_font.getlength(x)
if x == '\n':
text_len = 0
if text_len >= max_text_len:
text_len = 0
text_new += '\n'
text_new = text_new.replace("\n\n","\n")
text_new = text_new.rstrip()
line_num = line_num + text_new.count("\n")
return text_new, line_num
def draw_to(self, text, boss_name="", scale = True):
font_size = self.font_size
black_clor = self.black_clor
upper_size = self.upper_size
below_size = self.below_size
left_size = self.left_size
padding = self.padding
img_width = self.img_width
use_font = self.use_font
text, line_num= self.prepare(text=text, scale = scale)
if scale:
if line_num < 5:
blank_space = int(5 - line_num)
line_num =5
text += "\n"
for k in range(blank_space):
text += "(ᵔ ᵕ ᵔ)\n"
else:
line_num = line_num
else:
img_width = 1080
line_num = line_num
img_hight = int(upper_size + below_size + font_size * (line_num + 1) + padding * line_num )
out_img = Image.new(mode="RGB", size=(img_width, img_hight),
color=black_clor)
draw = ImageDraw.Draw(out_img, "RGBA")
# # # #
banner_size = 12
border_color = (220, 211, 196)
out_padding = 15
mi_img = Image.open(jsondata.BACKGROUND_FILE)
mi_banner = Image.open(jsondata.BANNER_FILE).resize(
(banner_size, banner_size), resample=3
)
# add background
for x in range(int(math.ceil(img_hight / 100))):
out_img.paste(mi_img, (0, x * 100))
# add border
def draw_rectangle(draw, rect, width):
for i in range(width):
draw.rectangle(
(rect[0] + i, rect[1] + i, rect[2] - i, rect[3] - i),
outline=border_color,
)
draw_rectangle(
draw, (out_padding, out_padding, img_width - out_padding, img_hight - out_padding), 2
)
# add banner
out_img.paste(mi_banner, (out_padding, out_padding))
out_img.paste(
mi_banner.transpose(Image.FLIP_TOP_BOTTOM),
(out_padding, img_hight - out_padding - banner_size + 1),
)
out_img.paste(
mi_banner.transpose(Image.FLIP_LEFT_RIGHT),
(img_width - out_padding - banner_size + 1, out_padding),
)
out_img.paste(
mi_banner.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.FLIP_TOP_BOTTOM),
(img_width - out_padding - banner_size + 1, img_hight - out_padding - banner_size + 1),
)
# # # #
draw.text(
(left_size, upper_size),
text,
font=use_font,
fill=(125, 101, 89),
spacing=padding,
)
if boss_name:
boss_img_path = jsondata.BOSS_IMG / f'{boss_name}.png'
if os.path.exists(boss_img_path):
boss_img = Image.open(boss_img_path)
base_cc = boss_img.height / img_hight
boss_img_w = int(boss_img.width / base_cc)
boss_img_h = int(boss_img.height / base_cc)
boss_img = boss_img.resize((int(boss_img_w), int(boss_img_h)), Image.ANTIALIAS)
out_img.paste(
boss_img,
(int(img_width - boss_img_w), int(img_hight - boss_img_h)),
boss_img
)
return self.img2b64(out_img)
def img2b64(self, out_img) -> str:
""" image to base64 """
buf = BytesIO()
out_img.save(buf, format="PNG")
base64_str = "base64://" + b64encode(buf.getvalue()).decode()
return base64_str
async def get_msg_pic(msg, boss_name="", scale = True):
img = Txt2Img()
pic = img.draw_to(msg, boss_name, scale)
return pic
def CommandObjectID() -> int:
"""
根据消息事件的类型获取对象id
私聊->用户id
群聊->群id
频道->子频道id
:return: 对象id
"""
def _event_id(event):
if event.message_type == 'private':
return event.user_id
elif event.message_type == 'group':
return event.group_id
elif event.message_type == 'guild':
return event.channel_id
return Depends(_event_id)
def number_to(num):
'''
递归实现,精确为最大单位值 + 小数点后一位
'''
def strofsize(num, level):
if level >= 2:
return num, level
elif num >= 10000:
num /= 10000
level += 1
return strofsize(num, level)
else:
return num, level
units = ['', '万', '亿']
num, level = strofsize(num, 0)
if level > len(units):
level -= 1
return '{}{}'.format(round(num, 1), units[level])