Archived
1
0
Fork 0
This commit is contained in:
yzhh 2024-01-01 21:40:32 +08:00
commit 3a8d32c43b
16 changed files with 907 additions and 141 deletions

View file

@ -0,0 +1,700 @@
{
"grade": {
"grade1": {
"charts": [
{
"level_index": 0,
"song_id": 10552
},
{
"level_index": 0,
"song_id": 322
},
{
"level_index": 0,
"song_id": 793
},
{
"level_index": 0,
"song_id": 741
}
],
"condition": [
"-0",
"-2",
"-5",
"+20"
],
"life": 350
},
"grade10": {
"charts": [
{
"level_index": 3,
"song_id": 11164
},
{
"level_index": 3,
"song_id": 112
},
{
"level_index": 3,
"song_id": 11233
},
{
"level_index": 3,
"song_id": 11230
}
],
"condition": [
"-2",
"-2",
"-5",
"+20"
],
"life": 900
},
"grade2": {
"charts": [
{
"level_index": 1,
"song_id": 11043
},
{
"level_index": 1,
"song_id": 582
},
{
"level_index": 1,
"song_id": 725
},
{
"level_index": 1,
"song_id": 682
}
],
"condition": [
"-0",
"-2",
"-5",
"+20"
],
"life": 350
},
"grade3": {
"charts": [
{
"level_index": 1,
"song_id": 11187
},
{
"level_index": 1,
"song_id": 11325
},
{
"level_index": 1,
"song_id": 11049
},
{
"level_index": 1,
"song_id": 10593
}
],
"condition": [
"-1",
"-2",
"-5",
"+50"
],
"life": 600
},
"grade4": {
"charts": [
{
"level_index": 2,
"song_id": 311
},
{
"level_index": 2,
"song_id": 11260
},
{
"level_index": 2,
"song_id": 546
},
{
"level_index": 2,
"song_id": 11139
}
],
"condition": [
"-2",
"-2",
"-5",
"+50"
],
"life": 700
},
"grade5": {
"charts": [
{
"level_index": 2,
"song_id": 11132
},
{
"level_index": 2,
"song_id": 11192
},
{
"level_index": 2,
"song_id": 11104
},
{
"level_index": 2,
"song_id": 548
}
],
"condition": [
"-2",
"-2",
"-5",
"+50"
],
"life": 700
},
"grade6": {
"charts": [
{
"level_index": 2,
"song_id": 699
},
{
"level_index": 2,
"song_id": 681
},
{
"level_index": 2,
"song_id": 113
},
{
"level_index": 2,
"song_id": 11221
}
],
"condition": [
"-2",
"-2",
"-5",
"+50"
],
"life": 700
},
"grade7": {
"charts": [
{
"level_index": 3,
"song_id": 11044
},
{
"level_index": 3,
"song_id": 242
},
{
"level_index": 3,
"song_id": 699
},
{
"level_index": 3,
"song_id": 138
}
],
"condition": [
"-2",
"-2",
"-5",
"+50"
],
"life": 700
},
"grade8": {
"charts": [
{
"level_index": 3,
"song_id": 11229
},
{
"level_index": 3,
"song_id": 713
},
{
"level_index": 3,
"song_id": 11091
},
{
"level_index": 3,
"song_id": 464
}
],
"condition": [
"-2",
"-2",
"-5",
"+20"
],
"life": 700
},
"grade9": {
"charts": [
{
"level_index": 3,
"song_id": 11092
},
{
"level_index": 3,
"song_id": 11141
},
{
"level_index": 3,
"song_id": 82
},
{
"level_index": 3,
"song_id": 319
}
],
"condition": [
"-2",
"-2",
"-5",
"+20"
],
"life": 800
}
},
"rgrade": {
"expert1": {
"base": [
7.0,
9.6
],
"condition": [
"-2",
"-2",
"-5",
"+50"
],
"level_index": 2,
"life": 700
},
"expert2": {
"base": [
9.7,
11.6
],
"condition": [
"-2",
"-2",
"-5",
"+50"
],
"level_index": 2,
"life": 600
},
"expert3": {
"base": [
11.7,
13.9
],
"condition": [
"-2",
"-2",
"-5",
"+50"
],
"level_index": 2,
"life": 500
},
"master1": {
"base": [
10.0,
11.9
],
"condition": [
"-2",
"-2",
"-5",
"+50"
],
"level_index": 3,
"life": 700
},
"master2": {
"base": [
12.0,
13.2
],
"condition": [
"-2",
"-2",
"-5",
"+50"
],
"level_index": 3,
"life": 500
},
"master3": {
"base": [
13.3,
14.4
],
"condition": [
"-2",
"-2",
"-5",
"+20"
],
"level_index": 3,
"life": 300
},
"master4": {
"base": [
14.5,
14.9
],
"condition": [
"-2",
"-3",
"-5",
"+20"
],
"level_index": 3,
"life": 100
}
},
"tgrade": {
"tgrade1": {
"charts": [
{
"level_index": 3,
"song_id": 11010
},
{
"level_index": 3,
"song_id": 535
},
{
"level_index": 3,
"song_id": 11001
},
{
"level_index": 2,
"song_id": 136
}
],
"condition": [
"-2",
"-3",
"-5",
"+10"
],
"life": 50
},
"tgrade10": {
"charts": [
{
"level_index": 3,
"song_id": 11295
},
{
"level_index": 3,
"song_id": 11302
},
{
"level_index": 3,
"song_id": 11106
},
{
"level_index": 3,
"song_id": 773
}
],
"condition": [
"-2",
"-3",
"-5",
"+10"
],
"life": 50
},
"tgrade11": {
"charts": [
{
"level_index": 3,
"song_id": 11364
},
{
"level_index": 3,
"song_id": 571
},
{
"level_index": 3,
"song_id": 11311
},
{
"level_index": 3,
"song_id": 834
}
],
"condition": [
"-2",
"-3",
"-5",
"+5"
],
"life": 50
},
"tgrade12": {
"charts": [
{
"level_index": 4,
"song_id": 833
},
{
"level_index": 4,
"song_id": 803
},
{
"level_index": 4,
"song_id": 799
},
{
"level_index": 4,
"song_id": 834
}
],
"condition": [
"-1",
"-3",
"-10",
"+0"
],
"life": 10
},
"tgrade2": {
"charts": [
{
"level_index": 2,
"song_id": 11027
},
{
"level_index": 3,
"song_id": 11137
},
{
"level_index": 3,
"song_id": 228
},
{
"level_index": 3,
"song_id": 313
}
],
"condition": [
"-2",
"-3",
"-5",
"+10"
],
"life": 50
},
"tgrade3": {
"charts": [
{
"level_index": 3,
"song_id": 434
},
{
"level_index": 3,
"song_id": 11263
},
{
"level_index": 2,
"song_id": 11167
},
{
"level_index": 3,
"song_id": 11188
}
],
"condition": [
"-2",
"-3",
"-5",
"+10"
],
"life": 50
},
"tgrade4": {
"charts": [
{
"level_index": 2,
"song_id": 833
},
{
"level_index": 3,
"song_id": 218
},
{
"level_index": 3,
"song_id": 11153
},
{
"level_index": 3,
"song_id": 35
}
],
"condition": [
"-2",
"-3",
"-5",
"+10"
],
"life": 50
},
"tgrade5": {
"charts": [
{
"level_index": 3,
"song_id": 11231
},
{
"level_index": 3,
"song_id": 624
},
{
"level_index": 3,
"song_id": 11214
},
{
"level_index": 3,
"song_id": 454
}
],
"condition": [
"-2",
"-3",
"-5",
"+10"
],
"life": 50
},
"tgrade6": {
"charts": [
{
"level_index": 3,
"song_id": 252
},
{
"level_index": 3,
"song_id": 559
},
{
"level_index": 3,
"song_id": 11158
},
{
"level_index": 3,
"song_id": 422
}
],
"condition": [
"-2",
"-3",
"-5",
"+10"
],
"life": 50
},
"tgrade7": {
"charts": [
{
"level_index": 3,
"song_id": 11334
},
{
"level_index": 3,
"song_id": 701
},
{
"level_index": 3,
"song_id": 574
},
{
"level_index": 3,
"song_id": 141
}
],
"condition": [
"-2",
"-3",
"-5",
"+10"
],
"life": 50
},
"tgrade8": {
"charts": [
{
"level_index": 3,
"song_id": 11237
},
{
"level_index": 4,
"song_id": 24
},
{
"level_index": 3,
"song_id": 11101
},
{
"level_index": 3,
"song_id": 270
}
],
"condition": [
"-2",
"-3",
"-5",
"+10"
],
"life": 50
},
"tgrade9": {
"charts": [
{
"level_index": 3,
"song_id": 11093
},
{
"level_index": 3,
"song_id": 641
},
{
"level_index": 3,
"song_id": 61
},
{
"level_index": 3,
"song_id": 348
}
],
"condition": [
"-2",
"-3",
"-5",
"+10"
],
"life": 50
}
}
}

