Archived
1
0
Fork 0

use toml #517; auto convert cfg to toml

This commit is contained in:
yzhh 2023-06-29 20:57:46 +08:00
parent 780846fdf6
commit ba4ed4583e
12 changed files with 288 additions and 267 deletions

1
.gitignore vendored
View file

@ -1,6 +1,7 @@
*.env
__pycache__/
config/*.cfg
config/*.toml
.idea
.vscode
assets/mcversion.txt

View file

@ -13,6 +13,7 @@
## 下载源代码
1. 从 [Release 页面](https://github.com/Teahouse-Studios/bot/releases/latest) 的 Assets 部分中下载 Source code源代码。当然。你也可以下载 [master 分支的最新代码](https://github.com/Teahouse-Studios/akari-bot/archive/refs/heads/master.zip)。
注意master分支下的部署文档可能会有所不同请在下载对应版本的源码后打开目录下的DEPLOY.md继续查看部署教程
2. 解压源代码,然后打开终端,进入文件夹。
## 安装依赖
@ -82,11 +83,11 @@ $ pip install -r requirements.txt
## 配置
进入 `config` 文件夹,将 `config.cfg.example` 重命名为 `config.cfg`,然后开始配置你所需要的内容。
进入 `config` 文件夹,将 `config.toml.example` 重命名为 `config.toml`,然后开始配置你所需要的内容。
对于第一次的简单部署,我们只需要关注数据库字段即可,其余字段可留空:
`db_path = mysql+pymysql://`
`db_path = "mysql+pymysql://"`
机器人需要一个数据库以用于存储用户数据。
@ -113,7 +114,7 @@ $ pip install -r requirements.txt
**格式**
`db_path = sqlite:///<相对路径>/<数据库文件名>.db`
`db_path = "sqlite:///<相对路径>/<数据库文件名>.db"`
**实际示例**
@ -145,9 +146,9 @@ $ pip install -r requirements.txt
我们在这里使用了 [aiocqhttp](https://github.com/nonebot/aiocqhttp) 来对接 [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) 客户端。
`qq_host = 127.0.0.1:11451` - 将会在填写的 IP 地址和端口中开启一个 websocket 服务器,用于 go-cqhttp 反向连接。
`qq_host = "127.0.0.1:11451"` - 将会在填写的 IP 地址和端口中开启一个 websocket 服务器,用于 go-cqhttp 反向连接。
`qq_account = 2314163511` - 填写机器人的 QQ 号。
`qq_account = "2314163511"` - 填写机器人的 QQ 号。
填写好后,请配置 `go-cqhttp``config.yml` 文件中的对应的连接方式。
@ -205,7 +206,7 @@ servers:
由于小可有着许多的功能,部分功能需要进一步的配置才能使用。
部分字段可能并未预设于 `config.yml.example` 中,手动添加即可。
部分字段可能并未预设于 `config.toml.example` 中,手动添加即可。
### 屏蔽词
@ -255,7 +256,7 @@ FC_SERVER_PORT=15551 # 填写服务运行的端口
**示例**
`web_render = http://127.0.0.1:15551/`
`web_render = "http://127.0.0.1:15551/"`
### 模块
@ -270,12 +271,14 @@ FC_SERVER_PORT=15551 # 填写服务运行的端口
填写完后,你还需要从下载 [Arcaea](https://arcaea.lowiro.com/) 的 Apk 文件,将其放置于 `assets` 文件夹并重命名为 `arc.apk`,并在 Bot
启动后使用 `~arcaea initialize` 来初始化资源文件。
如果不需要本模块的功能将api字段删除即可。
#### coin
`coin` 模块需要一些额外的参数才能正常工作。
`coin_limit = 10000` - 一次可投掷的硬币最大个数。
co`in_faceup_rate = 4994` - 硬币正面朝上的概率,按一万分之几计算。
`coin_faceup_rate = 4994` - 硬币正面朝上的概率,按一万分之几计算。
`coin_facedown_rate = 4994` - 硬币反面朝上的概率,按一万分之几计算。
@ -322,33 +325,41 @@ assets
具体配置教程请查看链接所指向的文档。
配置好上述所需要用到的服务后,请确保在 `config` 目录下的 `config.cfg` 文件中填写以下字段:
配置好上述所需要用到的服务后,请确保在 `config` 目录下的 `config.toml` 文件中填写以下字段:
+ `web_render` - Webrender 的地址IP 或域名)及端口
+ `netease_cloud_music_api` - NeteaseCloudMusicApi 的地址IP 或域名)及端口
如果不需要本模块的功能将api字段删除即可。
#### secret
此模块下的内容主要用于监测 Minecraft Wiki 注册日志和滥用日志,如无需要可直接删除此模块的文件夹。
### 其他功能
`qq_msg_logging_to_db = True` - 将 QQ 平台内的命令触发消息记录至 `database/msg.db` 中,有助于判断是否存在违规使用机器人的情况。
`base_superuser =` - 设置机器人主超级用户。可用格式为 `QQ|<QQ号>`、`Discord|<ClientID>`、`Telegram|<ClientID>`,可在机器人开启后使用 `~whoami`
命令来查看自身的 ID机器人启动后将自动标记对象为超级用户。
`qq_enable_dirty_check = True` - 是否启用 QQ 平台的屏蔽词检查
`qq_disable_temp_session = true` - 是否禁用 QQ 平台的临时会话功能
`qq_enable_urlmanager = True` - 是否启用 QQ 平台的 URL 管理(替换外部链接,提示非官方页面)。若停用此功能将同时停用 `wiki_audit` 命令
`qq_enable_dirty_check = true` - 是否启用 QQ 平台的屏蔽词检查
`slower_schedule = False` - 部分计划任务模块使用更长的时间间隔执行,可能有助于网络较差环境的优化
`qq_enable_urlmanager = true` - 是否启用 QQ 平台的 URL 管理(替换外部链接,提示非官方页面)。若停用此功能将同时停用 `wiki_audit` 命令
`enable_tos = False` - 是否启用内置的违反服务条款的检查。
`slower_schedule = false` - 部分计划任务模块使用更长的时间间隔执行,可能有助于网络较差环境的优化。
`enable_tos = false` - 是否启用内置的违反服务条款的检查。
`enable_analytics = true` - 是否启用内置的 `analytics` 命令,用于统计命令使用次数。
`enable_eval= true` - 是否启用内置的 `eval` 命令。
`qq_enable_listening_self_message = false` - 是否启用 QQ 平台的自我消息处理(可能有助于多设备下使用,但也可能会导致误触发导致消息陷入死循环状态)。
`allow_request_private_ip = true` - 是否允许机器人请求私有 IP 地址。
`enable_analytics = True` - 是否启用内置的 `analytics` 命令,用于统计命令使用次数。
`enable_eval= True` - 是否启用内置的 `eval` 命令。
#### 自定义确认词及命令前缀

View file

@ -1,8 +1,6 @@
import logging
import os
import re
import traceback
from typing import Dict, Any
from aiocqhttp import Event, Error
@ -18,7 +16,7 @@ from database import BotDBUtil
PrivateAssets.set(os.path.abspath(os.path.dirname(__file__) + '/assets'))
EnableDirtyWordCheck.status = True if Config('qq_enable_dirty_check') else False
Url.disable_mm = False if Config('qq_enable_urlmanager') else True
qq_account = Config("qq_account")
qq_account = str(Config("qq_account"))
enable_listening_self_message = Config("qq_enable_listening_self_message")

View file

@ -1,34 +1,54 @@
from configparser import ConfigParser
import os
import toml
from os.path import abspath
from core.exceptions import ConfigFileNotFound
config_filename = 'config.cfg'
config_filename = 'config.toml'
config_path = abspath('./config/' + config_filename)
old_cfg_file_path = abspath('./config/config.cfg')
def convert_cfg_to_toml():
import configparser
config = configparser.ConfigParser()
config.read(old_cfg_file_path)
config_dict = {}
for section in config.sections():
config_dict[section] = dict(config[section])
for x in config_dict:
for y in config_dict[x]:
if config_dict[x][y] == "True":
config_dict[x][y] = True
elif config_dict[x][y] == "False":
config_dict[x][y] = False
elif config_dict[x][y].isdigit():
config_dict[x][y] = int(config_dict[x][y])
with open(config_path, 'w') as f:
f.write(toml.dumps(config_dict))
os.remove(old_cfg_file_path)
class CFG:
def __init__(self):
self.cp = ConfigParser()
self.cp.read(config_path)
if not os.path.exists(config_path):
if os.path.exists(old_cfg_file_path):
convert_cfg_to_toml()
else:
raise ConfigFileNotFound(config_path) from None
self.cp = toml.loads(open(config_path, 'r', encoding='utf-8').read())
def config(self, q):
section = self.cp.sections()
if len(section) == 0:
raise ConfigFileNotFound(config_path) from None
value = self.cp.get('secret', q, fallback=False)
value_s = self.cp.get('secret')
value_n = self.cp.get('cfg')
value = value_s.get(q)
if not value:
value = self.cp.get('cfg', q, fallback=False)
if not value:
return None
if value.upper() == 'TRUE':
return True
if value.upper() in ['', 'FALSE']:
return False
value = value_n.get(q)
return value
Config = CFG().config
CachePath = Config('cache_path')
DBPath = Config('db_path')

View file

@ -1,50 +0,0 @@
[secret]
db_path = mysql+pymysql://
Check_accessKeyId =
Check_accessKeySecret =
web_render =
netease_cloud_music_api_url =
botarcapi_url =
botarcapi_agent =
dc_token =
tg_token =
openai_api_key =
nl2c_model =
curseforge_api_key =
exchange_rate_api_key =
[cfg]
base_superuser = QQ|2596322644
debug = False
cache_path = ./cache/
extra_services = False
db_cache = False
bug_report_url = https://s.wd-ljt.com/botreportbug
donate_url = https://afdian.net/@teahouse
help_url = https://bot.teahouse.team
issue_url = https://github.com/Teahouse-Studios/bot/issues/new/choose
wiki_whitelist_url = https://s.wd-ljt.com/botwhitelist
qq_msg_logging_to_db = True
qq_host = 127.0.0.1:11451
qq_account = 2314163511
qq_enable_dirty_check = True
qq_enable_urlmanager = True
qq_disable_temp_session = False
web_render_local =
slower_schedule = False
enable_tos = False
enable_analytics = True
allow_request_private_ip = False
enable_eval = True
coin_limit = 10000
coin_faceup_rate = 4994
coin_facedown_rate = 4994
dice_limit = 100
dice_roll_limit = 10
dice_mod_max = 10000
dice_mod_min = -10000
dice_output_cnt = 50
dice_output_len = 200
dice_detail_cnt = 5
dice_count_limit = 10
qq_enable_listening_self_message = False

View file

@ -0,0 +1,49 @@
[secret]
db_path = "mysql+pymysql://"
Check_accessKeyId =
Check_accessKeySecret =
web_render =
netease_cloud_music_api_url =
botarcapi_url =
botarcapi_agent =
dc_token =
tg_token =
openai_api_key =
nl2c_model =
curseforge_api_key =
exchange_rate_api_key =
[cfg]
base_superuser = "QQ|2596322644"
debug = false
cache_path = "./cache/"
extra_services = false
db_cache = false
bug_report_url = "https://s.wd-ljt.com/botreportbug"
donate_url = "https://afdian.net/@teahouse"
help_url = "https://bot.teahouse.team"
issue_url = "https://github.com/Teahouse-Studios/bot/issues/new/choose"
wiki_whitelist_url = "https://s.wd-ljt.com/botwhitelist"
qq_host = "127.0.0.1:11451"
qq_account = 2314163511
qq_enable_dirty_check = true
qq_enable_urlmanager = true
qq_disable_temp_session = false
web_render_local =
slower_schedule = false
enable_tos = false
enable_analytics = true
allow_request_private_ip = false
enable_eval = true
coin_limit = 10000
coin_faceup_rate = 4994
coin_facedown_rate = 4994
dice_limit = 100
dice_roll_limit = 10
dice_mod_max = 10000
dice_mod_min = -10000
dice_output_cnt = 50
dice_output_len = 200
dice_detail_cnt = 5
dice_count_limit = 10
qq_enable_listening_self_message = false

View file

@ -9,7 +9,7 @@ import filetype
from PIL import Image as PImage
from tenacity import retry, stop_after_attempt
from config import CachePath, Config
from config import Config
from core.types.message.internal import Plain as P, Image as I, Voice as V, Embed as E, EmbedField as EF, \
Url as U, ErrorMessage as EMsg
from core.utils.i18n import Locale
@ -74,7 +74,7 @@ class Image(I):
self.path = path
self.headers = headers
if isinstance(path, PImage.Image):
save = f'{CachePath}{str(uuid.uuid4())}.png'
save = f'{Config("cache_path")}{str(uuid.uuid4())}.png'
path.convert('RGBA').save(save)
self.path = save
elif re.match('^https?://.*', path):
@ -92,7 +92,7 @@ class Image(I):
async with session.get(url, timeout=aiohttp.ClientTimeout(total=20)) as req:
raw = await req.read()
ft = filetype.match(raw).extension
img_path = f'{CachePath}{str(uuid.uuid4())}.{ft}'
img_path = f'{Config("cache_path")}{str(uuid.uuid4())}.{ft}'
with open(img_path, 'wb+') as image_cache:
image_cache.write(raw)
return img_path

View file

@ -2,11 +2,12 @@ import asyncio
import logging
import os
import traceback
from configparser import ConfigParser
from os.path import abspath
import ujson as json
from config import CFG
from core.builtins import PrivateAssets, Secret
from core.exceptions import ConfigFileNotFound
from core.loader import load_modules, ModulesManager
@ -32,18 +33,10 @@ async def init_async() -> None:
async def load_secret():
config_filename = 'config.cfg'
config_path = abspath('./config/' + config_filename)
cp = ConfigParser()
cp.read(config_path)
section = cp.sections()
if len(section) == 0:
raise ConfigFileNotFound(config_path) from None
options = cp.options('secret')
for option in options:
value = cp.get('secret', option)
if value.upper() not in ['', 'TRUE', 'FALSE']:
Secret.add(value.upper())
for x in CFG().cp:
if x == 'secret':
for y in CFG().cp[x]:
Secret.add(str(CFG().cp[x][y]).upper())
async def append_ip():
try:

View file

@ -27,179 +27,176 @@ class WithErrCode(Exception):
pass
@arc.command('b30 [<friend_code>] {{arcaea.help.b30}}')
async def _(msg: Bot.MessageSession, friend_code: int = None):
if not os.path.exists(assets_path):
await msg.finish(msg.locale.t("arcaea.message.assets.not_found", prefix=msg.prefixes[0]))
if friend_code is not None:
if len(str(friend_code)) != 9:
await msg.finish(msg.locale.t("arcaea.message.invalid.friendcode.non_digital"))
query_code = friend_code
else:
query_code = ArcBindInfoManager(msg).get_bind_friendcode()
if query_code is not None:
try:
if msg.target.senderId in query_tasks:
await msg.finish(msg.locale.t("arcaea.message.b30.wait.already"))
query_tasks.add(msg.target.senderId)
get_ = await get_url(api + f'user/bests/session?user_name={query_code}', headers=headers,
fmt='json')
if get_['status'] == 0:
await msg.sendMessage(msg.locale.t("arcaea.message.b30.wait"))
if msg.target.targetFrom not in ['Discord|Channel', 'Telegram|group', 'Telegram|supergroup']:
await msg.sendMessage([Plain(msg.locale.t("arcaea.message.sb616")),
Image(os.path.abspath('./assets/noc.jpg')),
Image(os.path.abspath('./assets/aof.jpg'))])
elif get_['status'] == -33:
await msg.sendMessage(msg.locale.t("arcaea.message.b30.wait.cached"))
elif get_['status'] == -23:
await msg.finish(msg.locale.t("arcaea.message.b30.low_potential"))
else:
await msg.finish(msg.locale.t("arcaea.message.get_failed") + get_['message'])
ExecutionLockList.remove(msg)
if api:
async def _get_result(session):
try:
get_ = await get_url(api + f'user/bests/result?session_info={session}&with_song_info=true',
headers=headers,
fmt='json')
if get_['status'] in [-31, -32]:
Logger.warn(get_['message'])
@arc.command('b30 [<friend_code>] {{arcaea.help.b30}}')
async def _(msg: Bot.MessageSession, friend_code: int = None):
if not os.path.exists(assets_path):
await msg.finish(msg.locale.t("arcaea.message.assets.not_found", prefix=msg.prefixes[0]))
if friend_code is not None:
if len(str(friend_code)) != 9:
await msg.finish(msg.locale.t("arcaea.message.invalid.friendcode.non_digital"))
query_code = friend_code
else:
query_code = ArcBindInfoManager(msg).get_bind_friendcode()
if query_code is not None:
try:
if msg.target.senderId in query_tasks:
await msg.finish(msg.locale.t("arcaea.message.b30.wait.already"))
query_tasks.add(msg.target.senderId)
get_ = await get_url(api + f'user/bests/session?user_name={query_code}', headers=headers,
fmt='json')
if get_['status'] == 0:
await msg.sendMessage(msg.locale.t("arcaea.message.b30.wait"))
if msg.target.targetFrom not in ['Discord|Channel', 'Telegram|group', 'Telegram|supergroup']:
await msg.sendMessage([Plain(msg.locale.t("arcaea.message.sb616")),
Image(os.path.abspath('./assets/noc.jpg')),
Image(os.path.abspath('./assets/aof.jpg'))])
elif get_['status'] == -33:
await msg.sendMessage(msg.locale.t("arcaea.message.b30.wait.cached"))
elif get_['status'] == -23:
await msg.finish(msg.locale.t("arcaea.message.b30.low_potential"))
else:
await msg.finish(msg.locale.t("arcaea.message.get_failed") + get_['message'])
ExecutionLockList.remove(msg)
async def _get_result(session):
try:
get_ = await get_url(api + f'user/bests/result?session_info={session}&with_song_info=true',
headers=headers,
fmt='json')
if get_['status'] in [-31, -32]:
Logger.warn(get_['message'])
return False
return get_
except Exception as e:
Logger.error(e)
return False
return get_
except Exception as e:
Logger.error(e)
return False
async def _check(msg: Bot.MessageSession, session, tried):
if tried == 0:
for _ in range(4):
await msg.sleep(15)
async def _check(msg: Bot.MessageSession, session, tried):
if tried == 0:
for _ in range(4):
await msg.sleep(15)
if _result := await _get_result(session):
return _result
elif tried == 1:
await msg.sendMessage(msg.locale.t("arcaea.message.b30.wait.check"))
await msg.sleep(60)
if _result := await _get_result(session):
return _result
elif tried <= 30:
await msg.sleep(60)
if _result := await _get_result(session):
return _result
elif tried == 1:
await msg.sendMessage(msg.locale.t("arcaea.message.b30.wait.check"))
await msg.sleep(60)
if _result := await _get_result(session):
return _result
elif tried <= 30:
await msg.sleep(60)
if _result := await _get_result(session):
return _result
else:
await msg.sendMessage(msg.locale.t("arcaea.message.b30.wait.timeout"))
return False
tried += 1
return await _check(msg, session, tried)
resp = await _check(msg, get_['content']['session_info'], 0)
if resp:
resp = await make_b30_img(resp)
if resp['status']:
msgchain = [Plain(msg.locale.t("arcaea.message.b30.success", b30=resp["b30"], r10=resp["r10"],
last5list=resp["last5list"]))]
if 'file' in resp and msg.Feature.image:
msgchain.append(Image(path=resp['file']))
await msg.finish(msgchain)
else:
if 'errcode' in resp:
raise WithErrCode(resp['errcode'])
else:
raise
except WithErrCode as e:
err_key = "arcaea.errcode." + str(e.args[0])
err_msg = msg.locale.t(err_key)
if err_key != err_msg:
await msg.finish(msg.locale.t("arcaea.message.get_failed") + err_msg)
else:
await msg.sendMessage(msg.locale.t("arcaea.message.b30.wait.timeout"))
return False
tried += 1
return await _check(msg, session, tried)
resp = await _check(msg, get_['content']['session_info'], 0)
if resp:
resp = await make_b30_img(resp)
if resp['status']:
msgchain = [Plain(msg.locale.t("arcaea.message.b30.success", b30=resp["b30"], r10=resp["r10"],
last5list=resp["last5list"]))]
if 'file' in resp and msg.Feature.image:
msgchain.append(Image(path=resp['file']))
await msg.finish(msgchain)
else:
if 'errcode' in resp:
raise WithErrCode(resp['errcode'])
else:
raise
except WithErrCode as e:
err_key = "arcaea.errcode." + str(e.args[0])
err_msg = msg.locale.t(err_key)
if err_key != err_msg:
await msg.finish(msg.locale.t("arcaea.message.get_failed") + err_msg)
else:
await msg.finish(msg.locale.t("arcaea.message.get_failed"))
except Exception:
traceback.print_exc()
await msg.finish(msg.locale.t("arcaea.message.get_failed"))
except Exception:
traceback.print_exc()
await msg.finish(msg.locale.t("arcaea.message.get_failed"))
finally:
query_tasks.remove(msg.target.senderId)
else:
await msg.finish(msg.locale.t("arcaea.message.user_unbound", prefix=msg.prefixes[0]))
@arc.command('info [<friend_code>] {{arcaea.help.info}}')
async def _(msg: Bot.MessageSession, friend_code: int = None):
if not os.path.exists(assets_path):
await msg.sendMessage(msg.locale.t("arcaea.message.assets.not_found", prefix=msg.prefixes[0]))
return
if friend_code is not None:
if len(str(friend_code)) != 9:
await msg.finish(msg.locale.t("arcaea.message.invalid.friendcode.non_digital"))
query_code = friend_code
else:
query_code = ArcBindInfoManager(msg).get_bind_friendcode()
if query_code is not None:
try:
resp = await get_info(msg, query_code)
await msg.finish(resp)
except Exception:
traceback.print_exc()
await msg.finish(msg.locale.t("arcaea.message.get_failed"))
else:
await msg.finish(msg.locale.t("arcaea.message.user_unbound", prefix=msg.prefixes[0]))
@arc.command('song <songname> [<diff>] {{arcaea.help.song}}')
async def _(msg: Bot.MessageSession):
songname = msg.parsed_msg['<songname>']
diff_ = msg.parsed_msg.get('<diff>')
if not diff_:
diff_ = 'FTR'
s = diff_.upper()
if s in ['PST', 'PAST']:
diff = 0
elif s in ['PRS', 'PRESENT']:
diff = 1
elif s in ['FTR', 'FUTURE']:
diff = 2
elif s in ['BYD', 'BEYOND']:
diff = 3
else:
await msg.finish(msg.locale.t("arcaea.message.song.invalid.difficulty"))
usercode = ArcBindInfoManager(msg).get_bind_friendcode()
await msg.finish(Plain(await get_song_info(msg, songname, diff, usercode)))
@arc.command('bind <friendcode|username> {{arcaea.help.bind}}')
async def _(msg: Bot.MessageSession):
code: str = msg.parsed_msg['<friendcode|username>']
getcode = await get_userinfo(code)
if getcode:
bind = ArcBindInfoManager(msg).set_bind_info(username=getcode[0], friendcode=getcode[1])
if bind:
await msg.finish(msg.locale.t("arcaea.message.bind.success", username=getcode[0], friendcode=getcode[1]))
else:
if code.isdigit():
bind = ArcBindInfoManager(msg).set_bind_info(username='', friendcode=code)
if bind:
await msg.finish(msg.locale.t("arcaea.message.bind.success.but_failed_fetch_username"))
finally:
query_tasks.remove(msg.target.senderId)
else:
await msg.finish(msg.locale.t("arcaea.message.bind.failed"))
await msg.finish(msg.locale.t("arcaea.message.user_unbound", prefix=msg.prefixes[0]))
@arc.command('info [<friend_code>] {{arcaea.help.info}}')
async def _(msg: Bot.MessageSession, friend_code: int = None):
if not os.path.exists(assets_path):
await msg.sendMessage(msg.locale.t("arcaea.message.assets.not_found", prefix=msg.prefixes[0]))
return
if friend_code is not None:
if len(str(friend_code)) != 9:
await msg.finish(msg.locale.t("arcaea.message.invalid.friendcode.non_digital"))
query_code = friend_code
else:
query_code = ArcBindInfoManager(msg).get_bind_friendcode()
if query_code is not None:
try:
resp = await get_info(msg, query_code)
await msg.finish(resp)
except Exception:
traceback.print_exc()
await msg.finish(msg.locale.t("arcaea.message.get_failed"))
else:
await msg.finish(msg.locale.t("arcaea.message.user_unbound", prefix=msg.prefixes[0]))
@arc.command('unbind {{arcaea.help.unbind}}')
async def _(msg: Bot.MessageSession):
unbind = ArcBindInfoManager(msg).remove_bind_info()
if unbind:
await msg.finish(msg.locale.t("arcaea.message.unbind.success"))
@arc.command('song <songname> [<diff>] {{arcaea.help.song}}')
async def _(msg: Bot.MessageSession):
songname = msg.parsed_msg['<songname>']
diff_ = msg.parsed_msg.get('<diff>')
if not diff_:
diff_ = 'FTR'
s = diff_.upper()
if s in ['PST', 'PAST']:
diff = 0
elif s in ['PRS', 'PRESENT']:
diff = 1
elif s in ['FTR', 'FUTURE']:
diff = 2
elif s in ['BYD', 'BEYOND']:
diff = 3
else:
await msg.finish(msg.locale.t("arcaea.message.song.invalid.difficulty"))
@arc.command('initialize', required_superuser=True)
async def _(msg: Bot.MessageSession):
assets_apk = os.path.abspath('./assets/arc.apk')
if not os.path.exists(assets_apk):
await msg.finish(msg.locale.t("arcaea.message.initialize.not_found"))
return
result = await arcb30init()
if result:
await msg.finish(msg.locale.t("arcaea.message.initialize.success"))
usercode = ArcBindInfoManager(msg).get_bind_friendcode()
await msg.finish(Plain(await get_song_info(msg, songname, diff, usercode)))
@arc.command('bind <friendcode|username> {{arcaea.help.bind}}')
async def _(msg: Bot.MessageSession):
code: str = msg.parsed_msg['<friendcode|username>']
getcode = await get_userinfo(code)
if getcode:
bind = ArcBindInfoManager(msg).set_bind_info(username=getcode[0], friendcode=getcode[1])
if bind:
await msg.finish(msg.locale.t("arcaea.message.bind.success", username=getcode[0], friendcode=getcode[1]))
else:
if code.isdigit():
bind = ArcBindInfoManager(msg).set_bind_info(username='', friendcode=code)
if bind:
await msg.finish(msg.locale.t("arcaea.message.bind.success.but_failed_fetch_username"))
else:
await msg.finish(msg.locale.t("arcaea.message.bind.failed"))
@arc.command('unbind {{arcaea.help.unbind}}')
async def _(msg: Bot.MessageSession):
unbind = ArcBindInfoManager(msg).remove_bind_info()
if unbind:
await msg.finish(msg.locale.t("arcaea.message.unbind.success"))
@arc.command('initialize', required_superuser=True)
async def _(msg: Bot.MessageSession):
assets_apk = os.path.abspath('./assets/arc.apk')
if not os.path.exists(assets_apk):
await msg.finish(msg.locale.t("arcaea.message.initialize.not_found"))
return
result = await arcb30init()
if result:
await msg.finish(msg.locale.t("arcaea.message.initialize.success"))
@arc.command('download {{arcaea.help.download}}')

View file

@ -2,7 +2,6 @@ from config import Config
from core.builtins import Bot, Plain, Image
from core.component import module
from core.utils.http import get_url
from core.utils.image import msgchain2image
api_address = Config('netease_cloud_music_api_url')
@ -13,6 +12,8 @@ ncmusic = module('ncmusic',
@ncmusic.handle('search <keyword> {{ncmusic.help.search}}')
async def search(msg: Bot.MessageSession, keyword: str):
if not api_address:
await msg.finish(msg.locale.t('ncmusic.message.api_unconfigured'))
url = f"{api_address}search?keywords={keyword}"
result = await get_url(url, 200, fmt='json')

2
poetry.lock generated
View file

@ -4433,4 +4433,4 @@ cffi = ["cffi (>=1.11)"]
[metadata]
lock-version = "2.0"
python-versions = "^3.8.1"
content-hash = "397c58aa2c29af72e750d4ec142b2db8a8a59f009d10c9c15e61c396256a5272"
content-hash = "21c1f768442311a5d4fa657d4f07b5290eb7f1b8fd09b8be89cae12c15904c70"

View file

@ -52,6 +52,7 @@ chromadb = "^0.3.21"
tiktoken = "^0.3.3"
pycryptodome = "^3.18.0"
langconv = "^0.2.0"
toml = "^0.10.2"
[tool.poetry.group.dev.dependencies]