├── CAT.TTF ├── README.md ├── account.json ├── image ├── haha.png └── 救命.png ├── pjprofile.png ├── pjskinfo.py ├── test.png ├── test1.png ├── text.png └── zzaw.ttf /CAT.TTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FLAG250/hoshino-plugin-pjsk/13ecea83d2bdb3ef1bf5fbecc2f0e4a08a88d822/CAT.TTF -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SBGA还我API!!
2 | 鉴于unibot以开源 直接开摆(安静地躺平)
3 | 4 | # hoshino-pjsk-plugin
5 | 因为频道里的pjsk查询没有开源 翻了翻pjsk信息网站发现有api于是决定自己做
6 | 指令 `/pjsk绑定+pjskID`可以绑定发送者的qq与pjsk,
7 | 指令`/pjsk进度`可以查询master难度的完成情况
8 | 指令`/pjskpf`可以查询pjsk个人档案(目前只有各难度的clear、FC、AP完成情况,以及各个角色等级)
9 | 指令`/sk`可以查询个人当前活动分数和上一级的分数线
10 | '/pjsk进度、pjskpf' 支持可以通过@已绑定的群友或后接pjskID逮捕群友!*后接pjskID更新于20220625,前者是已有的功能*
11 | 12 | python初学者 第一次写hoshino的插件
13 | 所以你将可以在py文件中看到:屎山、多段重复代码、莫名其妙的变量名称……
14 | 15 | 16 | ## 部署方法
17 | 1.git本项目 将文件夹放在\hoshino\modulus\下
18 | 2.在\config\_bot_.py中加入“hoshino-pjsk-plugin”,
19 | 3.在pjskinfo.py中修改load_path的路径(指向你放本插件的目录)
20 | 例load_path = "C:\\Users\\Administrater\\Desktop\\haru-bot-setup\\hoshino\\modules\\hoshino-pjsk-plugin"
21 | 4.重启并运行hoshino
22 | 运行前最好在account.json里先加上你自己的qqID和pjsk信息
23 | (因为没试过空文件测试 不知道会有什么问题)
24 | 25 | ## 未来功能
26 | 谱面查询
27 | 歌曲查询
28 | 猜歌(谱面猜歌,曲绘猜歌,歌曲切片猜歌)
29 | 按歌曲别称检索
30 | (向频道的unibot靠拢)
31 | 大部分bug打算随新功能加入一起修复
32 | 33 | unibot开源了就开摆?(bushi)
34 | 会找时间整合功能减少服务器负担(自己挂的bot已经反向了4个了)
35 | 36 | ## 已知问题
37 | ~~文件中字体均不支持中日文字混用因此可能会出现下面这种情况~~(换字体后已修)
38 | >![](image/haha.png)
39 | ~~由于ID过长导致:~~(已修)
40 | > ![](image/救命.png)
41 | > (笑死)
42 | 43 |
44 | 每次更新活动需重启一次hoshino,原因应该是插件在开头获取一次的活动资源为静态缓存在本地)
45 | -------------------------------------------------------------------------------- /account.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "qqid": [qq号], 4 | "pjskid": [pjskid] 5 | } 6 | ] -------------------------------------------------------------------------------- /image/haha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FLAG250/hoshino-plugin-pjsk/13ecea83d2bdb3ef1bf5fbecc2f0e4a08a88d822/image/haha.png -------------------------------------------------------------------------------- /image/救命.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FLAG250/hoshino-plugin-pjsk/13ecea83d2bdb3ef1bf5fbecc2f0e4a08a88d822/image/救命.png -------------------------------------------------------------------------------- /pjprofile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FLAG250/hoshino-plugin-pjsk/13ecea83d2bdb3ef1bf5fbecc2f0e4a08a88d822/pjprofile.png -------------------------------------------------------------------------------- /pjskinfo.py: -------------------------------------------------------------------------------- 1 | import json, base64, time 2 | import requests as req 3 | import os 4 | from PIL import Image, ImageDraw, ImageFont, ImageFilter 5 | import re 6 | from io import BytesIO 7 | import codecs 8 | 9 | from hoshino.typing import CQEvent, MessageSegment 10 | from hoshino import Service, priv, config 11 | 12 | import asyncio 13 | 14 | sv = Service( 15 | name = 'pjsk信息查询', #功能名 16 | use_priv = priv.NORMAL, #使用权限 17 | manage_priv = priv.SUPERUSER, #管理权限 18 | visible = False, #False隐藏 19 | enable_on_default = True, #是否默认启用 20 | bundle = '娱乐', #属于哪一类 21 | ) 22 | 23 | 24 | headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36'} 25 | url_getmD = 'https://musics.pjsekai.moe/musicDifficulties.json' 26 | url_getmc = 'https://musics.pjsekai.moe/musics.json' 27 | url_e_data = 'https://database.pjsekai.moe/events.json' 28 | color={"ap":"#d89aef","fc":"#ef8cee","clr":"#f0d873","all":"#6be1d9"} 29 | load_path = os.path.dirname(__file__) #更改为自动获取 30 | 31 | def data_req(url): #现场请求相关数据,耗时较长,但是数据永远是最新的 32 | temp_res = req.get(url, headers = headers) 33 | re = json.loads(temp_res.text) 34 | return re 35 | 36 | def a_check(uid,account): #bot, ev: CQEvent 37 | n_a = len(account) 38 | for a in range(n_a): 39 | if uid != account[a]["qqid"]: 40 | continue 41 | else: 42 | return False 43 | else: 44 | return True 45 | 46 | @sv.on_prefix("/pjsk绑定") 47 | async def reg(bot, ev: CQEvent): 48 | ppid = ev.message.extract_plain_text().strip() 49 | try: 50 | pid = int(ppid) 51 | uid = ev.user_id 52 | print(pid) 53 | if isinstance(pid,int) and pid > 1000000000000000: #待优化 54 | with open(load_path+f"\\account.json","r") as f: 55 | account = json.load(f) 56 | n_a = len(account) 57 | 58 | if a_check(uid,account): 59 | indexdata = [] 60 | for a in range(n_a): 61 | uuid = account[a]["qqid"] 62 | ppid = account[a]["pjskid"] 63 | account_dict = {'qqid' : uuid, 64 | 'pjskid' : ppid} 65 | indexdata.append(account_dict) 66 | account_dict = {'qqid' : uid, 67 | 'pjskid' : int(pid)} 68 | indexdata.append(account_dict) 69 | 70 | with open (load_path+'\\account.json', 'w', encoding='utf8') as f: 71 | json.dump(indexdata, f,indent =2, ensure_ascii=False) 72 | 73 | await bot.send(ev,f"绑定完成!",at_sender = True) 74 | else: 75 | await bot.send(ev,f"你已经绑定过!",at_sender = True) 76 | else: 77 | await bot.send(ev,f"UID格式错误",at_sender = True) 78 | except: 79 | await bot.send(ev,f"绑定发生错误",at_sender = True) 80 | 81 | 82 | 83 | 84 | 85 | 86 | async def lg(user_id): 87 | uid = user_id 88 | 89 | with open(load_path+f'\\account.json', 'r') as fff: 90 | udata = json.load(fff) 91 | if not a_check(uid,udata): 92 | for a in udata: 93 | if uid == a['qqid']: 94 | return a['pjskid'] 95 | else: 96 | continue 97 | else: 98 | return 0 99 | 100 | 101 | 102 | 103 | async def getLeaderIcon(data1): 104 | leaderId = data1['userDecks'][0]["leader"] 105 | for level in data1["userCards"]: 106 | if leaderId == level["cardId"]: 107 | card_type = level["defaultImage"] 108 | break 109 | getCd = req.get('https://database.pjsekai.moe/cards.json') 110 | cards_infomation = json.loads(getCd.text) 111 | for sc in cards_infomation: 112 | if leaderId == sc["id"]: 113 | if card_type == 'original': 114 | url = f'https://asset.pjsekai.moe/startapp/thumbnail/chara/{sc["assetbundleName"]}_normal.png' 115 | elif card_type == "special_training": 116 | url = f'https://asset.pjsekai.moe/startapp/thumbnail/chara/{sc["assetbundleName"]}_after_training.png' 117 | l_icon = req.get(url) 118 | return l_icon 119 | 120 | 121 | 122 | async def countFlg(_list,TAG,difficulty,data1): 123 | a_count = 0 124 | for result in data1['userMusicResults']: 125 | if result['musicDifficulty'] == difficulty: 126 | if result[TAG] == True and result['musicId'] not in _list: 127 | a_count = a_count + 1 128 | _list.append(result['musicId']) 129 | return _list,a_count 130 | 131 | 132 | async def countClear(_list,difficulty,data1): 133 | a_count = 0 134 | for result in data1['userMusicResults']: 135 | if result['musicDifficulty'] == difficulty: 136 | if result['fullComboFlg'] == True and result['musicId'] not in _list: 137 | a_count = a_count + 1 138 | _list.append(result['musicId']) 139 | if result['playResult'] == 'clear' and result['musicId'] not in _list: 140 | a_count = a_count + 1 141 | _list.append(result['musicId']) 142 | for a in _list: 143 | if _list.count(a) >= 2: 144 | a_count = account - _list.count(a) + 1 145 | return _list,a_count 146 | 147 | @sv.on_prefix("/pjskpf") 148 | async def pj_profileGet(bot,ev:CQEvent): 149 | #逮捕 150 | uid = ev.user_id 151 | userID = await lg(uid) 152 | 153 | selection = 0 154 | 155 | for i in ev.message: 156 | if i.type == 'at': 157 | uid = int(i.data['qq']) 158 | userID = await lg(uid) 159 | break 160 | 161 | _uID = ev.message.extract_plain_text().strip() 162 | if _uID != "": 163 | _userID = int(_uID) 164 | if isinstance(_userID,int) and _userID > 1000000000000000: 165 | userID = _userID 166 | selection = 1 167 | else: 168 | return await bot.send(ev,f'UID格式错误') 169 | 170 | 171 | 172 | if userID == 0: 173 | await bot.send(ev,f"没有绑定捏\n输入“/pjsk绑定+pjskID”来绑定吧~") 174 | else: 175 | try: 176 | url = f'https://api.pjsekai.moe/api/user/{userID}/profile' 177 | getdata = req.get(url) 178 | data1 = json.loads(getdata.text) 179 | 180 | 181 | dict_backup=[] 182 | difficulty = ['easy','normal','hard','expert','master'] 183 | for tag in difficulty: 184 | count = 0 185 | fc_count = 0 186 | ap_count = 0 187 | clr_list = [] 188 | fc_list = [] 189 | ap_list = [] 190 | fc_list,fc_count = await countFlg(fc_list,'fullComboFlg',tag,data1) 191 | ap_list,ap_count = await countFlg(ap_list,'fullPerfectFlg',tag,data1) 192 | clr_list,count = await countClear(clr_list,tag,data1) 193 | 194 | dict_backup.append({tag:{'fc':fc_count,'ap':ap_count,'clear':count}}) 195 | #print(dict_backup) 196 | 197 | 198 | 199 | profile_image= Image.open(load_path+'\\test1.png') 200 | new_pimage = load_path+'\\pjprofile.png' 201 | 202 | if selection == 0: 203 | picon = Image.open(BytesIO((await get_usericon(f'{uid}')).content)) ##### 204 | else: 205 | picon = Image.open(BytesIO((await getLeaderIcon(data1)).content)) 206 | 207 | num_font = ImageFont.truetype(load_path+'\\CAT.TTF',size=40) 208 | name_font = ImageFont.truetype(load_path+'\\zzaw.ttf',size=80) 209 | rank_font = ImageFont.truetype(load_path+'\\CAT.TTF',size=36) 210 | word_font = ImageFont.truetype(load_path+'\\zzaw.ttf',size=32) 211 | draw = ImageDraw.Draw(profile_image) 212 | draw_icon = ImageDraw.Draw(picon) 213 | 214 | #防止部分玩家ID过大导致其以期望外的方式生成 215 | u = data1['user']['userGamedata']['name'].encode("utf-8") 216 | if len(u) < 18: 217 | draw.text((281,130),data1['user']['userGamedata']['name'],'#FFFFFF',font=name_font) 218 | else: 219 | name_font = ImageFont.truetype(load_path+'\\zzaw.ttf',size=48) 220 | draw.text((281,162),data1['user']['userGamedata']['name'],'#FFFFFF',font=name_font) 221 | 222 | draw.text((404,231),str(data1['user']['userGamedata']['rank']),'#FFFFFF',font=rank_font) 223 | 224 | 225 | 226 | 227 | async def measure(msg, font_size, img_width): 228 | i = 0 229 | l = len(msg) 230 | length = 0 231 | positions = [] 232 | while i < l : 233 | if re.search(r'[0-9a-zA-Z]', msg[i]): 234 | length += font_size // 2 235 | else: 236 | length += font_size 237 | if length >= img_width: 238 | positions.append(i) 239 | length = 0 240 | i -= 1 241 | i += 1 242 | return positions 243 | 244 | #个人简介 245 | 246 | word_text = Image.new('RGB', (654, 157), "#5b5b5b") 247 | 248 | draw1 = ImageDraw.Draw(word_text) 249 | 250 | 251 | msg = data1['userProfile']['word'] 252 | positions = await measure(msg,32,700) 253 | str_list = list(msg) 254 | for pos in positions: 255 | str_list.insert(pos,'\n') 256 | msg = "".join(str_list) 257 | 258 | draw1.text((0,0), msg, "#FFFFFF", font=word_font) 259 | profile_image.paste(word_text, (103,307)) 260 | 261 | 262 | def draw_musicsCompleted(): 263 | x = 0 264 | for tag in difficulty: 265 | for pdata in dict_backup[x]: 266 | y = 0 267 | for ptag in ['clear','fc','ap']: 268 | draw.text((140 + x * 128,580 + y * 128),str(dict_backup[x][pdata][ptag]),'#FFFFFF',font=num_font) 269 | y = y + 1 270 | x = x + 1 271 | 272 | def characterdataGet(): 273 | for i in data1['userCharacters']: 274 | if i["characterId"] % 4 == 0: 275 | x = 960 + (165 * 3) 276 | y = 350 + (107 * (((i["characterId"])// 4)-1)) 277 | if i["characterId"] > 20: 278 | y = 130 + (107 * ((((i["characterId"])-20)// 4)-1)) 279 | else: 280 | x = 960 + (165 * ((((i["characterId"])) % 4)-1)) 281 | y = 350 + (107 * (((i["characterId"])//4))) 282 | if i["characterId"] > 20: 283 | y = 130 + (107 * ((((i["characterId"])-20)// 4))) 284 | draw.text((x, y),str(i['characterRank']),"#000000",font=num_font) 285 | 286 | 287 | 288 | draw_musicsCompleted() 289 | characterdataGet() 290 | picon = picon.resize((177,177),Image.Resampling.LANCZOS) 291 | profile_image.paste(picon, (95,106)) 292 | buf = BytesIO() 293 | profile_image.save(buf, format='PNG') 294 | base64_str = f'base64://{base64.b64encode(buf.getvalue()).decode()}' #通过BytesIO发送图片,无需生成本地文件 295 | await bot.send(ev,f'[CQ:image,file={base64_str}]',at_sender = True) 296 | except: 297 | await bot.send(ev,f"api或服务器可能寄了 或者你这个小可爱填错别人ID 不然一般是不会出现意料之外的问题的! \n请及时联系管理员看看发生什么事了") 298 | 299 | def load_event_info(_data): 300 | i = -2 301 | close_time = int(_data[i]["closedAt"]/1000) 302 | if time.time() > close_time: #说明倒数第二个活动已关闭,按最新的算 303 | i = -1 304 | return _data[i]['id'], _data[i]['name'], time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(_data[i]["aggregateAt"]/1000))), _data[i]['eventType'] 305 | 306 | @sv.on_prefix("/sk") 307 | async def event_rank(bot,ev:CQEvent): 308 | uid = ev.user_id 309 | userid = await lg(uid) 310 | if userid == 0: 311 | await bot.send(ev,f"没有绑定捏\n输入“/pjsk绑定+pjskID”来绑定吧~") 312 | else: 313 | try: 314 | _data = data_req(url_e_data) 315 | event_id, event_name, event_end_time, e_type = load_event_info(_data) 316 | url1 = f'https://api.pjsekai.moe/api/user/%7Buser_id%7D/event/{event_id}/ranking?targetUserId={userid}' 317 | 318 | user_event_data = req.get(url1, headers=headers) 319 | _event_data = json.loads(user_event_data.text) 320 | try: 321 | user_event_rank = _event_data['rankings'][0]['rank'] #你的try嵌套错地方了,如果没打活动这里就取不到值了 322 | user_event_score = _event_data['rankings'][0]['score'] #所以生成消息那边嵌套的try实际没有用 323 | except: 324 | await bot.send(ev, '小可爱你还没打活动查什么呢', at_sender = True) 325 | return #利用return结束 326 | nearest_line = [] 327 | event_line = [100, 200, 500, 328 | 1000, 2000, 5000, 329 | 10000, 20000, 50000, 330 | 100000, 200000, 500000, 331 | 1000000, 2000000, 5000000] 332 | 333 | for a in range(len(event_line)): 334 | if int(event_line[a]) >= user_event_rank: 335 | if a != 0: 336 | nearest_line.append(event_line[a-1]) 337 | nearest_line.append(event_line[a]) 338 | break 339 | else: 340 | nearest_line.append(event_line[-1]) 341 | 342 | msg = f"当前活动:{event_name}\n活动类型:{e_type}\n活动截止时间:{event_end_time}\n你的分数:{str(user_event_score)} rank#{str(user_event_rank)}\n最近的分数线:" 343 | for i in nearest_line: 344 | try: 345 | url2 = f'https://api.pjsekai.moe/api/user/%7Buser_id%7D/event/{event_id}/ranking?targetRank={i}' 346 | event_line_data = req.get(url2, headers=headers) 347 | _event_line_data = json.loads(event_line_data.text) 348 | msg += f"\nrank#{i} {str(_event_line_data['rankings'][0]['score'])}" 349 | except: 350 | msg += f"\nrank#{i} 最近的分数线:暂无数据" 351 | 352 | except Exception as e: 353 | msg = f"发生错误,错误类型:{type(e)}\n请联系管理员" 354 | print(e) 355 | await bot.send(ev, msg, at_sender = True) 356 | 357 | def load_req_line(string:str): 358 | return string.replace('k', '000').replace('K', '000').replace('w', '0000').replace('W', '0000') 359 | 360 | @sv.on_prefix('/pjsk档线') 361 | async def event_line_score(bot, ev): 362 | try: 363 | req_line = load_req_line(ev.message.extract_plain_text().strip()) 364 | except: 365 | req_line = 0 366 | try: 367 | _data = data_req(url_e_data) 368 | event_id, event_name, event_end_time, e_type = load_event_info(_data) 369 | 370 | #line_score = [] 371 | if req_line ==0: 372 | event_line = [100, 200, 500, 373 | 1000, 2000, 5000, 374 | 10000, 20000, 50000, 375 | 100000, 200000, 500000, 1000000] 376 | event_line_msg = ['100', '200', '500', 377 | '1k', '2k', '5k', 378 | '1w', '2w', '5w', 379 | '10w', '20w', '50w', '100w'] 380 | index = 0 381 | msg = f'活动标题:{event_name}\n活动类型:{e_type}' 382 | for line in event_line: 383 | url2 = f'https://api.pjsekai.moe/api/user/%7Buser_id%7D/event/{event_id}/ranking?targetRank={line}' 384 | event_line_data = data_req(url2) 385 | try: 386 | #line_score.append(str(event_line_data['rankings'][0]['score'])) #预留后期图像化 387 | line_score = event_line_data['rankings'][0]['score'] 388 | msg += f'\n{event_line_msg[index]}线:{line_score}' 389 | except: 390 | #line_score.append('暂无数据') 391 | msg += f'\n{event_line_msg[index]}线:暂无数据' 392 | index += 1 393 | else: 394 | msg = f'活动标题:{event_name}\n活动类型:{e_type}' 395 | url2 = f'https://api.pjsekai.moe/api/user/%7Buser_id%7D/event/{event_id}/ranking?targetRank={req_line}' 396 | event_line_data = data_req(url2) 397 | try: 398 | line_score = event_line_data['rankings'][0]['score'] 399 | msg += f'\n{req_line}线:{line_score}' 400 | except: 401 | msg += f'\n{req_line}线:暂无数据' 402 | except Exception as e: 403 | print(e) 404 | msg = f"发生错误,错误类型:{type(e)}\n请联系管理员" 405 | 406 | await bot.send(ev, msg, at_sender = True) 407 | 408 | async def pj_musicCompletedDataGet(uid,data1): 409 | difficulty = 'master' 410 | count = 0 411 | c_count = 0 412 | p_count = 0 413 | list1 = [] 414 | list2 = [] 415 | list3 = [] 416 | list4 = [] 417 | 418 | list1,c_count = await countFlg(list1,'fullComboFlg',difficulty,data1) 419 | list2,p_count = await countFlg(list2,'fullPerfectFlg',difficulty,data1) 420 | list4,count = await countClear(list4,difficulty,data1) 421 | 422 | _lv = data_req(url_getmD) 423 | allMusic = data_req(url_getmc) 424 | #按难度分类 425 | for _ in allMusic: 426 | list3.append(_['id']) 427 | 428 | async def selectPlus(_list): 429 | lv_s = {26:0,27:0,28:0,29:0,30:0,31:0,32:0,33:0,34:0,35:0,36:0} 430 | for __lv in _lv: 431 | if __lv['musicDifficulty'] == difficulty and __lv['musicId'] in _list: 432 | lv_s[__lv['playLevel']] += 1 433 | return lv_s 434 | 435 | lv1 = await selectPlus(list1) 436 | lv2 = await selectPlus(list2) 437 | lv3 = await selectPlus(list3) 438 | lv4 = await selectPlus(list4) 439 | 440 | 441 | async def change(lv): 442 | re_lv1 = [] 443 | in_dex ={} 444 | for i in range(26,37): 445 | a = lv[i] 446 | b = str(i) 447 | in_dex[f"{b}"] = a 448 | n_dex =in_dex 449 | re_lv1.append(n_dex) 450 | return re_lv1 451 | 452 | re_lv1 = await change(lv1) #fc 453 | re_lv2 = await change(lv2) #ap 454 | _all = await change(lv3) #all 455 | _clear = await change(lv4) #clear 456 | 457 | 458 | return _clear,_all,re_lv1,re_lv2 459 | 460 | 461 | async def get_usericon(user): 462 | p_icon = req.get(f'https://q1.qlogo.cn/g?b=qq&nk={user}&s=640') 463 | return p_icon 464 | 465 | @sv.on_prefix("/pjsk进度") 466 | async def gen_pjsk_jindu_image(bot,ev:CQEvent): 467 | #逮捕 468 | uid = ev.user_id 469 | userID = await lg(uid) 470 | 471 | selection = 0 472 | 473 | for i in ev.message: 474 | if i.type == 'at': 475 | uid = int(i.data['qq']) 476 | userID = await lg(uid) 477 | break 478 | 479 | _uID = ev.message.extract_plain_text().strip() 480 | if _uID != "": 481 | _userID = int(_uID) 482 | if isinstance(_userID,int) and _userID > 1000000000000000: 483 | userID = _userID 484 | selection = 1 485 | else: 486 | return await bot.send(ev,f'UID格式错误') 487 | 488 | 489 | 490 | if userID == 0: 491 | await bot.send(ev,f"没有绑定捏\n输入“/pjsk绑定+pjskID”来绑定吧~") 492 | 493 | else: 494 | try: 495 | url = f'https://api.pjsekai.moe/api/user/{str(userID)}/profile' 496 | getdata = req.get(url) 497 | data1 = json.loads(getdata.text) 498 | 499 | _clr,_all,_fc,_ap = await pj_musicCompletedDataGet(uid,data1) 500 | image1 = Image.open(load_path+f'\\test.png') 501 | new_image =load_path+f'\\pjskjindu.png' 502 | 503 | 504 | if selection == 0: 505 | icon = Image.open(BytesIO((await get_usericon(f'{uid}')).content)) ##### 506 | else: 507 | icon = Image.open(BytesIO((await getLeaderIcon(data1)).content)) 508 | 509 | font = ImageFont.truetype(load_path+f'\\CAT.TTF',size=40) 510 | font1 = ImageFont.truetype(load_path+f'\\zzaw.ttf',size=50) 511 | font2 = ImageFont.truetype(load_path+f'\\CAT.TTF',size=36) 512 | draw = ImageDraw.Draw(image1) 513 | 514 | u = data1['user']['userGamedata']['name'].encode("utf-8") 515 | if len(u) < 18: 516 | draw.text((214,75),data1['user']['userGamedata']['name'],'#000000',font=font1) 517 | else: 518 | font1 = ImageFont.truetype(load_path+f'\\zzaw.ttf',size=30) 519 | draw.text((214,95),data1['user']['userGamedata']['name'],'#000000',font=font1) 520 | 521 | draw.text((315,135),str(data1['user']['userGamedata']['rank']), "#FFFFFF",font=font2) 522 | icon = icon.resize((117,117),Image.Resampling.LANCZOS) 523 | image1.paste(icon, (67,57)) 524 | 525 | for i in _ap[0]: 526 | if i <= '31': 527 | draw.text((167,284+(97*(int(i)-26))),str(_ap[0][i]), color["ap"],font=font) 528 | else: 529 | draw.text((667,284+(97*(int(i)-32))),str(_ap[0][i]), color["ap"],font=font) 530 | for i in _fc[0]: 531 | if i <= '31': 532 | draw.text((242,284+(97*(int(i)-26))),str(_fc[0][i]), color["fc"],font=font) 533 | else: 534 | draw.text((742,284+(97*(int(i)-32))),str(_fc[0][i]), color["fc"],font=font) 535 | 536 | for i in _clr[0]: 537 | if i <= '31': 538 | draw.text((317,284+(97*(int(i)-26))),str(_clr[0][i]), color["clr"],font=font) 539 | else: 540 | draw.text((817,284+(97*(int(i)-32))),str(_clr[0][i]), color["clr"],font=font) 541 | for i in _all[0]: 542 | if i <= '31': 543 | draw.text((392,284+(97*(int(i)-26))),str(_all[0][i]), color["all"],font=font) 544 | else: 545 | draw.text((892,284+(97*(int(i)-32))),str(_all[0][i]), color["all"],font=font) 546 | 547 | buf = BytesIO() 548 | image1.save(buf, format='PNG') 549 | base64_str = f'base64://{base64.b64encode(buf.getvalue()).decode()}' 550 | await bot.send(ev,f'[CQ:image,file={base64_str}]',at_sender = True) 551 | except: 552 | await bot.send(ev,f"api或服务器可能寄了 或者你这个小可爱填错别人ID 不然一般是不会出现意料之外的问题的! \n请及时联系管理员看看发生什么事了") 553 | 554 | 555 | ''' 556 | userID = await lg(uid) 557 | url = f'https://api.pjsekai.moe/api/user/{userID}/profile' 558 | getdata = req.get(url) 559 | data1 = json.loads(getdata.text) 560 | #print(data1) 561 | ''' 562 | ''' 备份 给新功能测试 563 | loop = asyncio.get_event_loop() 564 | loop.run_until_complete(pj_profileGet()) 565 | loop.close() 566 | ''' 567 | -------------------------------------------------------------------------------- /test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FLAG250/hoshino-plugin-pjsk/13ecea83d2bdb3ef1bf5fbecc2f0e4a08a88d822/test.png -------------------------------------------------------------------------------- /test1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FLAG250/hoshino-plugin-pjsk/13ecea83d2bdb3ef1bf5fbecc2f0e4a08a88d822/test1.png -------------------------------------------------------------------------------- /text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FLAG250/hoshino-plugin-pjsk/13ecea83d2bdb3ef1bf5fbecc2f0e4a08a88d822/text.png -------------------------------------------------------------------------------- /zzaw.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FLAG250/hoshino-plugin-pjsk/13ecea83d2bdb3ef1bf5fbecc2f0e4a08a88d822/zzaw.ttf --------------------------------------------------------------------------------