View file

@ -8,9 +8,9 @@ from config import Config
from core.builtins import Bot, Plain, Image
from core.component import module
from core.dirty_check import check_bool, rickroll
from core.exceptions import ConfigValueError
from core.petal import count_petal
from core.utils.cooldown import CoolDown
from core.exceptions import ConfigValueError
os.environ['LANGCHAIN_TRACING_V2'] = str(Config('enable_langsmith'))
if Config('enable_langsmith'):

View file

@ -65,6 +65,8 @@ async def _(msg: Bot.MessageSession):
url = f"{api_url}?aid={video[2:]}"
else:
url = await parse_shorturl(f"https://b23.tv/{video}")
if not url:
return
await get_info(msg, url, get_detail=False)
@ -75,5 +77,8 @@ async def parse_shorturl(shorturl):
target_url = response.headers.get('Location')
video = re.search(r'/video/([^/?]+)', target_url)
url = f"{api_url}?bvid={video.group(1)}"
return url
if video:
url = f"{api_url}?bvid={video.group(1)}"
return url
else:
return False

View file

@ -89,6 +89,7 @@ async def search_csr(id=None):
ccode = module('chemical_code', alias={'cc': 'chemical_code',
'cca': 'chemical_code captcha',
'chemicalcode': 'chemical_code',
'chemical_captcha': 'chemical_code captcha',
'chemicalcaptcha': 'chemical_code captcha',

View file

@ -3,8 +3,8 @@ import datetime
from config import Config
from core.builtins import Bot
from core.component import module
from core.utils.http import get_url
from core.exceptions import ConfigValueError
from core.utils.http import get_url
api_key = Config('exchange_rate_api_key')

View file

@ -1 +0,0 @@
资源文件请解压到assets/maimai文件夹。

View file

@ -1,21 +1,21 @@
import math
import traceback
from config import Config
from core.builtins import Bot, Plain, Image as BImage
from core.scheduler import CronTrigger
from core.utils.image import msgchain2image
from modules.maimai.libraries.maimai_best_50 import generate
from modules.maimai.libraries.maimaidx_api_data import get_alias, get_info, search_by_alias, update_alias, update_covers
from modules.maimai.libraries.maimaidx_music import get_cover_len5_id, TotalList
from modules.maimai.libraries.maimaidx_project import get_level_process, \
from modules.maimai.libraries.best50 import computeRa, generate
from modules.maimai.libraries.apidata import get_alias, get_info, search_by_alias, update_alias, update_covers
from modules.maimai.libraries.music import get_cover_len5_id, TotalList
from modules.maimai.libraries.utils import get_grade_info, get_level_process, \
get_plate_process, get_player_score, get_rank, get_score_list
from .regex import *
total_list = TotalList()
goal_list = ["A", "AA", "AAA", "S", "S+", "SS", "SS+", "SSS", "SSS+",
"FC", "FC+", "AP", "AP+", "FS", "FS+", "FDX", "FDX+"]
level_list = ['1', '2', '3', '4', '5', '6', '7', '7+', '8', '8+', '9', '9+',
'10', '10+', '11', '11+', '12', '12+', '13', '13+', '14', '14+', '15']
total_list = TotalList()
diff_label = ['Basic', 'Advanced', 'Expert', 'Master', 'Re:MASTER']
diff_label_abbr = ['bas', 'adv', 'exp', 'mas', 'rem']
@ -160,6 +160,11 @@ async def _(msg: Bot.MessageSession, sid: str):
await msg.finish([Plain(result.strip())])
@mai.command('grade <grade> {{maimai.help.grade}}')
async def _(msg: Bot.MessageSession, grade: str):
await get_grade_info(msg, grade)
@mai.command('b50 [<username>] {{maimai.help.b50}}')
async def _(msg: Bot.MessageSession, username: str = None):
if not username and msg.target.sender_from == "QQ":
@ -280,7 +285,7 @@ async def _(msg: Bot.MessageSession, plate: str, username: str = None):
await msg.finish(msg.locale.t("maimai.message.no_username"))
payload = {'username': username}
if plate == '真将' or (plate[1] == '' and plate[0] != ''):
if plate in ['真将', '真將'] or (plate[1] == '' and plate[0] != ''):
await msg.finish(msg.locale.t('maimai.message.plate.plate_not_found'))
output, get_img = await get_plate_process(msg, payload, plate)
@ -294,25 +299,6 @@ async def _(msg: Bot.MessageSession, plate: str, username: str = None):
@mai.command('process <level> <goal> [<username>] {{maimai.help.process}}')
async def _(msg: Bot.MessageSession, level: str, goal: str, username: str = None):
goal_list = [
"A",
"AA",
"AAA",
"S",
"S+",
"SS",
"SS+",
"SSS",
"SSS+",
"FC",
"FC+",
"AP",
"AP+",
"FS",
"FS+",
"FDX",
"FDX+"]
if not username and msg.target.sender_from == "QQ":
payload = {'qq': msg.session.sender}
else:
@ -463,39 +449,6 @@ async def _(msg: Bot.MessageSession, base: float, score: float):
await msg.finish([Plain(max(0, computeRa(base, score)))])
def computeRa(base: float, achievement: float) -> int:
if achievement < 50:
baseRa = 7.0
elif achievement < 60:
baseRa = 8.0
elif achievement < 70:
baseRa = 9.6
elif achievement < 75:
baseRa = 11.2
elif achievement < 80:
baseRa = 12.0
elif achievement < 90:
baseRa = 13.6
elif achievement < 94:
baseRa = 15.2
elif achievement < 97:
baseRa = 16.8
elif achievement < 98:
baseRa = 20.0
elif achievement < 99:
baseRa = 20.3
elif achievement < 99.5:
baseRa = 20.8
elif achievement < 100:
baseRa = 21.1
elif achievement < 100.5:
baseRa = 21.6
else:
baseRa = 22.4
return math.floor(base * (min(100.5, achievement) / 100) * baseRa)
@mai.command('update', required_superuser=True)
async def _(msg: Bot.MessageSession):
if await update_alias() and await update_covers():

View file

@ -1,17 +1,16 @@
import os
import shutil
import traceback
import ujson as json
from core.builtins import Bot, Plain, Image
from core.logger import Logger
from core.utils.cache import random_cache_path
from core.utils.http import get_url, post_url, download_to_cache
from .maimaidx_music import get_cover_len5_id, Music, TotalList
from .music import get_cover_len5_id, Music, TotalList
total_list = TotalList()
assets_path = os.path.abspath('./assets/maimai')
total_list = TotalList()
async def update_alias():
@ -113,7 +112,10 @@ async def get_record(msg, payload):
else:
await msg.finish(msg.locale.t("maimai.message.user_not_found"))
elif str(e).startswith('403'):
await msg.finish(msg.locale.t("maimai.message.forbidden"))
if "qq" in payload:
await msg.finish(msg.locale.t("maimai.message.forbidden.eula"))
else:
await msg.finish(msg.locale.t("maimai.message.forbidden"))
else:
traceback.print_exc()
@ -134,8 +136,9 @@ async def get_plate(msg, payload):
else:
await msg.finish(msg.locale.t("maimai.message.user_not_found"))
elif str(e).startswith('403'):
await msg.finish(msg.locale.t("maimai.message.forbidden"))
else:
traceback.print_exc()
if "qq" in payload:
await msg.finish(msg.locale.t("maimai.message.forbidden.eula"))
else:
await msg.finish(msg.locale.t("maimai.message.forbidden"))
return data

View file

@ -1,13 +1,12 @@
import math
import os
from typing import Optional, Dict, List, Tuple
import ujson as json
from PIL import Image, ImageDraw, ImageFont, ImageFilter
from core.builtins import ErrorMessage
from core.utils.http import post_url
from .maimaidx_music import get_cover_len5_id, TotalList
from .music import get_cover_len5_id, TotalList
total_list = TotalList()
@ -412,7 +411,10 @@ async def generate(msg, payload) -> Tuple[Optional[Image.Image], bool]:
else:
await msg.finish(msg.locale.t("maimai.message.user_not_found"))
elif str(e).startswith('403'):
await msg.finish(msg.locale.t("maimai.message.forbidden"))
if "qq" in payload:
await msg.finish(msg.locale.t("maimai.message.forbidden.eula"))
else:
await msg.finish(msg.locale.t("maimai.message.forbidden"))
else:
raise

View file

@ -1,18 +1,18 @@
import os
import ujson as json
from datetime import datetime
import matplotlib.pyplot as plt
import numpy as np
from core.utils.http import get_url
from core.utils.cache import random_cache_path
from .maimaidx_api_data import get_record, get_plate
from .maimaidx_music import TotalList
from .apidata import get_record, get_plate
from .music import TotalList
JINGLEBELL_SONG_ID = 70
assets_path = os.path.abspath('./assets/maimai')
total_list = TotalList()
plate_to_version = {
plate_conversion = {
'': 'maimai',
'': 'maimai PLUS',
'': 'maimai GreeN',
@ -41,6 +41,50 @@ plate_to_version = {
'': 'maimai でらっくす FESTiVAL'
}
grade_conversion = {
'初段': 'grade1',
'二段': 'grade2',
'三段': 'grade3',
'四段': 'grade4',
'五段': 'grade5',
'六段': 'grade6',
'七段': 'grade7',
'八段': 'grade8',
'九段': 'grade9',
'十段': 'grade10',
'真初段': 'tgrade1',
'真二段': 'tgrade2',
'真三段': 'tgrade3',
'真四段': 'tgrade4',
'真五段': 'tgrade5',
'真六段': 'tgrade6',
'真七段': 'tgrade7',
'真八段': 'tgrade8',
'真九段': 'tgrade9',
'真十段': 'tgrade10',
'真皆伝': 'tgrade11',
'真皆传': 'tgrade11',
'真皆傳': 'tgrade11',
'裏皆伝': 'tgrade12',
'里皆传': 'tgrade12',
'裡皆傳': 'tgrade12',
'裏皆傳': 'tgrade12',
'EXPERT初級': 'expert1',
'EXPERT初级': 'expert1',
'EXPERT中級': 'expert2',
'EXPERT中级': 'expert2',
'EXPERT上級': 'expert3',
'EXPERT上级': 'expert3',
'MASTER初級': 'master1',
'MASTER初级': 'master1',
'MASTER中級': 'master2',
'MASTER中级': 'master2',
'MASTER上級': 'master3',
'MASTER上级': 'master3',
'MASTER超上級': 'master4',
'MASTER超上级': 'master4',
}
score_to_rank = {
(0.0, 50.0): "D",
(50.0, 60.0): "C",
@ -88,6 +132,16 @@ combo_rank = list(combo_conversion.keys()) # Combo字典的键API内显示
sync_rank = list(sync_conversion.keys()) # Sync字典的键API内显示
def key_process(input_key, conv_dict):
key = next((k for k, v in conv_dict.items() if input_key == k), None)
if key is not None:
value = conv_dict[key]
new_key = next((k for k, v in conv_dict.items() if v == value), None)
return value, new_key
else:
return None, input_key
async def get_rank(msg, payload):
time = msg.ts2strftime(datetime.now().timestamp(), timezone=False)
@ -126,7 +180,7 @@ async def get_rank(msg, payload):
async def get_player_score(msg, payload, input_id):
payload['version'] = list(set(version for version in plate_to_version.values())) # 全版本
payload['version'] = list(set(version for version in plate_conversion.values())) # 全版本
res = await get_plate(msg, payload) # 获取用户成绩信息
verlist = res["verlist"]
@ -173,7 +227,7 @@ async def get_level_process(msg, payload, process, goal):
song_played = []
song_remain = []
payload['version'] = list(set(version for version in plate_to_version.values())) # 全版本
payload['version'] = list(set(version for version in plate_conversion.values())) # 全版本
res = await get_plate(msg, payload) # 获取用户成绩信息
verlist = res["verlist"]
@ -231,7 +285,7 @@ async def get_level_process(msg, payload, process, goal):
elif goal in syncRank:
if verlist[record_index]['fs']:
self_record = syncRank[sync_rank.index(verlist[record_index]['fs'])]
output += f"{s[0]}\u200B. {s[1]}{msg.locale.t('message.brackets', msg='DX') if s[5] == 'DX' else ''} {s[2]} {s[3]} {self_record}\n"
output += f"{s[0]}\u200B. {s[1]}{' (DX)' if s[5] == 'DX' else ''} {s[2]} {s[3]} {self_record}\n"
if len(song_remain) > 10: # 若剩余歌曲大于10个则使用图片形式
get_img = True
else:
@ -248,7 +302,7 @@ async def get_score_list(msg, payload, level):
player_data = await get_record(msg, payload)
username = player_data['username']
payload['version'] = list(set(version for version in plate_to_version.values())) # 全版本
payload['version'] = list(set(version for version in plate_conversion.values())) # 全版本
res = await get_plate(msg, payload) # 获取用户成绩信息
verlist = res["verlist"]
@ -258,7 +312,7 @@ async def get_score_list(msg, payload, level):
output_lines = []
for s in enumerate(sorted(song_list, key=lambda i: i['achievements'], reverse=True)): # 根据成绩排序
music = (await total_list.get()).by_id(str(s[1]['id']))
output = f"{music.id}\u200B. {music.title}{msg.locale.t('message.brackets', msg='DX') if music.type == 'DX' else ''} {diffs[s[1]['level_index']]} {music.ds[s[1]['level_index']]} {s[1]['achievements']}%"
output = f"{music.id}\u200B. {music.title}{' (DX)' if music.type == 'DX' else ''} {diffs[s[1]['level_index']]} {music.ds[s[1]['level_index']]} {s[1]['achievements']}%"
if s[1]["fc"] and s[1]["fs"]:
output += f" {combo_conversion.get(s[1]['fc'], '')} {sync_conversion.get(s[1]['fs'], '')}"
elif s[1]["fc"] or s[1]["fs"]:
@ -286,38 +340,46 @@ async def get_plate_process(msg, payload, plate):
song_remain_remaster = []
song_remain_difficult = []
version_mapping = {'': '', '': '', '': '', '': '', '': '', '': ''}
goal_mapping = {'': '', '': ''}
version = plate[0]
goal = plate[1:]
get_img = False
if version in version_mapping:
version = version_mapping[version]
if goal in goal_mapping:
goal = goal_mapping[goal]
plate = version + goal
if version == '': # 真代为无印版本
payload['version'] = ['maimai', 'maimai PLUS']
elif version in ['', '']: # 霸者和舞牌需要全版本
payload['version'] = list(set(version for version in list(plate_to_version.values())[:-9]))
elif version in plate_to_version and version != '': # “初”不是版本名称
payload['version'] = [plate_to_version[version]]
elif version in ['', '']: # 霸者和舞牌需要全版本
payload['version'] = list(set(ver for ver in list(plate_conversion.values())[:-9]))
elif version in plate_conversion and version != '': # “初”不是版本名称
payload['version'] = [plate_conversion[version]]
else:
await msg.finish(msg.locale.t('maimai.message.plate.plate_not_found'))
res = await get_plate(msg, payload) # 获取用户成绩信息
verlist = res["verlist"]
if goal in ['', '']:
if goal in ['', '']:
for song in verlist: # 将剩余歌曲ID和难度加入目标列表
if song['level_index'] == 0 and song['achievements'] < (100.0 if goal == '' else 80.0):
if song['level_index'] == 0 and song['achievements'] < (100.0 if goal == '' else 80.0):
song_remain_basic.append([song['id'], song['level_index']])
if song['level_index'] == 1 and song['achievements'] < (100.0 if goal == '' else 80.0):
if song['level_index'] == 1 and song['achievements'] < (100.0 if goal == '' else 80.0):
song_remain_advanced.append([song['id'], song['level_index']])
if song['level_index'] == 2 and song['achievements'] < (100.0 if goal == '' else 80.0):
if song['level_index'] == 2 and song['achievements'] < (100.0 if goal == '' else 80.0):
song_remain_expert.append([song['id'], song['level_index']])
if song['level_index'] == 3 and song['achievements'] < (100.0 if goal == '' else 80.0):
if song['level_index'] == 3 and song['achievements'] < (100.0 if goal == '' else 80.0):
song_remain_master.append([song['id'], song['level_index']])
if version in [
'', ''] and song['level_index'] == 4 and song['achievements'] < (
100.0 if goal == '' else 80.0):
if version in ['', ''] and song['level_index'] == 4 and song['achievements'] < (
100.0 if goal == '' else 80.0):
song_remain_remaster.append([song['id'], song['level_index']]) # 霸者和舞牌需要Re:MASTER难度
song_played.append([song['id'], song['level_index']])
elif goal in ['', '']:
elif goal == '':
for song in verlist: # 将剩余歌曲ID和难度加入目标列表
if song['level_index'] == 0 and not song['fc']:
song_remain_basic.append([song['id'], song['level_index']])
@ -369,7 +431,7 @@ async def get_plate_process(msg, payload, plate):
song_remain_expert.append([int(music.id), 2])
if [int(music.id), 3] not in song_played:
song_remain_master.append([int(music.id), 3])
if version in ['', ''] and len(music.level) == 5 and [int(music.id), 4] not in song_played:
if version in ['', ''] and len(music.level) == 5 and [int(music.id), 4] not in song_played:
song_remain_remaster.append([int(music.id), 4])
song_remain_basic = sorted(song_remain_basic, key=lambda i: int(i[0])) # 根据ID排序结果
song_remain_advanced = sorted(song_remain_advanced, key=lambda i: int(i[0]))
@ -399,7 +461,7 @@ async def get_plate_process(msg, payload, plate):
song_remain_expert=len(song_remain_expert),
song_remain_master=len(song_remain_master))
if version in ['', '']: # 霸者和舞牌需要Re:MASTER难度
if version in ['', '']: # 霸者和舞牌需要Re:MASTER难度
prompt += msg.locale.t('maimai.message.plate.remaster', song_remain_remaster=len(song_remain_remaster))
prompt += msg.locale.t('message.end')
@ -415,15 +477,15 @@ async def get_plate_process(msg, payload, plate):
self_record = ''
if [int(s[0]), s[-2]] in song_record: # 显示剩余13+以上歌曲信息
record_index = song_record.index([int(s[0]), s[-2]])
if goal in ['', '']:
if goal in ['', '']:
self_record = str(verlist[record_index]['achievements']) + '%'
elif goal in ['', '', '']:
elif goal in ['', '']:
if verlist[record_index]['fc']:
self_record = comboRank[combo_rank.index(verlist[record_index]['fc'])]
elif goal == '舞舞':
if verlist[record_index]['fs']:
self_record = syncRank[sync_rank.index(verlist[record_index]['fs'])]
output += f"{s[0]}\u200B. {s[1]}{msg.locale.t('message.brackets', msg='DX') if s[5] == 'DX' else ''} {s[2]} {s[3]} {self_record}".strip() + '\n'
output += f"{s[0]}\u200B. {s[1]}{' (DX)' if s[5] == 'DX' else ''} {s[2]} {s[3]} {self_record}".strip() + '\n'
if len(song_remain_difficult) > 10: # 若剩余歌曲大于10个则使用图片形式
get_img = True
else:
@ -440,15 +502,15 @@ async def get_plate_process(msg, payload, plate):
self_record = ''
if [int(s[0]), s[-2]] in song_record: # 显示剩余歌曲信息
record_index = song_record.index([int(s[0]), s[-2]])
if goal in ['', '']:
if goal in ['', '']:
self_record = str(verlist[record_index]['achievements']) + '%'
elif goal in ['', '', '']:
elif goal in ['', '']:
if verlist[record_index]['fc']:
self_record = comboRank[combo_rank.index(verlist[record_index]['fc'])]
elif goal == '舞舞':
if verlist[record_index]['fs']:
self_record = syncRank[sync_rank.index(verlist[record_index]['fs'])]
output += f"{m.id}\u200B. {m.title}{msg.locale.t('message.brackets', msg='DX') if m.type == 'DX' else ''} {diffs[s[1]]} {m.ds[s[1]]} {self_record}".strip(
output += f"{m.id}\u200B. {m.title}{' (DX)' if m.type == 'DX' else ''} {diffs[s[1]]} {m.ds[s[1]]} {self_record}".strip(
) + '\n'
if len(song_remain) > 10: # 若剩余歌曲大于10个则使用图片形式
get_img = True
@ -457,4 +519,47 @@ async def get_plate_process(msg, payload, plate):
else:
output += msg.locale.t('maimai.message.plate.completed', plate=plate)
return output, get_img
return output, get_img
async def get_grade_info(msg, grade):
file_path = os.path.join(assets_path, "mai_grade_info.json")
with open(file_path, 'r') as file:
data = json.load(file)
grade = grade.upper() # 输入强制转换为大写以适配字典
grade_key, grade = key_process(grade, grade_conversion)
if not grade_key:
await msg.finish(msg.locale.t('maimai.message.grade.grade_not_found'))
elif grade_key.startswith('tgrade'):
grade_type = 'tgrade'
elif grade_key.startswith('grade'):
grade_type = 'grade'
else:
grade_type = 'rgrade'
chart_info = []
grade_data = data[grade_type][grade_key]
condition = grade_data["condition"]
if grade_type != 'rgrade':
charts = grade_data["charts"]
for chart in charts:
music = (await total_list.get()).by_id(str(chart['song_id']))
level = chart['level_index']
chart_info.append(f"{music['id']}\u200B. {music['title']}{' (DX)' if music['type'] == 'DX' else ''} {diffs[level]} {music['level'][level]}")
else:
base = grade_data["base"]
level = grade_data["level_index"]
music_data = (await total_list.get()).filter(ds=(base[0], base[1]), diff=[level])
for i in range(4):
music = music_data.random()
chart_info.append(f"{music['id']}\u200B. {music['title']}{' (DX)' if music['type'] == 'DX' else ''} {diffs[level]} {music['level'][level]}")
content = '\n'.join(chart_info)
condition_info = f"GREAT{condition[0]}/GOOD{condition[1]}/MISS{condition[2]}/CLEAR{condition[3]}"
await msg.finish(msg.locale.t('maimai.message.grade', grade=grade, content=content, life=grade_data["life"], condition=condition_info))

View file

@ -1,8 +1,9 @@
{
"maimai.help.alias": "查询歌曲的别名。",
"maimai.help.b50": "查询 Maimai 用户的 B50 信息。",
"maimai.help.b50": "查询 Maimai 用户的 B50 列表。",
"maimai.help.base": "根据定数或定数范围搜索歌曲。",
"maimai.help.desc": "查询 Maimai 相关内容。",
"maimai.help.grade": "查询段位认定列表。",
"maimai.help.id": "根据 ID 查询歌曲或谱面信息。",
"maimai.help.info": "查询歌曲的相关谱面成绩ID 需要加入前缀“id”空格用“_”替代。",
"maimai.help.level": "根据等级搜索歌曲。",
@ -12,6 +13,7 @@
"maimai.help.maimai_regex.plate": "<名牌板>进度 [<用户名>] 查看用户的名牌板完成进度。",
"maimai.help.maimai_regex.process": "<难度> <目标>进度 [<用户名>] 查看用户在对应等级的评价完成进度。",
"maimai.help.maimai_regex.random": "随个[dx|标准][绿黄红紫白]<难度> 随机一首指定条件的歌曲。",
"maimai.help.maimai_regex.grade": "<段位>段位认定表 输入段位名查询段位认定列表。",
"maimai.help.maimai_regex.song": "<ID 或别名>是什么歌 输入 ID 或别名查询歌曲信息ID 需要加入前缀“id”。",
"maimai.help.plate": "查看用户的名牌板完成进度。",
"maimai.help.process": "查看用户在对应等级的评价完成进度。",
@ -31,13 +33,16 @@
"maimai.message.chart_not_found": "未找到符合要求的谱面。",
"maimai.message.error.non_digital": "发生错误:歌曲 ID 必须为数字。",
"maimai.message.forbidden": "此用户禁止了其他人获取数据。",
"maimai.message.forbidden.eula": "无法获取数据,请前往查分器并同意用户协议。\n查分器地址https://www.diving-fish.com/maimaidx/prober",
"maimai.message.goal_invalid": "无效的目标评级,请检查输入。",
"maimai.message.grade": "以下为 ${grade} 段位认定列表:\n${content}\n生命上限${life}\n${condition}",
"maimai.message.grade.grade_not_found": "无效的段位,请检查输入。",
"maimai.message.info.no_record": "未游玩过此谱面",
"maimai.message.level": "以下为 ${level} 级的曲目列表:",
"maimai.message.level_invalid": "无效的等级,请检查输入。",
"maimai.message.music_not_found": "未找到符合要求的歌曲。",
"maimai.message.no_username": "请提供用户名!",
"maimai.message.plate": "您的${plate}剩余进度如下:\nBasic 剩余 ${song_remain_basic} 首,\nAdvanced 剩余 ${song_remain_advanced} 首,\nExpert 剩余 ${song_remain_expert} 首,\nMaster 剩余 ${song_remain_master} 首",
"maimai.message.plate": "您的 ${plate} 剩余进度如下:\nBasic 剩余 ${song_remain_basic} 首,\nAdvanced 剩余 ${song_remain_advanced} 首,\nExpert 剩余 ${song_remain_expert} 首,\nMaster 剩余 ${song_remain_master} 首",
"maimai.message.plate.completed": "您已完成${plate}的所有进度。",
"maimai.message.plate.difficult": "您还有 ${song_remain} 首等级大于 13+ 的曲目。",
"maimai.message.plate.difficult.completed": "您已完成所有等级大于 13+ 的曲目。",
@ -51,7 +56,7 @@
"maimai.message.process.less_than_8": "歌曲等级必须大于 8 级。",
"maimai.message.random.error": "发生错误:随机歌曲失败,请检查输入。",
"maimai.message.rank": "截至 ${time}\n查分器共有 ${total_rank} 名用户,平均分数为 ${average_rating}。\n${user} 的分数为 ${rating},排名为 #${rank}\n已经超越了 ${surpassing_rate}% 的玩家。",
"maimai.message.scoreline": "分数线 ${scoreline}% 允许的最多 TAP GREAT 数量为 ${tap_great}(每个-${tap_great_prop}%\nBREAK 2550一共 ${brk} 个)等价于 ${b2t_2550_great} 个 TAP GREAT-${b2t_2550_great_prop}%\nBREAK 2000一共 ${brk} 个)等价于 ${b2t_2000_great} 个 TAP GREAT-${b2t_2000_great_prop}%",
"maimai.message.scoreline": "分数线 ${scoreline}% 允许的最多 TAP GREAT 数量为 ${tap_great}(每个-${tap_great_prop}%\nBREAK 2550一共 ${brk} 个)相当于 ${b2t_2550_great} 个 TAP GREAT-${b2t_2550_great_prop}%\nBREAK 2000一共 ${brk} 个)相当于 ${b2t_2000_great} 个 TAP GREAT-${b2t_2000_great_prop}%",
"maimai.message.scoreline.error": "发生错误:计算结果失败,请检查输入。",
"maimai.message.scorelist": "以下为 ${user} 的 ${level} 级成绩列表:",
"maimai.message.search": "“${keyword}”的搜索结果:",

View file

@ -1,13 +1,15 @@
{
"maimai.help.alias": "查詢歌曲的別名。",
"maimai.help.b50": "查詢 Maimai 使用者的 B50 資訊。",
"maimai.help.b50": "查詢 Maimai 使用者的 B50 列表。",
"maimai.help.base": "依據定數或定數範圍內搜尋歌曲。",
"maimai.help.desc": "查詢 Maimai 相關的內容。",
"maimai.help.id": "依據 ID 查詢歌曲或譜面資訊。",
"maimai.help.info": "查詢歌曲的相關譜面成績ID 需要加入前綴「id」空白用「_」取代。",
"maimai.help.level": "依據等級搜尋歌曲。",
"maimai.help.grade": "查詢段位認定列表。",
"maimai.help.maimai_regex.alias": "<ID> 有什麼別名 查詢歌曲的別名。",
"maimai.help.maimai_regex.desc": "更方便地使用 Maimai 相關指令。",
"maimai.help.maimai_regex.grade": "<段位>段位認定表 輸入段位名查詢段位認定列表。",
"maimai.help.maimai_regex.info": "<ID 或別名>有什麼分 [<使用者名稱>] 輸入 ID 或別名查詢歌曲相關譜面成績ID 需要加入前綴「id」空白用「_」取代。",
"maimai.help.maimai_regex.plate": "<名牌板>進度 [<使用者名稱>] 查看使用者的名牌板完成進度。",
"maimai.help.maimai_regex.process": "<難度> <目標>進度 [<使用者名稱>] 查看使用者在對應等級的評價完成進度。",
@ -30,14 +32,17 @@
"maimai.message.base.range": "以下為定數 ${constant}-${constant_max} 的曲目列表:",
"maimai.message.chart_not_found": "未找到符合要求的譜面。",
"maimai.message.error.non_digital": "發生錯誤:歌曲 ID 必須為數字!",
"maimai.message.forbidden": "此使用者禁止了其他人取得資料。",
"maimai.message.forbidden": "此使用者禁止了其他人取得資訊。",
"maimai.message.forbidden.eula": "無法取得資訊,請前往查分器並同意使用者協議。\n查分器網址https://www.diving-fish.com/maimaidx/prober",
"maimai.message.goal_invalid": "無效的目標評級,請校對輸入。",
"maimai.message.grade": "以下為 ${grade} 段位認定列表:\n${content}\n生命上限${life}\n${condition}",
"maimai.message.grade.grade_not_found": "無效的段位,請校對輸入。",
"maimai.message.info.no_record": "未遊玩過此譜面",
"maimai.message.level": "以下為難度 ${level} 的曲目列表:",
"maimai.message.level_invalid": "無效的等級,請校對輸入。",
"maimai.message.music_not_found": "未找到符合要求的歌曲。",
"maimai.message.no_username": "請提供使用者名稱!",
"maimai.message.plate": "您的${plate}剩餘進度如下:\nBasic 剩餘 ${song_remain_basic} 首,\nAdvanced 剩餘 ${song_remain_advanced} 首,\nExpert 剩餘 ${song_remain_expert} 首,\nMaster 剩餘 ${song_remain_master} 首",
"maimai.message.plate": "您的 ${plate} 剩餘進度如下:\nBasic 剩餘 ${song_remain_basic} 首,\nAdvanced 剩餘 ${song_remain_advanced} 首,\nExpert 剩餘 ${song_remain_expert} 首,\nMaster 剩餘 ${song_remain_master} 首",
"maimai.message.plate.completed": "您已完成${plate}的所有進度。",
"maimai.message.plate.difficult": "您還有 ${song_remain} 首等級大於 13+ 的曲目。",
"maimai.message.plate.difficult.completed": "您已完成所有等級大於 13+ 的曲目。",

View file

@ -5,14 +5,15 @@ from core.builtins import Bot, Plain, Image as BImage
from core.component import module
from core.logger import Logger
from core.utils.image import msgchain2image
from modules.maimai.libraries.maimaidx_api_data import get_alias, get_info, search_by_alias
from modules.maimai.libraries.maimaidx_music import get_cover_len5_id, TotalList
from modules.maimai.libraries.maimaidx_project import get_level_process, get_plate_process, get_player_score
total_list = TotalList()
from modules.maimai.libraries.apidata import get_alias, get_info, search_by_alias
from modules.maimai.libraries.music import get_cover_len5_id, TotalList
from modules.maimai.libraries.utils import get_grade_info, get_level_process, get_plate_process, get_player_score
goal_list = ["A", "AA", "AAA", "S", "S+", "SS", "SS+", "SSS", "SSS+",
"FC", "FC+", "AP", "AP+", "FS", "FS+", "FDX", "FDX+"]
level_list = ['1', '2', '3', '4', '5', '6', '7', '7+', '8', '8+', '9', '9+',
'10', '10+', '11', '11+', '12', '12+', '13', '13+', '14', '14+', '15']
total_list = TotalList()
diff_label = ['Basic', 'Advanced', 'Expert', 'Master', 'Re:MASTER']
diff_label_abbr = ['bas', 'adv', 'exp', 'mas', 'rem']
@ -162,7 +163,7 @@ async def _(msg: Bot.MessageSession):
await msg.finish(msg.locale.t("maimai.message.no_username"))
payload = {'username': username}
if plate == '真将' or (plate[1] == '' and plate[0] != ''):
if plate in ['真将', '真將'] or (plate[1] == '' and plate[0] != ''):
return
output, get_img = await get_plate_process(msg, payload, plate)
@ -176,24 +177,6 @@ async def _(msg: Bot.MessageSession):
@mai_regex.regex(re.compile(r"([0-9]+\+?)\s?(.+)\s?[进進]度\s?(.+)?"), desc='{maimai.help.maimai_regex.process}')
async def _(msg: Bot.MessageSession):
goal_list = [
"A",
"AA",
"AAA",
"S",
"S+",
"SS",
"SS+",
"SSS",
"SSS+",
"FC",
"FC+",
"AP",
"AP+",
"FS",
"FS+",
"FDX",
"FDX+"]
level = msg.matched_msg.groups()[0]
goal = msg.matched_msg.groups()[1]
username = msg.matched_msg.groups()[2]
@ -223,3 +206,9 @@ async def _(msg: Bot.MessageSession):
await msg.finish([BImage(img)])
else:
await msg.finish(output.strip())
@mai_regex.regex(re.compile(r"(.+)\s?段位[认認]定列?表"), desc='{maimai.help.maimai_regex.grade}')
async def _(msg: Bot.MessageSession):
grade = msg.matched_msg.groups()[0]
await get_grade_info(msg, grade)

View file

@ -5,10 +5,10 @@ from config import Config
from core.builtins import Bot
from core.component import module
from core.dirty_check import check_bool, rickroll
from core.exceptions import ConfigValueError
from core.logger import Logger
from core.petal import count_petal
from core.utils.cooldown import CoolDown
from core.exceptions import ConfigValueError
openai.api_key = Config('openai_api_key')

View file

@ -1,15 +1,14 @@
import os
import urllib.parse
from PIL import Image
from config import Config
from core.builtins import Bot, Image as BImage
from core.component import module
from core.dirty_check import check_bool, rickroll
from core.exceptions import ConfigValueError
from core.utils.http import download_to_cache, get_url
from core.exceptions import ConfigValueError
appid = Config('wolfram_alpha_appid')