Archived
1
0
Fork 0
This commit is contained in:
Dianliang233 2023-04-14 21:15:52 +08:00
commit edeb9b1b7d
54 changed files with 799 additions and 318 deletions

2
bot.py
View file

@ -124,7 +124,7 @@ if __name__ == '__main__':
logger.add(sys.stderr, format='{message}', level="INFO")
query_dbver = session.query(DBVersion).first()
if query_dbver is None:
session.add_all([DBVersion(value='3')])
session.add_all([DBVersion(value=str(BotDBUtil.database_version))])
session.commit()
query_dbver = session.query(DBVersion).first()
if (current_ver := int(query_dbver.value)) < (target_ver := BotDBUtil.database_version):

View file

@ -273,8 +273,8 @@ class FetchTarget(FT):
_tsk = []
fetch_base_superuser = await FetchTarget.fetch_target(base_superuser)
if fetch_base_superuser:
await fetch_base_superuser.sendDirectMessage(
'群消息发送被服务器拦截,已暂停群消息发送,使用~resume命令恢复推送。')
await fetch_base_superuser.\
sendDirectMessage(fetch_base_superuser.parent.locale.t("error.message.paused"))
except Exception:
Logger.error(traceback.format_exc())

View file

@ -30,5 +30,5 @@ class CFG:
Config = CFG().config
CachePath = abspath(Config('cache_path'))
CachePath = Config('cache_path')
DBPath = Config('db_path')

View file

@ -9,7 +9,7 @@ dc_token =
tg_token =
openai_api_key =
nl2c_model =
curseforge_api_key =
[cfg]
debug = False

View file

@ -7,7 +7,7 @@ from core.builtins.message import MessageSession as MS
from core.builtins.message.chain import MessageChain
from core.logger import Logger
from core.types import Session, MsgInfo, FetchTarget as FT, \
FetchedSession as FS, FinishedSession as FinS, AutoSession as AS
FetchedSession as FS, FinishedSession as FinS, AutoSession as AS, AutoSession
class FinishedSession(FinS):
@ -79,6 +79,21 @@ class Template(MS):
self.session.message = c
return self
async def waitReply(self, msgchain, quote=True, all_=False, append_instruction=True):
msgchain = MessageChain(msgchain)
if append_instruction:
msgchain.append(Plain(self.locale.t("message.reply.prompt")))
send = await self.sendMessage(msgchain, quote)
c = input('Reply: ')
return Template(target=MsgInfo(targetId='TEST|Console|0',
senderId='TEST|0',
senderName='',
targetFrom='TEST|Console',
senderFrom='TEST', clientName='TEST', messageId=0,
replyId=None),
session=AutoSession(message=c, target='TEST|Console|0', sender='TEST|0',
auto_interactions=None))
def asDisplay(self, text_only=False):
return self.session.message
@ -151,4 +166,3 @@ class FetchTarget(FT):
Bot.MessageSession = Template
Bot.FetchTarget = FetchTarget

View file

@ -8,6 +8,7 @@ from typing import Dict, Union
from core.builtins import PrivateAssets
from core.logger import Logger
from core.types import Module
from core.utils.i18n import load_locale_file
from core.types.module.component_meta import CommandMeta, RegexMeta, ScheduleMeta
load_dir_path = os.path.abspath('./modules/')
@ -15,6 +16,10 @@ load_dir_path = os.path.abspath('./modules/')
def load_modules():
err_prompt = []
locale_err = load_locale_file()
if locale_err:
locale_err.append('i18n:')
err_prompt.append('\n'.join(locale_err))
fun_file = None
dir_list = os.listdir(load_dir_path)
for file_name in dir_list:

View file

@ -40,7 +40,7 @@ async def msg_counter(msg: MessageSession, command: str):
else:
same['count'] += 1
if same['count'] > 10:
raise AbuseWarning('一段时间内使用相同命令的次数过多')
raise AbuseWarning(msg.locale.t("tos.reason.cooldown"))
all_ = counter_all.get(msg.target.senderId)
if all_ is None or datetime.now().timestamp() - all_['ts'] > 300: # 检查是否滥用(重复使用同一命令)
counter_all[msg.target.senderId] = {'count': 1,
@ -48,7 +48,7 @@ async def msg_counter(msg: MessageSession, command: str):
else:
all_['count'] += 1
if all_['count'] > 20:
raise AbuseWarning('一段时间内使用命令的次数过多')
raise AbuseWarning(msg.locale.t("tos.reason.abuse"))
async def temp_ban_check(msg: MessageSession):
@ -58,15 +58,12 @@ async def temp_ban_check(msg: MessageSession):
if ban_time < 300:
if is_temp_banned['count'] < 2:
is_temp_banned['count'] += 1
return await msg.finish('提示:\n'
'由于你的行为触发了警告,我们已对你进行临时限制。\n'
f'距离解封时间还有{str(int(300 - ban_time))}秒。')
return await msg.finish(msg.locale.t("tos.tempbanned", ban_time=str(int(300 - ban_time))))
elif is_temp_banned['count'] <= 5:
is_temp_banned['count'] += 1
return await msg.finish('即使是触发了临时限制,继续使用命令还是可能会导致你被再次警告。\n'
f'距离解封时间还有{str(int(300 - ban_time))}秒。')
return await msg.finish(msg.locale.t("tos.tempbanned.warning", ban_time=str(int(300 - ban_time))))
else:
raise AbuseWarning('无视临时限制警告')
raise AbuseWarning(msg.locale.t("tos.reason.bypass"))
async def parser(msg: MessageSession, require_enable_modules: bool = True, prefix: list = None,
@ -176,7 +173,12 @@ async def parser(msg: MessageSession, require_enable_modules: bool = True, prefi
module: Module = modules[command_first_word]
if not module.command_list.set: # 如果没有可用的命令,则展示模块简介
if module.desc is not None:
desc = msg.locale.t("parser.module.desc", desc=module.desc)
desc_ = module.desc
if locale_str := re.findall(r'\{(.*)}', desc_):
for l in locale_str:
desc_ = desc_.replace(f'{{{l}}}', msg.locale.t(l, fallback_failed_prompt=False))
desc = msg.locale.t("parser.module.desc", desc=desc_)
if command_first_word not in msg.enabled_modules:
desc += '\n' + msg.locale.t("parser.module.disabled.prompt", module=command_first_word,
prefix=msg.prefixes[0])
@ -240,7 +242,7 @@ async def parser(msg: MessageSession, require_enable_modules: bool = True, prefi
raise FinishedException(msg.sent) # if not using msg.finish
except InvalidCommandFormatError:
await msg.sendMessage(msg.locale.t("parser.command.format.invalid",
module=command_first_word))
module=command_first_word, prefix=msg.prefixes[0]))
"""if msg.options.get('typo_check', True): # 判断是否开启错字检查
nmsg, command_first_word, command_split = await typo_check(msg,
display_prefix,
@ -271,7 +273,7 @@ async def parser(msg: MessageSession, require_enable_modules: bool = True, prefi
await func.function(msg)
raise FinishedException(msg.sent) # if not using msg.finish
except ActionFailed:
await msg.sendMessage('消息发送失败,可能被风控,请稍后再试。')
await msg.sendMessage(msg.locale.t("error.message.limited"))
except FinishedException as e:
time_used = datetime.now() - time_start
@ -284,6 +286,12 @@ async def parser(msg: MessageSession, require_enable_modules: bool = True, prefi
if enable_analytics:
BotDBUtil.Analytics(msg).add(msg.trigger_msg, command_first_word, 'normal')
except AbuseWarning as e:
if enable_tos:
await warn_target(msg, str(e))
temp_ban_counter[msg.target.senderId] = {'count': 1,
'ts': datetime.now().timestamp()}
except NoReportException as e:
Logger.error(traceback.format_exc())
err_msg = str(e)
@ -380,18 +388,24 @@ async def parser(msg: MessageSession, require_enable_modules: bool = True, prefi
for l in locale_str:
err_msg = err_msg.replace(f'{{{l}}}', msg.locale.t(l, fallback_failed_prompt=False))
await msg.sendMessage(msg.locale.t("error.prompt.noreport", err_msg=err_msg))
except AbuseWarning as e:
if enable_tos:
await warn_target(msg, str(e))
temp_ban_counter[msg.target.senderId] = {'count': 1,
'ts': datetime.now().timestamp()}
except Exception as e:
Logger.error(traceback.format_exc())
await msg.sendMessage(msg.locale.t('error.prompt.report', err_msg=str(e)) +
str(Url(Config('bug_report_url'))))
finally:
ExecutionLockList.remove(msg)
except ActionFailed:
await msg.sendMessage('消息发送失败,可能被风控,请稍后再试。')
await msg.sendMessage((msg.locale.t("error.message.limited")))
continue
return msg
except AbuseWarning as e:
if enable_tos:
await warn_target(msg, str(e))
temp_ban_counter[msg.target.senderId] = {'count': 1,
'ts': datetime.now().timestamp()}
except WaitCancelException: # 出现于等待被取消的情况
Logger.warn('Waiting task cancelled by user.')

View file

@ -34,13 +34,14 @@ def private_ip_check(url: str):
f'Attempt of requesting private IP addresses is not allowed, requesting {hostname}.')
async def get_url(url: str, status_code: int = False, headers: dict = None, fmt=None, timeout=20, attempt=3,
async def get_url(url: str, status_code: int = False, headers: dict = None, params: dict = None, fmt=None, timeout=20, attempt=3,
request_private_ip=False, logging_err_resp=True):
"""利用AioHttp获取指定url的内容。
:param url: 需要获取的url
:param status_code: 指定请求到的状态码若不符则抛出ValueError
:param headers: 请求时使用的http头
:param params: 请求时使用的参数
:param fmt: 指定返回的格式
:param timeout: 超时时间
:param attempt: 指定请求尝试次数
@ -60,7 +61,7 @@ async def get_url(url: str, status_code: int = False, headers: dict = None, fmt=
connector=TCPConnector(verify_ssl=False) if debug else None, ) as session:
try:
async with session.get(url, timeout=aiohttp.ClientTimeout(total=timeout), headers=headers,
proxy=proxy) as req:
proxy=proxy, params=params) as req:
Logger.debug(f'[{req.status}] {url}')
if logging_resp:
Logger.debug(await req.read())

View file

@ -30,6 +30,7 @@ def flatten(d, parent_key='', sep='.'):
def load_locale_file():
err_prompt = []
locales_path = os.path.abspath('./locales')
locales = os.listdir(locales_path)
for l in locales:
@ -41,14 +42,18 @@ def load_locale_file():
if os.path.exists(f'{modules_path}/{m}/locales'):
locales_m = os.listdir(f'{modules_path}/{m}/locales')
for lm in locales_m:
with open(f'{modules_path}/{m}/locales/{lm}', 'r', encoding='utf-8') as f:
if remove_suffix(lm, '.json') in locale_cache:
locale_cache[remove_suffix(lm, '.json')].update(flatten(json.load(f)))
else:
locale_cache[remove_suffix(lm, '.json')] = flatten(json.load(f))
ml = f'{modules_path}/{m}/locales/{lm}'
with open(ml, 'r', encoding='utf-8') as f:
try:
if remove_suffix(lm, '.json') in locale_cache:
locale_cache[remove_suffix(lm, '.json')].update(flatten(json.load(f)))
else:
locale_cache[remove_suffix(lm, '.json')] = flatten(json.load(f))
except Exception as e:
err_prompt.append(f'Failed to load {ml}: {e}')
return err_prompt
load_locale_file()
class LocaleFile(TypedDict):

View file

@ -1,8 +1,26 @@
from typing import List
import traceback
import base64
from os.path import abspath
from typing import List, Union
import aiohttp
from config import Config
from core.logger import Logger
from core.types.message.chain import MessageChain
from PIL import Image as PImage
import ujson as json
import filetype as ft
from core.builtins import Image
from core.builtins import Plain, Image, Voice, Embed
from core.utils.cache import random_cache_path
from core.utils.http import download_to_cache
from aiofile import async_open
web_render = Config('web_render')
web_render_local = Config('web_render_local')
async def image_split(i: Image) -> List[Image]:
@ -20,3 +38,75 @@ async def image_split(i: Image) -> List[Image]:
i_list.append(Image(i.crop((0, _h, iw, crop_h))))
_h = crop_h
return i_list
save_source = True
async def msgchain2image(msgchain: Union[List, MessageChain], use_local=True):
if not web_render_local:
if not web_render:
Logger.warn('[Webrender] Webrender is not configured.')
return False
use_local = False
if isinstance(msgchain, List):
msgchain = MessageChain(msgchain)
lst = []
html_template = """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="botbox"'>
${content}
</div>
</body>
</html>"""
for m in msgchain.elements:
if isinstance(m, Plain):
lst.append('<div>' + m.text.replace('\n', '<br>') + '</div>')
if isinstance(m, Image):
async with async_open(await m.get(), 'rb') as fi:
data = await fi.read()
try:
ftt = ft.match(data)
lst.append(f'<img src="data:{ftt.mime};base64,{(base64.encodebytes(data)).decode("utf-8")}" width="720" />')
except TypeError:
traceback.print_exc()
if isinstance(m, Voice):
lst.append('<div>[Voice]</div>')
if isinstance(m, Embed):
lst.append('<div>[Embed]</div>')
pic = False
d = {'content': html_template.replace('${content}', '\n'.join(lst)), 'element': '.botbox'}
html_ = json.dumps(d)
fname = random_cache_path() + '.html'
with open(fname, 'w', encoding='utf-8') as fi:
fi.write(d['content'])
try:
pic = await download_to_cache((web_render_local if use_local else web_render) + 'element_screenshot',
status_code=200,
headers={'Content-Type': 'application/json'},
method="POST",
post_data=html_,
attempt=1,
timeout=30,
request_private_ip=True
)
except aiohttp.ClientConnectorError:
if use_local:
pic = await download_to_cache(web_render, method='POST', headers={
'Content-Type': 'application/json',
}, post_data=html_, request_private_ip=True)
else:
return False
return pic

View file

@ -25,13 +25,24 @@ async def _(session: MessageSession):
@test.command('reply')
async def _(session: MessageSession):
# >>> ~test reply
# <<< Send a word
# >>> Hello World!
# <<< Reply me!
# >>> Hello World! >> [Reply me!]
# <<< Hello World!
s = await session.waitReply('Send a word')
await s.sendMessage(s.asDisplay())
@test.command('confirm')
async def _(session: MessageSession):
# >>> ~test confirm
# <<< Are you sure?
# >>> Yes
# <<< OK!
s = await session.waitConfirm('Are you sure?')
if s:
await s.sendMessage('OK!')
@test.command('image')
async def _(session: MessageSession):
# >>> ~test image

View file

@ -3,6 +3,8 @@
"error.prompt": "An error occurred: ${error_msg}\nReport this issue: ",
"error.prompt.report": "An error occurred while executing the command. Please report the following to developers:\n${err_msg}\nReport this issue: ",
"error.prompt.noreport": "An error occurred while executing the command:\n${err_msg}\nThis error is not caused by the bot (e.g. the API request went wrong) and thus should not be reported to developers.",
"error.message.limited": "Message sending failed, possibly restricted by server. Please try again later.",
"error.message.paused": "群消息发送被服务器拦截,已暂停群消息发送,使用 ${prefix}resume 命令恢复推送。",
"error.message.chain.invalid": "The bot attempted to send an invalid message chain. Please get in touch with the developers to solve this issue.",
"error.message.chain.empty": "The bot attempted to send an empty message chain. Please get in touch with the developers to solve this issue.",
"error.message.chain.plain.empty": "The bot attempted to send an empty text message. Please get in touch with the developers to solve this issue.",
@ -14,17 +16,23 @@
"error.request.api.timeout": "API request timeout.",
"tos.warning": "Warning:\nYou have violated our Code of Conduct according to our Terms of Service.",
"tos.reason": "Reason: ",
"tos.reason.cooldown": "一段时间内使用相同命令的次数过多。",
"tos.reason.abuse": "一段时间内使用命令的次数过多。",
"tos.reason.bypass": "无视临时封禁警告。",
"tos.warning.count": "You have received ${current_warns} warnings. Your account will be blacklisted if you receive more than 5 warnings.",
"tos.warning.appeal": "If you have any objections, please go to ${issue_url} and create an issue.",
"tos.warning.last": "This is your last warning.",
"tos.tempbanned": "提示:\n由于你的行为触发了警告我们已对你进行临时封禁。\n距离解封时间还有 ${ban_time} 秒。",
"tos.tempbanned.warning": "提示:\n即使是触发了临时封禁继续使用命令还是可能会导致你被再次警告。\n距离解封时间还有 ${ban_time} 秒。",
"parser.command.running.prompt": "There are currently commands running. Please try again later.",
"parser.command.running.prompt2": "The previous command is being executed.",
"parser.command.format.invalid": "Syntax Error.\nUse \"~help ${module}\" for help.",
"parser.command.format.invalid": "Syntax Error.\nUse \"${prefix}help ${module}\" for help.",
"parser.sudo.permission.denied": "You are not a superuser and cannot use the sudo command.",
"parser.superuser.permission.denied": "You do not have permission to use this command.",
"parser.admin.module.permission.denied": "Commands under the \"${module}\" module can only be used by the admins of the group. Please contact the admins to execute the command.",
"parser.admin.submodule.permission.denied": "This command can only be used by the admins of the group. Please contact the admins to execute the command.",
"parser.module.disabled.prompt": "\"${module}\" module is not enabled, please send ${prefix}enable ${module} to enable the module.",
"error": "An error occurred: ",
"example": "Hello world!",
"success": "Success.",
"yes": "Yes",

View file

@ -3,6 +3,8 @@
"error.prompt": "发生错误:${error_msg}\n错误汇报地址",
"error.prompt.report": "执行命令时发生错误,请报告机器人开发者:\n${err_msg}\n错误汇报地址",
"error.prompt.noreport": "执行命令时发生错误:\n${err_msg}\n此问题并非机器人程序错误API 请求出错等),请勿将此消息报告给机器人开发者。",
"error.message.limited": "消息发送失败,可能被风控,请稍后再试。",
"error.message.paused": "群消息发送被服务器拦截,已暂停群消息发送,使用 ${prefix}resume 命令恢复推送。",
"error.message.chain.invalid": "机器人尝试发送非法消息链,请联系机器人开发者解决问题。",
"error.message.chain.empty": "机器人尝试发送空消息链,请联系机器人开发者解决问题。",
"error.message.chain.plain.empty": "机器人尝试发送空文本消息,请联系机器人开发者解决问题。",
@ -14,17 +16,23 @@
"error.request.api.timeout": "请求 API 超时。",
"tos.warning": "警告:\n根据服务条款你已违反我们的行为准则。",
"tos.reason": "具体原因:",
"tos.reason.cooldown": "一段时间内使用相同命令的次数过多。",
"tos.reason.abuse": "一段时间内使用命令的次数过多。",
"tos.reason.bypass": "无视临时封禁警告。",
"tos.warning.count": "这是对你的第 ${current_warns} 次警告。如超过 5 次警告,我们将会把你的账户加入黑名单。",
"tos.warning.appeal": "如果你有任何异议,请至 ${issue_url} 发起问题。",
"tos.warning.last": "这是对你的最后一次警告。",
"tos.tempbanned": "提示:\n由于你的行为触发了警告我们已对你进行临时封禁。\n距离解封时间还有 ${ban_time} 秒。",
"tos.tempbanned.warning": "提示:\n即使是触发了临时封禁继续使用命令还是可能会导致你被再次警告。\n距离解封时间还有 ${ban_time} 秒。",
"parser.command.running.prompt": "当前有命令正在执行,请稍后再试。",
"parser.command.running.prompt2": "先前的命令正在执行中。",
"parser.command.format.invalid": "语法错误。\n使用 ~help ${module} 查看帮助。",
"parser.command.format.invalid": "语法错误。\n使用 ${prefix}help ${module} 查看帮助。",
"parser.sudo.permission.denied": "你不是本机器人的超级用户,无法使用 sudo 命令。",
"parser.superuser.permission.denied": "你没有使用该命令的权限。",
"parser.admin.module.permission.denied": "${module} 模块下的命令仅能被该群组的管理员所使用,请联系管理员执行此命令。",
"parser.admin.submodule.permission.denied": "此命令仅能被该群组的管理员所使用,请联系管理员执行此命令。",
"parser.module.disabled.prompt": "${module} 模块未启用,请发送 ${prefix}enable ${module} 启用本模块。",
"error": "发生错误:",
"example": "你好世界!",
"success": "成功。",
"yes": "是",

View file

@ -3,6 +3,8 @@
"error.prompt": "發生錯誤:${error_msg}\n錯誤回報網址",
"error.prompt.report": "執行指令時發生錯誤,請回報機器人開發人員:\n${err_msg}\n錯誤回報網址",
"error.prompt.noreport": "執行指令時發生錯誤:\n${err_msg}\n此問題並非機器人程式錯誤API 請求錯誤等),請勿將此訊息回報給機器人開發人員。",
"error.message.limited": "訊息傳送失敗,可能被風控,請稍後再試。",
"error.message.paused": "群消息发送被服务器拦截,已暂停群消息发送,使用 ${prefix}resume 命令恢复推送。",
"error.message.chain.invalid": "機器人嘗試傳送無效訊息鏈,請聯絡機器人開發人員解決問題。",
"error.message.chain.empty": "機器人嘗試傳送空白訊息鏈,請聯絡機器人開發人員解決問題。",
"error.message.chain.plain.empty": "機器人嘗試傳送空白文字訊息,請聯絡機器人開發人員解決問題。",
@ -14,23 +16,29 @@
"error.request.api.timeout": "請求 API 逾時。",
"tos.warning": "警告:\n依據使用條款你已違反我們的行為準則。",
"tos.reason": "原因:",
"tos.reason.cooldown": "一段时间内使用相同命令的次数过多。",
"tos.reason.abuse": "一段时间内使用命令的次数过多。",
"tos.reason.bypass": "无视临时封禁警告。",
"tos.warning.count": "這是第 ${current_warns} 次警告。如超過 5 次警告,我們將會把你的帳戶加入黑名單。",
"tos.warning.appeal": "如果你有任何異義,請至 ${issue_url} 發起問題。",
"tos.warning.last": "這是最後警告。",
"tos.tempbanned": "提示:\n由于你的行为触发了警告我们已对你进行临时封禁。\n距离解封时间还有 ${ban_time} 秒。",
"tos.tempbanned.warning": "提示:\n即使是触发了临时封禁继续使用命令还是可能会导致你被再次警告。\n距离解封时间还有 ${ban_time} 秒。",
"parser.command.running.prompt": "目前有指令正在執行,請稍後再試。",
"parser.command.running.prompt2": "先前的指令正在執行中。",
"parser.command.format.invalid": "語法錯誤。\n使用 ~help ${module} 檢視說明。",
"parser.command.format.invalid": "語法錯誤。\n使用 ${prefix}help ${module} 檢視說明。",
"parser.sudo.permission.denied": "你不是本機器人的超級使用者,無法使用 sudo 指令。",
"parser.superuser.permission.denied": "你沒有使用此指令的權限。",
"parser.admin.module.permission.denied": "${module} 模組下的指令僅能由該群組的管理員所使用,請聯絡管理員執行此指令。",
"parser.admin.submodule.permission.denied": "此指令僅能由該群組的管理員所使用,請聯絡管理員執行此指令。",
"parser.module.disabled.prompt": "${module} 模組未啟用,請發送 ${prefix}enable ${module} 啟用此模組。",
"parser.module.disabled.prompt": "${module} 模組未啟用,請傳送 ${prefix}enable ${module} 啟用此模組。",
"error": "發生錯誤:",
"example": "你好世界!",
"success": "成功。",
"yes": "是",
"no": "否",
"message.wait.confirm.prompt.type1": "送「是」或符合確認條件的詞語確認)",
"message.wait.confirm.prompt.type2": "送符合條件的詞語確認)",
"message.wait.confirm.prompt.type1": "送「是」或符合確認條件的詞語確認)",
"message.wait.confirm.prompt.type2": "送符合條件的詞語確認)",
"message.reply.prompt": "(請使用指定的詞語回覆此訊息)",
"core.help.none": "(此模組沒有說明資訊)",
"core.help.options": "參數:",

View file

@ -30,7 +30,7 @@ class WithErrCode(Exception):
'b30 unofficial [<friendcode>] {{arcaea.message.unofficial}}')
async def _(msg: Bot.MessageSession):
if not os.path.exists(assets_path):
await msg.finish(msg.locale.t("arcaea.message.assets.not_found"))
await msg.finish(msg.locale.t("arcaea.message.assets.not_found", prefix=msg.prefixes[0]))
query_code = None
prefer_uses = msg.options.get('arc_api', None)
official = msg.parsed_msg.get('official', False)
@ -97,7 +97,7 @@ async def _(msg: Bot.MessageSession):
traceback.print_exc()
await msg.finish(msg.locale.t("arcaea.message.unofficial.fetch.failed"))
else:
await msg.finish(msg.locale.t("arcaea.message.user.unbound"))
await msg.finish(msg.locale.t("arcaea.message.user.unbound", prefix=msg.prefixes[0]))
@arc.command('info [<friendcode>] {{arcaea.info.help}}',
@ -105,7 +105,7 @@ async def _(msg: Bot.MessageSession):
'info unofficial [<friendcode>] {{arcaea.message.unofficial}}', )
async def _(msg: Bot.MessageSession):
if not os.path.exists(assets_path):
await msg.sendMessage(msg.locale.t("arcaea.message.assets.not_found"))
await msg.sendMessage(msg.locale.t("arcaea.message.assets.not_found", prefix=msg.prefixes[0]))
return
query_code = None
prefer_uses = msg.options.get('arc_api', None)
@ -152,7 +152,7 @@ async def _(msg: Bot.MessageSession):
traceback.print_exc()
await msg.finish(msg.locale.t("arcaea.message.unofficial.fetch.failed"))
else:
await msg.finish(msg.locale.t("arcaea.message.user.unbound"))
await msg.finish(msg.locale.t("arcaea.message.user.unbound", prefix=msg.prefixes[0]))
@arc.command('song <songname+prs/pst/byd> {{arcaea.song.help}}')

View file

@ -21,7 +21,7 @@
"arcaea.errcode.-20": "File does not exist",
"arcaea.errcode.-23": "Internal error occurred",
"arcaea.errcode.-233": "Unknown error occurred",
"arcaea.message.assets.not_found": "No resource files found! Please place the apk files of Arcaea to the robot's assets directory and rename them to \"arc.apk\", use \"~arcaea\" to initialize resources.",
"arcaea.message.assets.not_found": "No resource files found! Please place the apk files of Arcaea to the robot's assets directory and rename them to \"arc.apk\", use \"${prefix}arcaea initialize\" to initialize resources.",
"arcaea.message.failed": "Failed to query.",
"arcaea.message.failed.errcode": "Failed to query: ",
"arcaea.message.failed.fetch": "Failed to fetch.",
@ -32,7 +32,7 @@
"arcaea.message.official.fetch.failed.fallback": "Failed to fetch using the official API. Trying to use unofficial API.",
"arcaea.message.unofficial": "Use Unofficial API",
"arcaea.message.unofficial.fetch.failed": "Failed to query using the unofficial API.",
"arcaea.message.user.unbound": "Unbound user. Please bind user by \"~arcaea bind <friendcode>\".",
"arcaea.message.user.unbound": "Unbound user. Please bind user by \"${prefix}arcaea bind <friendcode>\".",
"arcaea.message.no_webrender": "No webrender configured, this command cannot be used.",
"arcaea.b30.help": "Query the best 30 list of Arcaea user. (Automatically select to use API)",
"arcaea.b30.message.success": "Result\nBest 30${b30} | Recent 10${r10}\nBest 30 last 5 list: \n${last5list}",

View file

@ -21,7 +21,7 @@
"arcaea.errcode.-20": "文件不存在",
"arcaea.errcode.-23": "发生了内部错误",
"arcaea.errcode.-233": "发生了未知错误",
"arcaea.message.assets.not_found": "未找到资源文件!请放置一份 Arcaea 的 apk 文件到机器人的 assets 目录并重命名为 arc.apk 后,使用 ~arcaea initialize 初始化资源。",
"arcaea.message.assets.not_found": "未找到资源文件!请放置一份 Arcaea 的 apk 文件到机器人的 assets 目录并重命名为 arc.apk 后,使用 ${prefix}arcaea initialize 初始化资源。",
"arcaea.message.failed": "查询失败。",
"arcaea.message.failed.errcode": "查询失败:",
"arcaea.message.failed.fetch": "获取失败。",
@ -32,7 +32,7 @@
"arcaea.message.official.fetch.failed.fallback": "使用官方 API 获取失败,尝试使用非官方接口。",
"arcaea.message.unofficial": "使用非官方 API",
"arcaea.message.unofficial.fetch.failed": "使用非官方 API 查询失败!",
"arcaea.message.user.unbound": "未绑定用户,请使用 ~arcaea bind <friendcode> 绑定一个用户。",
"arcaea.message.user.unbound": "未绑定用户,请使用 ${prefix}arcaea bind <friendcode> 绑定一个用户。",
"arcaea.message.no_webrender": "未配置 webrender无法使用此命令。",
"arcaea.b30.help": "查询 Arcaea 用户的 b30 列表。(自动选择使用 API",
"arcaea.b30.message.success": "获取结果\nB30${b30} | R10${r10}\nB30 倒 5 列表:\n${last5list}",

View file

@ -21,7 +21,7 @@
"arcaea.errcode.-20": "檔案不存在",
"arcaea.errcode.-23": "發生了內部錯誤",
"arcaea.errcode.-233": "發生了不明錯誤",
"arcaea.message.assets.not_found": "找不到資源檔案! 請放置一份 Arcaea 的 apk 檔案到機器人的 assets 目錄並重命名為 arc.apk 後,使用 ~arcaea initialize 初始化資源。",
"arcaea.message.assets.not_found": "找不到資源檔案! 請放置一份 Arcaea 的 apk 檔案到機器人的 assets 目錄並重命名為 arc.apk 後,使用 ${prefix}arcaea initialize 初始化資源。",
"arcaea.message.failed": "查詢失敗。",
"arcaea.message.failed.errcode": "查詢失敗:",
"arcaea.message.failed.fetch": "取得失敗。",
@ -32,7 +32,7 @@
"arcaea.message.official.fetch.failed.fallback": "使用官方 API 取得失敗,嘗試使用非官方介面。",
"arcaea.message.unofficial": "使用非官方 API",
"arcaea.message.unofficial.fetch.failed": "使用非官方 API 查詢失敗!",
"arcaea.message.user.unbound": "未綁定使用者,請使用 ~arcaea bind <friendcode> 綁定一個使用者。",
"arcaea.message.user.unbound": "未綁定使用者,請使用 ${prefix}arcaea bind <friendcode> 綁定一個使用者。",
"arcaea.message.no_webrender": "未配置 webrender無法使用此指令。",
"arcaea.b30.help": "查詢 Arcaea 使用者的 b30 列表。(自動選擇使用 API",
"arcaea.b30.message.success": "取得結果\nB30${b30} | R10${r10}\nB30 倒 5 列表:\n${last5list}",

View file

@ -1,7 +1,6 @@
{
"coin.begin": "You toss ${count} coin(s),",
"coin.help": "Toss any number of coins.",
"coin.error": "An error occurred: ",
"coin.error.amount": "An error occurred: Invalid number of coins: ",
"coin.error.max": "An error occurred: You can only toss at most ${max} coins at one time.",
"coin.error.nocoin": "An error occurred: You toss no coin, and nothing happened...",

View file

@ -1,7 +1,6 @@
{
"coin.begin": "你抛了${count} 枚硬币,",
"coin.help": "抛n枚硬币",
"coin.error": "发生错误:",
"coin.error.amount": "发生错误:无效的硬币个数:",
"coin.error.max": "发生错误:你最多只能抛 ${max} 个硬币",
"coin.error.nocoin": "发生错误:你抛了个空气,什么也没发生...",

View file

@ -1,7 +1,6 @@
{
"coin.begin": "你拋了 ${count} 枚硬幣,",
"coin.help": "拋任意枚硬幣。",
"coin.error": "發生錯誤:",
"coin.error.amount": "發生錯誤:無效的硬幣數量:",
"coin.error.max": "發生錯誤:你最多只能拋 ${max} 枚硬幣。",
"coin.error.nocoin": "發生錯誤:你拋了 0 枚硬幣,什麼也沒有發生...",
@ -22,7 +21,7 @@
"coin.mix.tail": "${tail} 枚是反面",
"coin.mix.stand": "…還有 ${stand} 枚立起來了!",
"coin.mix.end": "。",
"coin_regex.help": "啟用後將在送的聊天內容尋找到以下相符的訊息時執行對應指令:\n",
"coin_regex.help": "啟用後將在送的聊天內容尋找到以下相符的訊息時執行對應指令:\n",
"coin.stand": "…它立起来了!",
"coin.stand.all": "它們…\n…全都立起来了"
}

View file

@ -4,7 +4,7 @@
"core.alias.help.reset": "重設自訂指令別名。",
"core.alias.help.list": "列出自訂指令別名列表。",
"core.alias.message.add.invalid_prefix": "新增的別名對應的指令必須以指令前綴開頭,請檢查。",
"core.alias.message.add.success": "已添加自訂指令別名:${arg1} -> ${arg2}",
"core.alias.message.add.success": "已新增自訂指令別名:${arg1} -> ${arg2}",
"core.alias.message.add.already_in": "[${arg1}]別名已存在於自訂別名列表。",
"core.alias.message.remove.success": "已移除自訂指令別名:${arg1}",
"core.alias.message.remove.not_found": "[${arg1}]別名不存在於自訂別名列表。",
@ -40,7 +40,7 @@
"core.module.message.reload.confirm": "此操作將額外同時重新載入以下模組:\n${modules}\n是否繼續",
"core.module.message.reload.permission.denied": "失敗:你沒有重新載入模組的權限。",
"core.module.message.recommends": "建議同時啟用以下模組:\n${msgs}\n是否一同啟用",
"core.module.message.help.support_regex": "此模組支援正規表示式,訊息送時將會尋找相符的以下內容:",
"core.module.message.help.support_regex": "此模組支援正規表示式,訊息送時將會尋找相符的以下內容:",
"core.module.message.help.regex.detail": "${msg}",
"core.module.message.help.regex.no_information": "無描述",
"core.module.message.help.author.type1": "模組作者:",
@ -115,7 +115,7 @@
"core.locale.help": "用於設定機器人使用的語言。",
"core.locale.help.locale": "設定機器人使用的語言。",
"core.locale.message.invalid": "語言格式錯誤,已支援的語言有:${lang}。",
"core.whoami.help": "取得送指令的帳戶在機器人內部的 ID。",
"core.whoami.help": "取得送指令的帳戶在機器人內部的 ID。",
"core.whoami.message.admin": "(你擁有此對話的管理員權限)",
"core.whoami.message.botadmin": "(你擁有此對話的機器人管理員權限)",
"core.whoami.message.superuser": "(你擁有此機器人的超級使用者權限)",

View file

@ -405,7 +405,7 @@ async def modules_help(msg: Bot.MessageSession):
appends = [module_.bind_prefix]
doc_ = []
help_ = CommandParser(
module_, bind_prefix=module_.bind_prefix, command_prefixes=msg.prefixes)
module_, bind_prefix=module_.bind_prefix, command_prefixes=msg.prefixes, msg=msg)
if module_.desc is not None:
doc_.append(module_.desc)
if help_.args:

View file

@ -6,7 +6,7 @@
"github.user.message.not_found": "The given user cannot be found; please check your input.",
"github.search.help": "Searching repositories on GitHub.",
"github.search.message": "Successfully to search for ${result} results:",
"github.search.message.more": "Truncated due to chat limits; ${more_result} more results may not be shown.",
"github.search.message.not_found": "The given repository cannot be found; please check your input.",
"github.message.error": "An error occurred: The given repository cannot be found; please check your spelling."
"github.message.error": "An error occurred: The given repository cannot be found; please check your spelling.",
"github.search.message.more_information": "Truncated due to chat limits; ${more_result} more results may not be shown."
}

View file

@ -1,12 +1,12 @@
{
"github.help": "尝试自动识别并区分 repo/user。",
"github.repo.help": "获取 GitHub 库信息。",
"github.repo.message.not_found": "此库不存在,请检查输入。",
"github.repo.help": "获取 GitHub 存储库信息。",
"github.repo.message.not_found": "此存储库不存在,请检查输入。",
"github.user.help": "获取 GitHub 用户或组织信息。",
"github.user.message.not_found": "查无此人,请检查输入。",
"github.search.help": "搜索 GitHub 上的库。",
"github.search.help": "搜索 GitHub 上的存储库。",
"github.search.message": "搜索成功,共 ${result} 条结果:",
"github.search.message.more": "另有 ${more_result} 条结果未显示。",
"github.search.message.not_found": "找不到仓库,请检查输入。",
"github.message.error": "发生错误:找不到仓库,请检查拼写是否正确。"
"github.search.message.not_found": "找不到存储库,请检查输入。",
"github.message.error": "发生错误:找不到存储库,请检查拼写是否正确。",
"github.search.message.more_information": "另有 ${more_result} 条结果未显示。"
}

View file

@ -1,12 +1,12 @@
{
"github.help": "尝试自动识别并区分 repo/user。",
"github.repo.help": "获取 GitHub 仓库信息。",
"github.repo.message.not_found": "此仓库不存在,请检查输入。",
"github.user.help": "获取 GitHub 用户或组织信息。",
"github.user.message.not_found": "查无此人,请检查输入。",
"github.search.help": "搜索 GitHub 上的仓库。",
"github.search.message": "搜索成功,共 ${result} 条结果:",
"github.search.message.more": "另有 ${more_result} 条结果未显示。",
"github.help": "嘗試自動識別並區分 repo/user。",
"github.repo.help": "取得 Github 儲存庫資訊。",
"github.repo.message.not_found": "此儲存庫不存在,請檢查輸入。",
"github.user.help": "取得 Github 使用者或組織資訊。",
"github.user.message.not_found": "找不到使用者,請檢查輸入。",
"github.search.help": "搜尋 Github 上的儲存庫。",
"github.search.message": "搜尋成功,共 ${result} 條結果:",
"github.search.message.not_found": "找不到仓库,请检查输入。",
"github.message.error": "发生错误:找不到仓库,请检查拼写是否正确。"
"github.message.error": "发生错误:找不到仓库,请检查拼写是否正确。",
"github.search.message.more_information": "另有 ${more_result} 條結果未顯示。"
}

View file

@ -21,7 +21,7 @@ async def search(msg: Bot.MessageSession):
items_out.append(str(item['full_name'] + ': ' + str(Url(item['html_url']))))
except TypeError:
continue
footnotes = msg.locale.t("github.search.message.more", more_result=result['total_count'] - 5) if item_count_expected == 5 else ''
footnotes = msg.locale.t("github.search.message.more_information", more_result=result['total_count'] - 5) if item_count_expected == 5 else ''
message = msg.locale.t("github.search.message", result=result['total_count']) + '\n' + '\n'.join(
items_out[0:item_count_expected]) + f'\n{footnotes}'

View file

@ -6,7 +6,8 @@ mcmod = module(
bind_prefix='mcmod',
desc='{mcmod.help.desc}',
developers=['Dianliang233', 'HornCopper', 'DrLee_lihr'],
alias={'moddetails': 'mcmod details'}
alias={'moddetails': 'mcmod details'},
support_languages=['zh_cn']
)

View file

@ -1,6 +1,6 @@
{
"mcmod.help.details": "通过模组内容的名称获取模组简介及链接,可使用物品/方块/实体的 ID 或准确名称。",
"mcmod.help.mod_name": "通过模组名称获取模组简介及链接,可使用无歧义缩写和准确名称。",
"mcmod.message.not_found": "找到结果。",
"mcmod.message.not_found": "到结果。",
"mcmod.help.desc": "从 MC 百科获取 Minecraft 模组信息。"
}

View file

@ -1,6 +1,6 @@
{
"mcmod.help.details": "透過模組內容的名稱取得模組簡介及連結,可使用物品/方塊/實體的 ID 或準確名稱。",
"mcmod.help.mod_name": "透過模組名稱取模組簡介及連結,可使用無歧義簡稱或準確名稱。",
"mcmod.help.mod_name": "透過模組名稱模組簡介及連結,可使用無歧義簡稱或準確名稱。",
"mcmod.message.not_found": "找不到結果。",
"mcmod.help.desc": "從 MC 百科取得 Minecraft 模組訊息。"
}

View file

@ -1,5 +1,5 @@
{
"mcplayer.help": "Get player information about Minecraft: Java Edition from the Mojang API.",
"mcplayer.help": "Get player information about Minecraft: Java Edition from Mojang API.",
"mcplayer.help.player": "Get player information from player name or UUID.",
"mcplayer.message.not_found": "${player}'s information not found."
}

View file

@ -18,7 +18,7 @@ meme = module(
async def _(msg: Bot.MessageSession):
# res_jiki = await jiki(msg.parsed_msg['<term>'])
# R.I.P. jikipedia
res_moegirl = await moegirl(msg.parsed_msg['<term>'])
res_moegirl = await moegirl(msg.parsed_msg['<term>'], msg.locale.locale)
res_nbnhhsh = await nbnhhsh(msg.parsed_msg['<term>'])
res_urban = await urban(msg.parsed_msg['<term>'])
chk = await check(res_moegirl, res_nbnhhsh, res_urban)

View file

@ -1,16 +1,18 @@
import re
from core.builtins import Bot
from core.logger import Logger
from modules.wiki import query_pages
from modules.wiki.utils.wikilib import QueryInfo
async def moegirl(term: str):
async def moegirl(term: str, locale: str = 'zh_cn'):
result = await query_pages(QueryInfo('https://zh.moegirl.org.cn/api.php', headers={'accept': '*/*',
'accept-encoding': 'gzip, deflate',
'accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,en-GB;q=0.6',
'content-type': 'application/json',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62'}),
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62'},
locale=locale),
term)
msg = ''
if result['msg_list']:
@ -28,7 +30,7 @@ async def moegirl(term: str):
'accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,en-GB;q=0.6',
'content-type': 'application/json',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62'
}), redirect)
}, locale=locale), redirect)
msg += wait['msg_list'][0].text
return '[萌娘百科] ' + msg

View file

@ -1,19 +1,20 @@
import re
import urllib.parse
from bs4 import BeautifulSoup
import asyncio
import traceback
from core.builtins import Bot
from core.component import module
from core.utils.http import get_url
from config import Config
mod_dl = module(
bind_prefix='mod_dl',
desc='下载CurseForge上的Mod。',
developers=['HornCopper', 'OasisAkari'],
desc='下载 CurseForge 和 Modrinth 上的 Mod。',
developers=['HornCopper', 'OasisAkari', 'z0z0r4'],
recommend_modules=['mcmod'],
alias='moddl')
x_api_key = Config("curseforge_api_key")
def cn_chk(string: str):
for word in string:
@ -21,97 +22,153 @@ def cn_chk(string: str):
return True
return False
source_url = 'https://files.xmdhs.com/curseforge/'
@mod_dl.handle('<mod_name> [<version>] {通过模组名获取模组下载链接CloudFlare CDN支持。}')
@mod_dl.handle('<mod_name> [<version>] {通过模组名获取模组下载链接}')
async def main(msg: Bot.MessageSession):
mod_name = msg.parsed_msg['<mod_name>']
ver = msg.parsed_msg.get('<version>', False)
ver = msg.parsed_msg.get('<version>', None)
if ver:
match_ver = re.match(r'^\d+\.\d+\.\d+$|^\d+\.\d+$|\d+w\d+[abcd]', ver)
if match_ver is None:
mod_name += ' ' + ver
ver = False
if cn_chk(mod_name):
return {'msg': 'CurseForge暂不支持中文搜索。', 'success': False}
full_url = f'{source_url}s?q={urllib.parse.quote(mod_name)}&type=1'
try:
html = await get_url(full_url, status_code=200)
bs = BeautifulSoup(html, 'html.parser')
information = bs.body.div.div
infos = {}
for x in information.find_all('a'):
infos[x.find('h3').text] = x.get('href')
if len(infos) > 1:
reply_text = []
i = 0
for info in infos:
i += 1
reply_text.append(f'{i}. {info}')
reply = await msg.waitReply('搜索结果如下:\n' + '\n'.join(reply_text) + '\n请回复编号来选择mod。')
replied = reply.asDisplay(text_only=True)
if replied.isdigit():
replied = int(replied)
if replied > len(infos):
return await msg.finish('编号超出范围。')
else:
mod_url = infos[list(infos.keys())[replied - 1]]
else:
return await msg.finish('无效的编号,必须为纯数字。')
else:
mod_url = infos[list(infos.keys())[0]]
html_2 = await get_url(f'{source_url}{mod_url[1:]}', status_code=200)
bs_2 = BeautifulSoup(html_2, 'html.parser')
information_2 = bs_2.body.div.div
infos_2 = {}
for x in information_2.find_all('a'):
infos_2[x.find('h3').text] = x.get('href')
return {'msg': '暂不支持中文搜索。', 'success': False}
async def search_modrinth(name: str, ver: str):
url = f'https://api.modrinth.com/v2/search?query={name}&limit=10'
if ver:
if ver in infos_2:
mod_url_2 = infos_2[ver]
else:
return await msg.finish('没有找到指定版本的模组。')
url += f'&facets=[["versions:{ver}"],["project_type:mod"]]'
else:
reply_text = []
for info2 in infos_2:
reply_text.append(f'{info2}')
reply2 = await msg.waitReply('此mod拥有如下版本\n' + '\n'.join(reply_text) + '\n请回复版本号来选择版本。')
replied2 = reply2.asDisplay(text_only=True)
if replied2 in infos_2:
mod_url_2 = infos_2[replied2]
ver = replied2
else:
return await msg.finish('无效的版本号。')
url_3 = source_url + mod_url_2[1:]
html_3 = await get_url(url_3, status_code=200)
bs_3 = BeautifulSoup(html_3, 'html.parser')
infos = {'normal': {}, 'fabric': {}, 'forge': {}}
information_3 = bs_3.find_all('tr')
for x in information_3[1:]:
tbs = x.find_all('td')
mod = tbs[0].find('a')
status = tbs[1].text
name = mod.text
depends = tbs[3].find_all('a')
mod_type = 'normal'
if name.lower().find('fabric') != -1:
mod_type = 'fabric'
elif name.lower().find('forge') != -1:
mod_type = 'forge'
if status not in infos[mod_type]:
infos[mod_type][status] = {'url': mod.get('href'), 'depends': len(depends), 'name': name}
send_ = []
for x in infos:
for y in infos[x]:
send_.append((f'{x.title()} ({y})\n' if x != 'normal' else f'{y}\n') +
f'下载链接:{infos[x][y]["url"]}\n'
f'文件名:{infos[x][y]["name"]}\n' +
(f'此mod共有{str(infos[x][y]["depends"])}个依赖,请确认是否已经下载:\n{url_3}' if
infos[x][y][
"depends"] > 0 else ''))
await msg.finish('\n'.join(send_))
url += f'&facets=[["project_type:mod"]]'
resp = await get_url(url, 200, fmt="json", timeout=5, attempt=3)
if resp is not None:
results = []
if len(resp["hits"]) == 0:
return None
for project in resp['hits']:
results.append(("modrinth", project["title"], project["project_id"], project["versions"]))
return results
async def search_curseforge(name: str, ver: str):
headers = {
'Accept': 'application/json',
'x-api-key': x_api_key
}
url = f'https://api.curseforge.com/v1/mods/search?gameId=432&searchFilter={name}&sortField=2&sortOrder=desc&pageSize=10&classId=6'
if ver:
url += f'&gameVersion={ver}'
results = []
try:
resp = await get_url(url, 200, fmt="json", timeout=5, attempt=3, headers=headers)
if resp is not None:
if resp["pagination"]["resultCount"] == 0:
return None
for mod in resp["data"]:
results.append(("curseforge", mod["name"], mod["id"], None))
except Exception:
traceback.print_exc()
return results
async def get_modrinth_project_version(project_id: str, ver: str):
url = f'https://api.modrinth.com/v2/project/{project_id}/version?game_versions=["{ver}"]&featured=true'
resp = (await get_url(url, 200, fmt="json", timeout=5, attempt=3))[0]
if resp is not None:
return resp
except ValueError: # 404 ...
await msg.finish('未找到该Mod。')
async def get_curseforge_mod_version_index(modid: str):
headers = {
'Accept': 'application/json',
'x-api-key': x_api_key
}
url = f'https://api.curseforge.com/v1/mods/{modid}'
resp = await get_url(url, 200, fmt="json", timeout=5, attempt=3, headers=headers)
if resp is not None:
return resp["data"]['latestFilesIndexes']
async def get_curseforge_mod_file(modid: str, ver: str):
headers = {
'Accept': 'application/json',
'x-api-key': x_api_key
}
url = f'https://api.curseforge.com/v1/mods/{modid}/files?gameVersion={ver}'
try:
resp = await get_url(url, 200, fmt="json", timeout=5, attempt=3, headers=headers)
if resp is not None:
return resp["data"][0]
except Exception:
traceback.print_exc()
# 搜索 Mod
result = await asyncio.gather(*(search_modrinth(mod_name, ver), search_curseforge(mod_name, ver)))
cache_result = []
if result[0] is None and result[1] is None:
await msg.finish("搜索失败,无结果。")
else:
# 合并搜索结果
reply_text, count = [], 0
if result[0] is None:
reply_text.append("Modrinth 结果:无")
reply_text.append("Modrinth 结果:")
for mod in result[0]:
count += 1
reply_text.append(f"{count}. {mod[1]}")
cache_result.append(mod)
if result[1] is None:
reply_text.append("CurseForge 结果:无")
else:
reply_text.append("CurseForge 结果:")
for mod in result[1]:
count += 1
reply_text.append(f"{count}. {mod[1]}")
cache_result.append(mod)
reply = await msg.waitReply('\n'.join(reply_text) + '\n请回复编号来选择mod。')
replied = reply.asDisplay(text_only=True)
# 查找 Mod
if replied.isdigit():
replied = int(replied)
if replied > len(cache_result):
return await msg.finish('编号超出范围。')
else:
mod_info = cache_result[replied - 1]
else:
return await msg.finish('无效的编号,必须为纯数字。')
if mod_info[0] == "modrinth": # modrinth mod
if ver is None:
reply2 = await msg.waitReply('此mod拥有如下版本\n' + '\n'.join(mod_info[3]) + '\n请回复版本号来选择版本。')
replied2 = reply2.asDisplay(text_only=True)
if replied2 in mod_info[3]:
version_info = await get_modrinth_project_version(mod_info[2], replied2)
if version_info is not None:
await msg.finish(f'{" ".join(version_info["loaders"])}\n下载链接:{version_info["files"][0]["url"]}\n文件名:{version_info["files"][0]["filename"]}')
elif ver not in mod_info[3]:
await msg.finish("未找到指定版本。")
elif ver in mod_info[3]:
version_info = await get_modrinth_project_version(mod_info[2], ver)
if version_info is not None:
await msg.finish(f'{" ".join(version_info["loaders"])}\n下载链接:{version_info["files"][0]["url"]}\n文件名:{version_info["files"][0]["filename"]}')
else: # curseforge mod
version_index = await get_curseforge_mod_version_index(mod_info[2])
if version_index is not None:
if ver is None:
reply_text = []
for version in version_index:
reply_text.append(version["gameVersion"])
reply2 = await msg.waitReply('此mod拥有如下版本\n' +
'\n'.join(reply_text) +
'\n请回复版本号来选择版本。')
ver = reply2.asDisplay(text_only=True)
elif ver not in version_index:
await msg.finish("未找到指定版本。")
if ver in version_index:
file_info = await get_curseforge_mod_file(mod_info[2], ver)
if file_info is not None:
await msg.finish(f'{" ".join(file_info["gameVersions"])} \
\n下载链接{file_info["downloadUrl"]} \
\n文件名{file_info["fileName"]}')
else:
await msg.finish("未找到指定版本。")

View file

@ -26,24 +26,21 @@ async def main(msg: Bot.MessageSession):
is_local_ip = True
matchserip = re.match(r'(.*?)\.(.*?)\.(.*?)\.(.*?)', server_address)
if matchserip:
try:
if matchserip.group(1) == '192':
if matchserip.group(2) == '168':
is_local_ip = True
if matchserip.group(1) == '172':
if 16 <= int(matchserip.group(2)) <= 31:
is_local_ip = True
if matchserip.group(1) == '10':
if 0 <= int(matchserip.group(2)) <= 255:
is_local_ip = True
if matchserip.group(1) == '127':
if matchserip.group(1) == '192':
if matchserip.group(2) == '168':
is_local_ip = True
if matchserip.group(1) == '0':
if matchserip.group(2) == '0':
if matchserip.group(3) == '0':
is_local_ip = True
except:
traceback.print_exc()
if matchserip.group(1) == '172':
if 16 <= int(matchserip.group(2)) <= 31:
is_local_ip = True
if matchserip.group(1) == '10':
if 0 <= int(matchserip.group(2)) <= 255:
is_local_ip = True
if matchserip.group(1) == '127':
is_local_ip = True
if matchserip.group(1) == '0':
if matchserip.group(2) == '0':
if matchserip.group(3) == '0':
is_local_ip = True
if is_local_ip:
return await msg.sendMessage(msg.locale.t('server.message.local_ip'))
sm = ['j', 'b']

View file

@ -40,10 +40,9 @@ async def server(msg, address, raw=False, showplayer=False, mode='j'):
elif 'extra' in description:
extra = description['extra']
text = []
qwq = ''
for item in extra[:]:
text.append(str(item['text']))
servers.append(qwq.join(text))
servers.append(''.join(text))
else:
servers.append(str(description))
@ -83,12 +82,12 @@ async def server(msg, address, raw=False, showplayer=False, mode='j'):
bemotd = await req.text()
bejson = json.loads(bemotd)
unpack_data = bejson['data'].split(';')
edition = unpack_data[0]
motd_1 = unpack_data[1]
motd_2 = unpack_data[7]
version_name = unpack_data[3]
player_count = unpack_data[4]
max_players = unpack_data[5]
edition = unpack_data[0]
version_name = unpack_data[3]
motd_2 = unpack_data[7]
game_mode = unpack_data[8]
bemsg = '[BE]\n' + \
motd_1 + ' - ' + motd_2 + \

View file

@ -8,6 +8,7 @@ from core.component import module
from core.utils.http import get_url
from core.utils.i18n import Locale
from .teahouse import get_rss as get_teahouse_rss
from core.utils.image import msgchain2image
async def get_weekly(with_img=False, zh_tw=False):
@ -42,12 +43,25 @@ wky = module('weekly', developers=['Dianliang233'], support_languages=['zh_cn',
@wky.handle('{{weekly.help}}')
async def _(msg: Bot.MessageSession):
weekly = await get_weekly(True if msg.target.clientName == 'QQ' else False,
weekly = await get_weekly(True if msg.target.clientName in ['QQ', 'TEST'] else False,
zh_tw=True if msg.locale.locale == 'zh_tw' else False)
await msg.finish(weekly)
@wky.handle('image {{weekly.image.help}}')
async def _(msg: Bot.MessageSession):
weekly = await get_weekly(True if msg.target.clientName in ['QQ', 'TEST'] else False,
zh_tw=True if msg.locale.locale == 'zh_tw' else False)
await msg.finish(Image((await msgchain2image([Plain(msg.locale.t('weekly_rss.prompt'))] + weekly))))
@wky.handle('teahouse {{weekly.teahouse.help}}')
async def _(msg: Bot.MessageSession):
weekly = await get_teahouse_rss()
await msg.finish(weekly)
@wky.handle('teahouse image {{weekly.teahouse.help}}')
async def _(msg: Bot.MessageSession):
weekly = await get_teahouse_rss()
await msg.finish(Image(await msgchain2image([Plain(weekly)])))

View file

@ -1,7 +1,8 @@
{
"weekly.help": "Get the weekly page of Chinese Minecraft Wiki.",
"weekly.image.help": "获取中文 Minecraft Wiki 的每周页面(图片版)。",
"weekly.message": "Weekly page:\n\n${text}",
"weekly.message.link": "\nImage: ${img}\n\nArticle Link: ${article}\nWeekly Pages: ${link}",
"weekly.message.expired": "An error occurred: The weekly page has expired. Please contact Chinese Minecraft Wiki to update.",
"weekly.teahouse.help": "Get Teahouse Weekly."
}
}

View file

@ -1,7 +1,8 @@
{
"weekly.help": "获取中文 Minecraft Wiki 的每周页面。",
"weekly.image.help": "获取中文 Minecraft Wiki 的每周页面(图片版)。",
"weekly.message": "本周页面:\n\n${text}",
"weekly.message.link": "\n图片${img}\n\n页面链接${article}\n每周页面${link}",
"weekly.message.expired": "发生错误:本周页面已过期,请联系中文 Minecraft Wiki 更新。",
"weekly.teahouse.help": "获取茶馆周报。"
}
}

View file

@ -1,7 +1,8 @@
{
"weekly.help": "取得中文 Minecraft Wiki 的每週頁面。",
"weekly.image.help": "取得中文 Minecraft Wiki 的每週頁面(圖片版)。",
"weekly.message": "本週頁面:\n\n${text}",
"weekly.message.link": "\n圖片${img}\n\n頁面連結${article}\n每週頁面${link}",
"weekly.message.expired": "發生錯誤:本週頁面已過期,請聯絡中文 Minecraft Wiki 更新。",
"weekly.teahouse.help": "取得茶館週報。"
}
}

View file

@ -1,7 +1,9 @@
from core.builtins import Bot
from core.builtins import Bot, Image, Plain
from core.component import module
from core.logger import Logger
from core.scheduler import CronTrigger
from core.utils.image import msgchain2image
from core.utils.i18n import Locale
from modules.weekly import get_weekly
from modules.weekly.teahouse import get_rss as get_teahouse_rss
@ -16,6 +18,11 @@ async def weekly_rss():
weekly_cn = await get_weekly(True if Bot.FetchTarget.name == 'QQ' else False)
weekly_tw = await get_weekly(True if Bot.FetchTarget.name == 'QQ' else False, zh_tw=True)
if Bot.FetchTarget.name == 'QQ':
weekly_cn = [Plain(Locale('zh_cn').t('weekly_rss.prompt'))] + weekly_cn
weekly_tw = [Plain(Locale('zh_tw').t('weekly_rss.prompt'))] + weekly_tw
weekly_cn = Image(await msgchain2image(weekly_cn))
weekly_tw = Image(await msgchain2image(weekly_tw))
post_msg = {'zh_cn': weekly_cn, 'zh_tw': weekly_tw, 'fallback': weekly_cn}
await Bot.FetchTarget.post_message('weekly_rss', post_msg, i18n=True)
Logger.info('Weekly checked.')
@ -32,5 +39,12 @@ async def weekly_rss():
Logger.info('Checking teahouse weekly...')
weekly = await get_teahouse_rss()
await Bot.FetchTarget.post_message('teahouse_weekly_rss', weekly)
if Bot.FetchTarget.name == 'QQ':
weekly_cn = [Plain(Locale('zh_cn').t('weekly_rss.teahouse.prompt'))] + weekly
weekly_tw = [Plain(Locale('zh_tw').t('weekly_rss.teahouse.prompt'))] + weekly
weekly_en = [Plain(Locale('en_us').t('weekly_rss.teahouse.prompt'))] + weekly
post_msg = {'zh_cn': weekly_cn, 'zh_tw': weekly_tw, 'en_us': weekly_en, 'fallback': weekly_cn}
await Bot.FetchTarget.post_message('teahouse_weekly_rss', post_msg, i18n=True)
else:
await Bot.FetchTarget.post_message('teahouse_weekly_rss', weekly)
Logger.info('Teahouse Weekly checked.')

View file

@ -1,4 +1,5 @@
{
"weekly_rss.help.desc": "When enabled, you will subscribe to the weekly page of Chinese Minecraft Wiki. (updated every Monday at 8:30)",
"teahouse_weekly_rss.help.desc": "When enabled, you will subscribe to the weekly page of Teahouse Weekly. (Updated every Monday at 8:30)"
}
"teahouse_weekly_rss.help.desc": "When enabled, you will subscribe to the weekly page of Teahouse Weekly. (Updated every Monday at 8:30)",
"weekly_rss.prompt": "如需获取每周页面的文字版本及链接,请使用 ~weekly 命令。"
}

View file

@ -1,4 +1,6 @@
{
"weekly_rss.help.desc": "开启后将订阅中文 Minecraft Wiki 的每周页面。(每周一 8:30 更新)",
"teahouse_weekly_rss.help.desc": "开启后将订阅茶馆周报的每周页面。(每周一 8:30 更新)"
}
"teahouse_weekly_rss.help.desc": "开启后将订阅茶馆周报的每周页面。(每周一 8:30 更新)",
"weekly_rss.prompt": "如需获取每周页面的文字版本及链接,请使用 ~weekly 命令。",
"weekly_rss.teahouse.prompt": "如需获取每周页面的文字版本及链接,请使用 ~weekly teahouse 命令。"
}

View file

@ -1,4 +1,5 @@
{
"weekly_rss.help.desc": "啟用後將訂閱中文 Minecraft Wiki 的每週頁面。(每週一 8:30 更新)",
"teahouse_weekly_rss.help.desc": "啟用後將訂閱茶館週報的每週頁面。(每週一 8:30 更新)"
}
"teahouse_weekly_rss.help.desc": "啟用後將訂閱茶館週報的每週頁面。(每週一 8:30 更新)",
"weekly_rss.prompt": "如需获取每周页面的文字版本及链接,请使用 ~weekly 命令。"
}

View file

@ -3,7 +3,7 @@
"whois.message.type": "類型:",
"whois.message.postal_code": "郵編:",
"whois.message.location": "位置:",
"whois.message.organization": "機構",
"whois.message.organization": "組織",
"whois.message.asn": "ASN",
"whois.message.utc": "時區:",
"whois.message.reverse": "反向解析:",

View file

@ -18,17 +18,17 @@ async def _(msg: Bot.MessageSession):
api = check.value.api
if req.get('trust', False):
res = Audit(api).add_to_AllowList(op)
list_name = ''
list_name = msg.locale.t('wiki.wiki_audit.list_name.allowlist')
else:
res = Audit(api).add_to_BlockList(op)
list_name = ''
list_name = msg.locale.t('wiki.wiki_audit.list_name.blocklist')
if not res:
await msg.finish(f'失败此wiki已经存在于{list_name}名单中:' + api)
await msg.finish(msg.locale.t('wiki.wiki_audit.add.message.failed', list_name=list_name) + api)
else:
await msg.finish(f'成功加入{list_name}名单:' + api)
await msg.finish(msg.locale.t('wiki.wiki_audit.add.message.success', list_name=list_name) + api)
else:
result = '错误无法添加此Wiki。' + \
('\n详细信息:' + check.message if check.message != '' else '')
result = msg.locale.t('wiki.message.error.add') + \
('\n' + msg.locale.t('wiki.message.error.info') + check.message if check.message != '' else '')
await msg.finish(result)
@ -42,18 +42,18 @@ async def _(msg: Bot.MessageSession):
if req.get('distrust', False):
res = Audit(api).remove_from_AllowList()
if res is None:
await msg.finish(f'失败此wiki不存在于白名单中此wiki的白名单可能来自其它同一域名的Wiki' + api)
list_name = ''
await msg.finish(msg.locale.t('wiki.wiki_audit.remove.message.failed.other') + api)
list_name = msg.locale.t('wiki.wiki_audit.list_name.allowlist')
else:
res = Audit(api).remove_from_BlockList()
list_name = ''
list_name = msg.locale.t('wiki.wiki_audit.list_name.blocklist')
if not res:
await msg.finish(f'失败此wiki不存在于{list_name}名单中:' + api)
await msg.finish(msg.locale.t('wiki.wiki_audit.remove.message.failed', list_name=list_name) + api)
else:
await msg.finish(f'成功从{list_name}名单删除:' + api)
await msg.finish(msg.locale.t('wiki.wiki_audit.remove.message.success', list_name=list_name) + api)
else:
result = '错误无法查询此Wiki。' + \
('\n详细信息:' + check.message if check.message != '' else '')
result = msg.locale.t('wiki.message.error.query') + \
('\n' + msg.locale.t('wiki.message.error.info') + check.message if check.message != '' else '')
await msg.finish(result)
@ -69,17 +69,17 @@ async def _(msg: Bot.MessageSession):
block = audit.inBlockList
msg_list = []
if allow:
msg_list.append(api + '已存在于白名单。')
msg_list.append(api + msg.locale.t('wiki.wiki_audit.query.message.allowlist'))
if block:
msg_list.append(api + '已存在于黑名单。')
msg_list.append(api + msg.locale.t('wiki.wiki_audit.query.message.blocklist'))
if msg_list:
msg_list.append('优先级:白名单 > 黑名单')
msg_list.append(msg.locale.t('wiki.wiki_audit.query.message.conflict'))
await msg.finish('\n'.join(msg_list))
else:
await msg.finish(api + '不存在于任何名单。')
await msg.finish(api + msg.locale.t('wiki.wiki_audit.query.message.none'))
else:
result = '错误无法查询此Wiki。' + \
('\n详细信息:' + check.message if check.message != '' else '')
result = msg.locale.t('wiki.message.error.query') + \
('\n' + msg.locale.t('wiki.message.error.info') + check.message if check.message != '' else '')
await msg.finish(result)
@ -93,29 +93,33 @@ async def _(msg: Bot.MessageSession):
allow_columns = [[x[0], x[1]] for x in allow_list]
if allow_columns:
allow_table = ImageTable(data=allow_columns, headers=[
'APILink', 'Operator'])
msg.locale.t('wiki.wiki_audit.list.message.table.header.apilink'),
msg.locale.t('wiki.wiki_audit.list.message.table.header.operator')
])
if allow_table:
allow_image = await image_table_render(allow_table)
if allow_image:
send_msgs.append(Plain('现有白名单:'))
send_msgs.append(Plain(msg.locale.t('wiki.wiki_audit.list.message.allowlist')))
send_msgs.append(Image(allow_image))
block_columns = [[x[0], x[1]] for x in block_list]
if block_columns:
block_table = ImageTable(data=block_columns, headers=[
'APILink', 'Operator'])
msg.locale.t('wiki.wiki_audit.list.message.table.header.apilink'),
msg.locale.t('wiki.wiki_audit.list.message.table.header.operator')
])
if block_table:
block_image = await image_table_render(block_table)
if block_image:
send_msgs.append(Plain('现有黑名单:'))
send_msgs.append(Plain(msg.locale.t('wiki.wiki_audit.list.message.blocklist')))
send_msgs.append(Image(block_image))
if send_msgs:
await msg.finish(send_msgs)
legacy = False
if legacy:
wikis = ['现有白名单:']
wikis = [msg.locale.t('wiki.wiki_audit.list.message.allowlist')]
for al in allow_list:
wikis.append(f'{al[0]}by {al[1]}')
wikis.append('现有黑名单:')
wikis.append(msg.locale.t('wiki.wiki_audit.list.message.blocklist'))
for bl in block_list:
wikis.append(f'{bl[0]}by {bl[1]}')
await msg.finish('\n'.join(wikis))

View file

@ -14,8 +14,9 @@ from modules.wiki.utils.screenshot_image import generate_screenshot_v1, generate
from modules.wiki.utils.wikilib import WikiLib
from .wiki import query_pages, generate_screenshot_v2_blocklist
wiki_inline = module('wiki_inline',
desc='开启后将自动解析消息中带有的[[]]或{{}}字符串并自动查询Wiki如[[海晶石]]',
desc='{wiki.wiki_inline.help.desc}',
alias='wiki_regex', developers=['OasisAkari'])
@ -97,12 +98,12 @@ async def _(msg: Bot.MessageSession):
if guess_type is not None:
if guess_type.extension in ["png", "gif", "jpg", "jpeg", "webp", "bmp", "ico"]:
if msg.Feature.image:
await msg.sendMessage([Plain(f'此页面包括以下文件:{get_page.file}'), Image(dl)],
await msg.sendMessage([Plain(msg.locale.t('wiki.wiki_inline.message.flies', file=get_page.file)), Image(dl)],
quote=False)
img_send = True
elif guess_type.extension in ["oga", "ogg", "flac", "mp3", "wav"]:
if msg.Feature.voice:
await msg.sendMessage([Plain(f'此页面包括以下文件:{get_page.file}'), Voice(dl)],
await msg.sendMessage([Plain(msg.locale.t('wiki.wiki_inline.message.flies', file=get_page.file)), Voice(dl)],
quote=False)
if msg.Feature.image:
if get_page.status and wiki_.wiki_info.in_allowlist:

View file

@ -0,0 +1,77 @@
{
"wiki.wiki_audit.list_name.blocklist": "黑名单",
"wiki.wiki_audit.list_name.allowlist": "白名单",
"wiki.wiki_audit.add.message.success": "成功加入${list_name}",
"wiki.wiki_audit.add.message.failed": "失败,此 Wiki 已存在于${list_name}中:",
"wiki.wiki_audit.remove.message.success": "成功从${list_name}删除:",
"wiki.wiki_audit.remove.message.failed": "失败,此 Wiki 不存在于${list_name}中:",
"wiki.wiki_audit.remove.message.failed.other": "失败,此 Wiki 不存在于白名单中,此 Wiki 的白名单可能来自其他同一域名的 Wiki",
"wiki.wiki_audit.query.message.allowlist": "已存在于白名单。",
"wiki.wiki_audit.query.message.blocklist": "已存在于黑名单。",
"wiki.wiki_audit.query.message.conflict": "优先级:白名单 > 黑名单",
"wiki.wiki_audit.query.message.none": "不存在于任何名单。",
"wiki.wiki_audit.list.message.allowlist": "现有白名单:",
"wiki.wiki_audit.list.message.blocklist": "现有黑名单:",
"wiki.wiki_audit.list.message.table.header.apilink": "API 链接",
"wiki.wiki_audit.list.message.table.header.operator": "操作者",
"wiki.wiki_inline.help.desc": "开启后将自动解析消息中带有 [[ ]] 或 {{ }} 的字符串并自动查询 Wiki例如 [[海晶石]]。",
"wiki.wiki_inline.message.flies": "此页面包括以下文件:${file}",
"wiki.search.help": "搜索一个 Wiki 页面。",
"wiki.search.message": "搜索到以下结果:",
"wiki.search.message.prompt": "回复编号以查询对应的页面。",
"wiki.set.help": "设置起始查询 Wiki。",
"wiki.set.message.success": "成功设置起始 Wiki${name}",
"wiki.set.message.default": "没有设置起始 Wiki已默认为中文 Minecraft Wiki发送 ${prefix}wiki set <域名> 设置自定义起始 Wiki。\n示例${prefix}wiki set https://minecraft.fandom.com/zh/wiki/",
"wiki.iw.message.none": "当前没有设置任何 Interwiki可使用 ${prefix}wiki iw add <interwiki> <api_endpoint_link> 添加。",
"wiki.iw.set.help": "添加自定义 Interwiki。",
"wiki.iw.set.message.success": "成功:已添加自定义 Interwiki\n${iw} -> ${name}",
"wiki.iw.remove.help": "删除自定义 Interwiki。",
"wiki.iw.remove.message.success": "成功:已删除自定义 Interwiki${iw}",
"wiki.iw.list.help": "展示当前设置的 Interwiki。",
"wiki.iw.list.help.legacy": "展示当前设置的 Interwiki。旧版",
"wiki.iw.list.message": "使用 ${prefix}wiki iw get <Interwiki> 可以获取 Interwiki 对应的链接。",
"wiki.iw.list.message.legacy": "当前设置了以下 Interwiki",
"wiki.iw.list.message.prompt": "此处展示的是为机器人设置的自定义 Interwiki如需查看起始 Wiki 的 Interwiki请见${url}",
"wiki.iw.get.help": "获取设置的 Interwiki 对应的 API 地址。",
"wiki.iw.get.message.not_found": "未找到 Interwiki${iw}",
"wiki.headers.list.help": "展示当前设置的请求标头。",
"wiki.headers.list.message": "当前设置了以下请求标头:\n${headers}\n如需自定义请使用 ${prefix}wiki headers set <headers>。\n示例\n${prefix}wiki headers set {{\"accept-language\": \"zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6\"}}",
"wiki.headers.set.help": "添加自定义请求标头。",
"wiki.headers.remove.help": "删除自定义请求标头。",
"wiki.headers.reset.help": "重置自定义请求标头。",
"wiki.headers.set.message.success": "成功:已更新请求时所使用的请求标头:${headers}",
"wiki.headers.reset.message.success": "成功:已重置请求时所使用的请求标头。",
"wiki.prefix.set.help": "设置自定义前缀。",
"wiki.prefix.reset.help": "重置自定义前缀。",
"wiki.prefix.set.message.success": "成功:已更新请求时所使用的前缀:${wiki_prefix}",
"wiki.fandom.enable.help": "开启 Fandom 全局 Interwiki 查询。",
"wiki.fandom.disable.help": "关闭 Fandom 全局 Interwiki 查询。",
"wiki.fandom.enable.message": "已开启 Fandom 全局 Interwiki 查询。",
"wiki.fandom.disable.message": "已关闭 Fandom 全局 Interwiki 查询。",
"wiki.redlink.enable.help": "开启页面不存在时返回编辑链接。",
"wiki.redlink.disable.help": "关闭页面不存在时返回编辑链接。",
"wiki.redlink.enable.message": "已开启页面不存在时返回编辑链接。",
"wiki.redlink.disable.message": "已关闭页面不存在时返回编辑链接。",
"wiki.redlink.message.not_found": "(页面不存在)",
"wiki.redlink.message.not_found.uneditable": "[${title}] 页面不存在。",
"wiki.prefix.reset.message.success": "成功:已重置请求时所使用的前缀。",
"wiki.help": "查询一个 Wiki 页面,若查询“随机页面”则随机一个页面。",
"wiki.help.l": "查找本页面的对应语言版本,若无结果则返回当前语言。",
"wiki.id.help": "根据页面 ID 查询一个 Wiki 页面。",
"wiki.id.message.error": "发生错误:页面 ID 必须为数字。",
"wiki.id.message.not_found": "找不到页面 ID 为 ${id} 的页面。",
"wiki.message.redirect": "(重定向[${title}] -> [${redirected_title}]",
"wiki.message.redirect.autofix": "(已指定 [${title}] 更正为 [${redirected_title}]。)",
"wiki.message.redirect.template_to_page": "[${title}] 不存在,已自动重定向至 [${redirected_title}]",
"wiki.message.invalid_namespace": "此 Wiki 上没有名为 ${namespace} 的命名空间,请检查拼写后重试。",
"wiki.message.not_found": "找不到 [${title}]。",
"wiki.message.magic_word": "机器人暂不支持魔术字。",
"tos.reason.too_many_redirects": "使机器人重定向页面的次数过多。",
"tos.reason.wiki_abuse": "一次性查询的页面超过 15 个。",
"wiki.message.untrust": "注意:此 Wiki 当前没有加入机器人的白名单列表中,查询此 Wiki 时将会对返回内容进行限制。\n若需取消限制请在此处申请白名单\n",
"wiki.message.error.add": "发生错误:无法添加此 Wiki。",
"wiki.message.error.blocked": "发生错误:${name} 处于黑名单中。",
"wiki.message.error.query": "发生错误:无法查询此 Wiki。",
"wiki.message.error.set": "发生错误:无法设置此 Wiki。",
"wiki.message.error.info": "详细信息:"
}

View file

@ -0,0 +1,77 @@
{
"wiki.wiki_audit.list_name.blocklist": "黑名单",
"wiki.wiki_audit.list_name.allowlist": "白名单",
"wiki.wiki_audit.add.message.success": "成功加入${list_name}",
"wiki.wiki_audit.add.message.failed": "失败,此 Wiki 已存在于${list_name}中:",
"wiki.wiki_audit.remove.message.success": "成功从${list_name}删除:",
"wiki.wiki_audit.remove.message.failed": "失败,此 Wiki 不存在于${list_name}中:",
"wiki.wiki_audit.remove.message.failed.other": "失败,此 Wiki 不存在于白名单中,此 Wiki 的白名单可能来自其他同一域名的 Wiki",
"wiki.wiki_audit.query.message.allowlist": "已存在于白名单。",
"wiki.wiki_audit.query.message.blocklist": "已存在于黑名单。",
"wiki.wiki_audit.query.message.conflict": "优先级:白名单 > 黑名单",
"wiki.wiki_audit.query.message.none": "不存在于任何名单。",
"wiki.wiki_audit.list.message.allowlist": "现有白名单:",
"wiki.wiki_audit.list.message.blocklist": "现有黑名单:",
"wiki.wiki_audit.list.message.table.header.apilink": "API 链接",
"wiki.wiki_audit.list.message.table.header.operator": "操作者",
"wiki.wiki_inline.help.desc": "开启后将自动解析消息中带有 [[ ]] 或 {{ }} 的字符串并自动查询 Wiki例如 [[海晶石]]。",
"wiki.wiki_inline.message.flies": "此页面包括以下文件:${file}",
"wiki.search.help": "搜索一个 Wiki 页面。",
"wiki.search.message": "搜索到以下结果:",
"wiki.search.message.prompt": "回复编号以查询对应的页面。",
"wiki.set.help": "设置起始查询 Wiki。",
"wiki.set.message.success": "成功设置起始 Wiki${name}",
"wiki.set.message.default": "没有设置起始 Wiki已默认为中文 Minecraft Wiki发送 ${prefix}wiki set <域名> 设置自定义起始 Wiki。\n示例${prefix}wiki set https://minecraft.fandom.com/zh/wiki/",
"wiki.iw.message.none": "当前没有设置任何 Interwiki可使用 ${prefix}wiki iw add <interwiki> <api_endpoint_link> 添加。",
"wiki.iw.set.help": "添加自定义 Interwiki。",
"wiki.iw.set.message.success": "成功:已添加自定义 Interwiki\n${iw} -> ${name}",
"wiki.iw.remove.help": "删除自定义 Interwiki。",
"wiki.iw.remove.message.success": "成功:已删除自定义 Interwiki${iw}",
"wiki.iw.list.help": "展示当前设置的 Interwiki。",
"wiki.iw.list.help.legacy": "展示当前设置的 Interwiki。旧版",
"wiki.iw.list.message": "使用 ${prefix}wiki iw get <Interwiki> 可以获取 Interwiki 对应的链接。",
"wiki.iw.list.message.legacy": "当前设置了以下 Interwiki",
"wiki.iw.list.message.prompt": "此处展示的是为机器人设置的自定义 Interwiki如需查看起始 Wiki 的 Interwiki请见${url}",
"wiki.iw.get.help": "获取设置的 Interwiki 对应的 API 地址。",
"wiki.iw.get.message.not_found": "未找到 Interwiki${iw}",
"wiki.headers.list.help": "展示当前设置的请求标头。",
"wiki.headers.list.message": "当前设置了以下请求标头:\n${headers}\n如需自定义请使用 ${prefix}wiki headers set <headers>。\n示例\n${prefix}wiki headers set {{\"accept-language\": \"zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6\"}}",
"wiki.headers.set.help": "添加自定义请求标头。",
"wiki.headers.remove.help": "删除自定义请求标头。",
"wiki.headers.reset.help": "重置自定义请求标头。",
"wiki.headers.set.message.success": "成功:已更新请求时所使用的请求标头:${headers}",
"wiki.headers.reset.message.success": "成功:已重置请求时所使用的请求标头。",
"wiki.prefix.set.help": "设置自定义前缀。",
"wiki.prefix.reset.help": "重置自定义前缀。",
"wiki.prefix.set.message.success": "成功:已更新请求时所使用的前缀:${wiki_prefix}",
"wiki.fandom.enable.help": "开启 Fandom 全局 Interwiki 查询。",
"wiki.fandom.disable.help": "关闭 Fandom 全局 Interwiki 查询。",
"wiki.fandom.enable.message": "已开启 Fandom 全局 Interwiki 查询。",
"wiki.fandom.disable.message": "已关闭 Fandom 全局 Interwiki 查询。",
"wiki.redlink.enable.help": "开启页面不存在时返回编辑链接。",
"wiki.redlink.disable.help": "关闭页面不存在时返回编辑链接。",
"wiki.redlink.enable.message": "已开启页面不存在时返回编辑链接。",
"wiki.redlink.disable.message": "已关闭页面不存在时返回编辑链接。",
"wiki.redlink.message.not_found": "(页面不存在)",
"wiki.redlink.message.not_found.uneditable": "[${title}] 页面不存在。",
"wiki.prefix.reset.message.success": "成功:已重置请求时所使用的前缀。",
"wiki.help": "查询一个 Wiki 页面,若查询“随机页面”则随机一个页面。",
"wiki.help.l": "查找本页面的对应语言版本,若无结果则返回当前语言。",
"wiki.id.help": "根据页面 ID 查询一个 Wiki 页面。",
"wiki.id.message.error": "发生错误:页面 ID 必须为数字。",
"wiki.id.message.not_found": "找不到页面 ID 为 ${id} 的页面。",
"wiki.message.redirect": "(重定向[${title}] -> [${redirected_title}]",
"wiki.message.redirect.autofix": "(已指定 [${title}] 更正为 [${redirected_title}]。)",
"wiki.message.redirect.template_to_page": "[${title}] 不存在,已自动重定向至 [${redirected_title}]",
"wiki.message.invalid_namespace": "此 Wiki 上没有名为 ${namespace} 的命名空间,请检查拼写后重试。",
"wiki.message.not_found": "找不到 [${title}]。",
"wiki.message.magic_word": "机器人暂不支持魔术字。",
"tos.reason.too_many_redirects": "使机器人重定向页面的次数过多。",
"tos.reason.wiki_abuse": "一次性查询的页面超过 15 个。",
"wiki.message.untrust": "注意:此 Wiki 当前没有加入机器人的白名单列表中,查询此 Wiki 时将会对返回内容进行限制。\n若需取消限制请在此处申请白名单\n",
"wiki.message.error.add": "发生错误:无法添加此 Wiki。",
"wiki.message.error.blocked": "发生错误:${name} 处于黑名单中。",
"wiki.message.error.query": "发生错误:无法查询此 Wiki。",
"wiki.message.error.set": "发生错误:无法设置此 Wiki。",
"wiki.message.error.info": "详细信息:"
}

View file

@ -0,0 +1,77 @@
{
"wiki.wiki_audit.list_name.blocklist": "黑名單",
"wiki.wiki_audit.list_name.allowlist": "白名單",
"wiki.wiki_audit.add.message.success": "成功加入${list_name}",
"wiki.wiki_audit.add.message.failed": "失敗,此 Wiki 已存在於${list_name}中:",
"wiki.wiki_audit.remove.message.success": "成功從${list_name}刪除:",
"wiki.wiki_audit.remove.message.failed": "失敗,此 Wiki 不存在於${list_name}中:",
"wiki.wiki_audit.remove.message.failed.other": "失敗,此 Wiki 不存在於白名單中,此 Wiki 的白名單可能來自其他同一域名的 Wiki",
"wiki.wiki_audit.query.message.allowlist": "已存在於白名單。",
"wiki.wiki_audit.query.message.blocklist": "已存在於黑名單。",
"wiki.wiki_audit.query.message.conflict": "優先順序:白名單 > 黑名單",
"wiki.wiki_audit.query.message.none": "不存在於任何名單。",
"wiki.wiki_audit.list.message.allowlist": "現有白名單:",
"wiki.wiki_audit.list.message.blocklist": "現有黑名單:",
"wiki.wiki_audit.list.message.table.header.apilink": "API 連結",
"wiki.wiki_audit.list.message.table.header.operator": "操作員",
"wiki.wiki_inline.help.desc": "啟用後將自動解析訊息中帶有 [[ ]] 或 {{ }} 的字串並自動查詢 Wiki例如 [[海晶石]]。",
"wiki.wiki_inline.message.flies": "此頁面含有以下檔案:${file}",
"wiki.search.help": "搜尋一個 Wiki 頁面。",
"wiki.search.message": "搜尋到以下結果:",
"wiki.search.message.prompt": "回覆編號以查詢對應的頁面。",
"wiki.set.help": "設定起始查詢 Wiki。",
"wiki.set.message.success": "成功設定起始 Wiki${name}",
"wiki.set.message.default": "沒有設定起始 Wiki已預設為中文 Minecraft Wiki傳送 ${prefix}wiki set <域名> 設定自訂起始 Wiki。\n示例${prefix}wiki set https://minecraft.fandom.com/zh/wiki/",
"wiki.iw.message.none": "目前沒有設定任何 Interwiki可使用 ${prefix}wiki iw add <interwiki> <api_endpoint_link> 新增。",
"wiki.iw.set.help": "新增自訂 Interwiki。",
"wiki.iw.set.message.success": "成功:已新增自訂 Interwiki\n${iw} -> ${name}",
"wiki.iw.remove.help": "刪除自訂 Interwiki。",
"wiki.iw.remove.message.success": "成功:已刪除自訂 Interwiki${iw}",
"wiki.iw.list.help": "展示目前設定的 Interwiki。",
"wiki.iw.list.help.legacy": "展示目前設定的 Interwiki。舊版",
"wiki.iw.list.message": "使用 ${prefix}wiki iw get <Interwiki> 可以取得 Interwiki 對應的連結。",
"wiki.iw.list.message.legacy": "目前設定了以下 Interwiki",
"wiki.iw.list.message.prompt": "此處展示的是機器人設定的自訂 Interwiki如需查看起始 Wiki 的 Interwiki請見${url}",
"wiki.iw.get.help": "取得設定的 Interwiki 對應的 API 地址。",
"wiki.iw.get.message.not_found": "未找到 Interwiki${iw}",
"wiki.headers.list.help": "展示目前設定的請求標頭。",
"wiki.headers.list.message": "目前設定了以下請求標頭:\n${headers}\n如需自訂請使用 ${prefix}wiki headers set <headers>。\n示例\n${prefix}wiki headers set {{\"accept-language\": \"zh-TW,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6\"}}",
"wiki.headers.set.help": "新增自訂請求標頭。",
"wiki.headers.remove.help": "刪除自訂請求標頭。",
"wiki.headers.reset.help": "重設自訂請求標頭。",
"wiki.headers.set.message.success": "成功:已更新請求時所使用的請求標頭:${headers}",
"wiki.headers.reset.message.success": "成功:已重設請求時所使用的請求標頭:",
"wiki.prefix.set.help": "設定自訂前綴。",
"wiki.prefix.reset.help": "重設自訂前綴。",
"wiki.prefix.set.message.success": "成功:已更新請求時所使用的前綴:${wiki_prefix}",
"wiki.fandom.enable.help": "啟用 Fandom 全域 Interwiki 查詢。",
"wiki.fandom.disable.help": "禁用 Fandom 全域 Interwiki 查詢。",
"wiki.fandom.enable.message": "已啟用 Fandom 全域 Interwiki 查詢。",
"wiki.fandom.disable.message": "已禁用 Fandom 全域 Interwiki 查詢。",
"wiki.redlink.enable.help": "啟用頁面不存在時返回編輯連結。",
"wiki.redlink.disable.help": "禁用頁面不存在時返回編輯連結。",
"wiki.redlink.enable.message": "已啟用頁面不存在時返回編輯連結。",
"wiki.redlink.disable.message": "已禁用頁面不存在時返回編輯連結。",
"wiki.redlink.message.not_found": "(頁面不存在)",
"wiki.redlink.message.not_found.uneditable": "[${title}] 頁面不存在。",
"wiki.prefix.reset.message.success": "成功:已重設請求時所使用的前綴:",
"wiki.help": "查詢一個 Wiki 頁面,若查詢「隨機頁面」則隨機一個頁面。",
"wiki.help.l": "查找本頁面的對應語言版本,若無結果則返回目前語言。",
"wiki.id.help": "根據頁面 ID 查詢一個 Wiki 頁面。",
"wiki.id.message.error": "發生錯誤:頁面 ID 必須為數字。",
"wiki.id.message.not_found": "找不到頁面 ID 為 ${id} 的頁面。",
"wiki.message.redirect": "(重新導向[${title}] -> [${redirected_title}]",
"wiki.message.redirect.autofix": "(已指定 [${title}] 更正為 [${redirected_title}]。)",
"wiki.message.redirect.template_to_page": "[${title}] 不存在,已自動重新導向至 [${redirected_title}]",
"wiki.message.invalid_namespace": "此 Wiki 上沒有名為 ${namespace} 的命名空間,请檢查拼字後重試。",
"wiki.message.not_found": "找不到 [${title}]。",
"wiki.message.magic_word": "機器人暫不支援魔術字。",
"tos.reason.too_many_redirects": "使機器人重新導向頁面的次數過多。",
"tos.reason.wiki_abuse": "一次性查詢的頁面超過 15 個。",
"wiki.message.untrust": "注意:此 Wiki 目前沒有加入機器人的白名單列表中,查詢此 Wiki 時將會對返回內容進行限制。\n若需取消限制請在此處申請白名單",
"wiki.message.error.add": "發生錯誤:無法新增此 Wiki。",
"wiki.message.error.blocked": "發生錯誤:${name} 處於黑名單中。",
"wiki.message.error.query": "發生錯誤:無法查詢此 Wiki。",
"wiki.message.error.set": "發生錯誤:無法設定此 Wiki。",
"wiki.message.error.info": "詳細資訊:"
}

View file

@ -9,7 +9,7 @@ from modules.wiki.utils.wikilib import WikiLib
from .wiki import wiki, query_pages
@wiki.handle('search <PageName> {搜索一个Wiki页面。}')
@wiki.handle('search <PageName> {{wiki.search.help}}')
async def _(msg: Bot.MessageSession):
await search_pages(msg, msg.parsed_msg['<PageName>'])
@ -22,9 +22,7 @@ async def search_pages(session: Bot.MessageSession, title: Union[str, list, tupl
prefix = target.get_prefix()
enabled_fandom_addon = session.options.get('wiki_fandom_addon')
if start_wiki is None:
await session.sendMessage(
f'没有指定起始Wiki已默认指定为中文Minecraft Wiki发送{session.prefixes[0]}wiki set <域名>来设定自定义起始Wiki。'
f'\n例子:{session.prefixes[0]}wiki set https://minecraft.fandom.com/zh/wiki/')
await session.sendMessage(session.locale.t('wiki.set.message.default', prefix=session.prefixes[0]))
start_wiki = 'https://minecraft.fandom.com/zh/api.php'
if isinstance(title, str):
title = [title]
@ -87,13 +85,13 @@ async def search_pages(session: Bot.MessageSession, title: Union[str, list, tupl
for r in result:
wait_msg_list.append(iw_prefix + r)
if len(wait_msg_list) != 0:
msg_list.append('查询到以下结果:')
msg_list.append(session.locale.t('wiki.search.message'))
i = 0
for w in wait_msg_list:
i += 1
w = f'{i}. {w}'
msg_list.append(w)
msg_list.append('回复编号以查询对应的页面。')
msg_list.append(session.locale.t('wiki.search.message.prompt'))
reply = await session.waitReply(Plain('\n'.join(msg_list)))
if reply.asDisplay(text_only=True).isdigit():
reply_number = int(reply.asDisplay(text_only=True)) - 1

View file

@ -9,7 +9,7 @@ from .wiki import wiki
from config import Config
@wiki.handle('set <WikiUrl> {设置起始查询Wiki}', required_admin=True)
@wiki.handle('set <WikiUrl> {{wiki.set.help}}', required_admin=True)
async def set_start_wiki(msg: Bot.MessageSession):
target = WikiTargetInfo(msg)
check = await WikiLib(msg.parsed_msg['<WikiUrl>'], headers=target.get_headers()).check_wiki_available()
@ -18,19 +18,18 @@ async def set_start_wiki(msg: Bot.MessageSession):
result = WikiTargetInfo(msg).add_start_wiki(check.value.api)
if result:
await msg.finish(
f'成功添加起始Wiki{check.value.name}' + ('\n' + check.message if check.message != '' else '') +
(('\n注意此Wiki当前没有加入本机器人的白名单列表中查询此Wiki时将会对返回内容进行一些限制。\n'
'如需取消限制,请在此处申请白名单:\n' + Config("wiki_whitelist_url"))
msg.locale.t("wiki.set.message.success", name=check.value.name) + ('\n' + check.message if check.message != '' else '') +
(('\n' + msg.locale.t("wiki.message.untrust") + Config("wiki_whitelist_url"))
if not check.value.in_allowlist else ''))
else:
await msg.finish(f'错误:{check.value.name}处于黑名单中。')
await msg.finish(msg.locale.t("wiki.message.error.blocked", name=check.value.name))
else:
result = '错误无法添加此Wiki。' + \
('\n详细信息:' + check.message if check.message != '' else '')
result = msg.locale.t('wiki.message.error.add') + \
('\n' + msg.locale.t('wiki.message.error.info') + check.message if check.message != '' else '')
await msg.finish(result)
@wiki.handle('iw (add|set) <Interwiki> <WikiUrl> {添加自定义Interwiki}', required_admin=True)
@wiki.handle('iw (add|set) <Interwiki> <WikiUrl> {{wiki.iw.set.help}}', required_admin=True)
async def _(msg: Bot.MessageSession):
iw = msg.parsed_msg['<Interwiki>']
url = msg.parsed_msg['<WikiUrl>']
@ -40,29 +39,28 @@ async def _(msg: Bot.MessageSession):
if not check.value.in_blocklist or check.value.in_allowlist:
result = target.config_interwikis(iw, check.value.api, let_it=True)
if result:
await msg.finish(f'成功添加自定义Interwiki\n{iw} -> {check.value.name}' +
(('\n注意此Wiki当前没有加入本机器人的白名单列表中查询此Wiki时将会对返回内容进行一些限制。\n'
'如需取消限制,请在此处申请白名单:\n' + Config("wiki_whitelist_url"))
await msg.finish(msg.locale.t("wiki.iw.set.message.success", iw=iw, name=check.value.name) +
(('\n' + msg.locale.t("wiki.message.untrust") + Config("wiki_whitelist_url"))
if not check.value.in_allowlist else ''))
else:
await msg.finish(f'错误:{check.value.name}处于黑名单中。')
await msg.finish(msg.locale.t("wiki.message.error.blocked", name=check.value.name))
else:
result = '错误无法添加此Wiki。' + \
('\n详细信息:' + check.message if check.message != '' else '')
result = msg.locale.t('wiki.message.error.add') + \
('\n' + msg.locale.t('wiki.message.error.info') + check.message if check.message != '' else '')
await msg.finish(result)
@wiki.handle('iw (del|delete|remove|rm) <Interwiki> {删除自定义Interwiki}', required_admin=True)
@wiki.handle('iw (del|delete|remove|rm) <Interwiki> {{wiki.iw.remove.help}}', required_admin=True)
async def _(msg: Bot.MessageSession):
iw = msg.parsed_msg['<Interwiki>']
target = WikiTargetInfo(msg)
result = target.config_interwikis(iw, let_it=False)
if result:
await msg.finish(f'成功删除自定义Interwiki“{msg.parsed_msg["<Interwiki>"]}')
await msg.finish(msg.locale.t("wiki.iw.remove.message.success", iw=iw))
@wiki.handle(['iw list {展示当前设置的Interwiki}', 'iw show {iw list的别名}',
'iw (list|show) legacy {展示当前设置的Interwiki旧版}'])
@wiki.handle(['iw (list|show) {{wiki.iw.list.help}}',
'iw (list|show) legacy {{wiki.iw.list.help.legacy}}'])
async def _(msg: Bot.MessageSession):
target = WikiTargetInfo(msg)
query = target.get_interwikis()
@ -79,21 +77,21 @@ async def _(msg: Bot.MessageSession):
else:
img = False
if img:
mt = f'使用{msg.prefixes[0]}wiki iw get <Interwiki> 可以获取interwiki对应的链接。'
mt = msg.locale.t("wiki.iw.list.message", prefix=msg.prefixes[0])
if base_interwiki_link is not None:
mt += f'\n此处展示的是为机器人设定的自定义Interwiki如需查看起始wiki的Interwiki请见{str(Url(base_interwiki_link))}'
mt += '\n' + msg.locale.t("wiki.iw.list.message.prompt", url=str(Url(base_interwiki_link)))
await msg.finish([Image(img), Plain(mt)])
else:
result = '当前设置了以下Interwiki\n' + \
result = msg.locale.t("wiki.iw.list.message.legacy") + '\n' + \
'\n'.join([f'{x}: {query[x]}' for x in query])
if base_interwiki_link is not None:
result += f'\n此处展示的是为机器人设定的自定义Interwiki如需查看起始wiki的Interwiki请见{str(Url(base_interwiki_link))}'
result += '\n' + msg.locale.t("wiki.iw.list.message.prompt", url=str(Url(base_interwiki_link)))
await msg.finish(result)
else:
await msg.finish('当前没有设置任何Interwiki使用~wiki iw add <interwiki> <api_endpoint_link>添加一个。')
await msg.finish(msg.locale.t("wiki.iw.message.none", prefix=msg.prefixes[0]))
@wiki.handle('iw get <Interwiki> {获取设置的Interwiki对应的api地址}')
@wiki.handle('iw get <Interwiki> {{wiki.iw.get.help}}')
async def _(msg: Bot.MessageSession):
target = WikiTargetInfo(msg)
query = target.get_interwikis()
@ -101,81 +99,79 @@ async def _(msg: Bot.MessageSession):
if msg.parsed_msg['<Interwiki>'] in query:
await msg.finish(Url(query[msg.parsed_msg['<Interwiki>']]))
else:
await msg.finish(f'未找到Interwiki{msg.parsed_msg["<Interwiki>"]}')
await msg.finish(msg.locale.t("wiki.iw.get.message.not_found", iw=iw))
else:
await msg.finish('当前没有设置任何Interwiki使用~wiki iw add <interwiki> <api_endpoint_link>添加一个。')
await msg.finish(msg.locale.t("wiki.iw.message.none", prefix=msg.prefixes[0]))
@wiki.handle(['headers show {展示当前设置的headers}', 'headers list {headers show 的别名}'])
@wiki.handle(['headers (list|show) {{wiki.headers.list.help}}'])
async def _(msg: Bot.MessageSession):
target = WikiTargetInfo(msg)
headers = target.get_headers()
prompt = f'当前设置了以下标头:\n{json.dumps(headers)}\n如需自定义,请使用~wiki headers set <headers>。\n' \
f'格式:\n' \
f'~wiki headers set {{"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6"}}'
prompt = msg.locale.t("wiki.headers.list.message")
await msg.finish(prompt)
@wiki.handle('headers (add|set) <Headers> {添加自定义headers}', required_admin=True)
@wiki.handle('headers (add|set) <Headers> {{wiki.headers.set.help}}', required_admin=True)
async def _(msg: Bot.MessageSession):
target = WikiTargetInfo(msg)
add = target.config_headers(
" ".join(msg.trigger_msg.split(" ")[3:]), let_it=True)
if add:
await msg.finish(f'成功更新请求时所使用的Headers\n{json.dumps(target.get_headers())}')
await msg.finish(msg.locale.t("wiki.headers.set.message.success", headers=json.dumps(target.get_headers())))
@wiki.handle('headers (del|delete|remove|rm) <HeaderKey> {删除一个headers}', required_admin=True)
@wiki.handle('headers (del|delete|remove|rm) <HeaderKey> {{wiki.headers.remove.help}}', required_admin=True)
async def _(msg: Bot.MessageSession):
target = WikiTargetInfo(msg)
delete = target.config_headers(
[msg.parsed_msg['<HeaderHey>']], let_it=False)
if delete:
await msg.finish(f'成功更新请求时所使用的Headers\n{json.dumps(target.get_headers())}')
await msg.finish(msg.locale.t("wiki.headers.set.message.success", headers=json.dumps(target.get_headers())))
@wiki.handle('headers reset {重置headers}', required_admin=True)
@wiki.handle('headers reset {{wiki.headers.reset.help}}', required_admin=True)
async def _(msg: Bot.MessageSession):
target = WikiTargetInfo(msg)
reset = target.config_headers('{}', let_it=None)
if reset:
await msg.finish(f'成功更新请求时所使用的Headers\n{json.dumps(target.get_headers())}')
await msg.finish(msg.locale.t("wiki.headers.reset.message.success"))
@wiki.handle('prefix set <prefix> {设置查询自动添加前缀}', required_admin=True)
@wiki.handle('prefix set <prefix> {{wiki.prefix.set.help}}', required_admin=True)
async def _(msg: Bot.MessageSession):
target = WikiTargetInfo(msg)
prefix = msg.parsed_msg['<prefix>']
set_prefix = target.set_prefix(prefix)
if set_prefix:
await msg.finish(f'成功更新请求时所使用的前缀:{prefix}')
await msg.finish(msg.locale.t("wiki.prefix.set.message.success", wiki_prefix=prefix))
@wiki.handle('prefix reset {重置查询自动添加的前缀}', required_admin=True)
@wiki.handle('prefix reset {{wiki.prefix.reset.help}}', required_admin=True)
async def _(msg: Bot.MessageSession):
target = WikiTargetInfo(msg)
set_prefix = target.del_prefix()
if set_prefix:
await msg.finish(f'成功重置请求时所使用的前缀。')
await msg.finish(msg.locale.t("wiki.prefix.reset.message.success"))
@wiki.handle('fandom enable {启用Fandom全局Interwiki查询}', 'fandom disable {禁用Fandom全局Interwiki查询}',
@wiki.handle('fandom enable {{wiki.fandom.enable.help}}', 'fandom disable {{wiki.fandom.disable.help}}',
required_admin=True)
async def _(msg: Bot.MessageSession):
if msg.parsed_msg.get('enable', False):
msg.data.edit_option('wiki_fandom_addon', True)
await msg.finish('已启用Fandom全局Interwiki查询。')
await msg.finish(msg.locale.t("wiki.fandom.enable.message"))
else:
msg.data.edit_option('wiki_fandom_addon', False)
await msg.finish('已禁用Fandom全局Interwiki查询。')
await msg.finish(msg.locale.t("wiki.fandom.disable.message"))
@wiki.handle('redlink enable {启用不存在页面时返回编辑链接}', 'redlink disable {禁用不存在页面时返回编辑链接}',
@wiki.handle('redlink enable {{wiki.redlink.enable.help}}', 'redlink disable {{wiki.redlink.disable.help}}',
required_admin=True)
async def _(msg: Bot.MessageSession):
if msg.parsed_msg.get('enable', False):
msg.data.edit_option('wiki_redlink', True)
await msg.finish('已启用不存在页面时返回编辑链接。')
await msg.finish(msg.locale.t("wiki.redlink.enable.message"))
else:
msg.data.edit_option('wiki_redlink', False)
await msg.finish('已禁用不存在页面时返回编辑链接。')
await msg.finish(msg.locale.t("wiki.redlink.disable.message"))

View file

@ -13,6 +13,7 @@ from core.builtins import Url
from core.dirty_check import check
from core.logger import Logger
from core.utils.http import get_url
from core.utils.i18n import Locale
from modules.wiki.utils.dbutils import WikiSiteInfo as DBSiteInfo, Audit
@ -37,11 +38,12 @@ class WhatAreUDoingError(Exception):
class QueryInfo:
def __init__(self, api, headers=None, prefix=None):
def __init__(self, api, headers=None, prefix=None, locale=None):
self.api = api
self.headers = headers if headers is not None else {
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6'}
self.prefix = prefix
self.locale = Locale(locale if locale is not None else 'zh_cn')
class WikiInfo:

View file

@ -22,8 +22,8 @@ wiki = module('wiki',
developers=['OasisAkari'])
@wiki.handle('<PageName> [-l <lang>] {查询一个Wiki页面若查询“随机页面”则随机一个页面。}',
options_desc={'-l': '查找本页面的对应语言版本,若无结果则返回当前语言。'})
@wiki.handle('<PageName> [-l <lang>] {{wiki.help}}',
options_desc={'-l': '{wiki.help.l}'})
async def _(msg: Bot.MessageSession):
get_lang: dict = msg.parsed_msg.get('-l', False)
if get_lang:
@ -33,7 +33,7 @@ async def _(msg: Bot.MessageSession):
await query_pages(msg, msg.parsed_msg['<PageName>'], lang=lang)
@wiki.handle('-p <PageID> [-i <CustomIW>] {根据页面ID查询一个Wiki页面。}')
@wiki.handle('id <PageID> [-i <CustomIW>] {{wiki.id.help}}')
async def _(msg: Bot.MessageSession):
if msg.parsed_msg.get('-i', False):
iw: str = msg.parsed_msg['-i'].get('<CustomIW>', '')
@ -41,7 +41,7 @@ async def _(msg: Bot.MessageSession):
iw = ''
page_id: str = msg.parsed_msg['<PageID>']
if not page_id.isdigit():
await msg.finish('错误页面ID必须是数字。')
await msg.finish(msg.locale.t('wiki.id.message.error'))
Logger.debug(msg.parsed_msg)
await query_pages(msg, pageid=page_id, iw=iw)
@ -69,15 +69,13 @@ async def query_pages(session: Union[Bot.MessageSession, QueryInfo], title: Unio
if start_wiki is None:
if isinstance(session, Bot.MessageSession):
await session.sendMessage(
f'没有指定起始Wiki已默认指定为中文Minecraft Wiki发送{session.prefixes[0]}wiki set <域名>来设定自定义起始Wiki。'
f'\n例子:{session.prefixes[0]}wiki set https://minecraft.fandom.com/zh/wiki/')
await session.sendMessage(session.locale.t('wiki.set.message.default', prefix=session.prefixes[0]))
start_wiki = 'https://minecraft.fandom.com/zh/api.php'
if title is not None:
if isinstance(title, str):
title = [title]
if len(title) > 15:
raise AbuseWarning('一次性查询的页面超出15个。')
raise AbuseWarning(session.locale.t('tos.reason.wiki_abuse'))
query_task = {start_wiki: {'query': [], 'iw_prefix': ''}}
for t in title:
if prefix is not None and use_prefix:
@ -147,7 +145,7 @@ async def query_pages(session: Union[Bot.MessageSession, QueryInfo], title: Unio
try:
tasks = []
for rd in ready_for_query_pages:
if rd == '随机页面':
if rd in ['随机页面', '隨機頁面', 'Random']:
tasks.append(asyncio.create_task(
WikiLib(q, headers).random_page()))
else:
@ -179,11 +177,11 @@ async def query_pages(session: Union[Bot.MessageSession, QueryInfo], title: Unio
plain_slice = []
if display_before_title is not None and display_before_title != display_title:
if r.before_page_property == 'template' and r.page_property == 'page':
plain_slice.append(
f'[{display_before_title}]不存在,已自动重定向至[{display_title}]')
plain_slice.append(session.locale.t('wiki.message.redirect.template_to_page',
title=display_before_title, redirected_title=display_title))
else:
plain_slice.append(
f'(重定向[{display_before_title}] -> [{display_title}]')
plain_slice.append(session.locale.t('wiki.message.redirect', title=display_before_title,
redirected_title=display_title))
if r.desc is not None and r.desc != '':
plain_slice.append(r.desc)
if r.link is not None:
@ -198,7 +196,8 @@ async def query_pages(session: Union[Bot.MessageSession, QueryInfo], title: Unio
render_infobox_list.append(
{r.link: {'url': r.info.realurl, 'in_allowlist': r.info.in_allowlist,
'content_mode': r.has_template_doc or r.title.split(':')[0] in ['User'] or
'Template:Disambiguation' in r.templates}})
(r.templates is not None and
'Template:Disambiguation' in r.templates)}})
elif r.link is not None and r.section is not None and r.info.in_allowlist:
render_section_list.append(
{r.link: {'url': r.info.realurl, 'section': r.section,
@ -231,39 +230,37 @@ async def query_pages(session: Union[Bot.MessageSession, QueryInfo], title: Unio
f'(请直接发送“是”字来确认,发送其他内容则代表取消获取。)')
else:
if r.edit_link is not None:
plain_slice.append(r.edit_link + '(页面不存在)')
plain_slice.append(r.edit_link + session.locale.t('wiki.redlink.message.not_found'))
else:
plain_slice.append(f'{display_before_title}页面不存在。')
plain_slice.append(session.locale.t('wiki.redlink.message.not_found.uneditable', title=display_before_title))
else:
wait_plain_slice.append(
f'提示:[{display_before_title}]不存在,您可能要找的是:[{display_title}]。')
if len(r.possible_research_title) == 1:
wait_list.append({display_title: display_before_title})
elif r.before_title is not None:
plain_slice.append(f'提示:找不到[{display_before_title}]。')
plain_slice.append(session.locale.t('wiki.message.not_found', title=display_before_title))
elif r.id != -1:
plain_slice.append(f'提示找不到ID为{str(r.id)}的页面。')
plain_slice.append(session.locale.t('wiki.id.message.not_found', id=str(r.id)))
if r.desc is not None and r.desc != '':
plain_slice.append(r.desc)
if r.invalid_namespace and r.before_title is not None:
plain_slice.append(
f'此Wiki上没有名为{r.invalid_namespace}的命名空间,请检查拼写后再试。')
plain_slice.append(session.locale.t('wiki.message.invalid_namespace', namespace=r.invalid_namespace))
if r.before_page_property == 'template':
if r.before_title.split(':')[1].isupper():
plain_slice.append(
f'提示:机器人暂不支持魔术字。')
plain_slice.append(session.locale.t('wiki.message.magic_word'))
if plain_slice:
msg_list.append(Plain('\n'.join(plain_slice)))
if wait_plain_slice:
wait_msg_list.append(
Plain('\n'.join(wait_plain_slice)))
except WhatAreUDoingError:
raise AbuseWarning('使机器人重定向页面的次数过多。')
raise AbuseWarning(session.locale.t('tos.reason.too_many_redirects'))
except InvalidWikiError as e:
if isinstance(session, Bot.MessageSession):
await session.sendMessage(f'发生错误:' + str(e))
await session.sendMessage(session.locale.t('error') + str(e))
else:
msg_list.append(Plain(f'发生错误:' + str(e)))
msg_list.append(Plain(session.locale.t('error') + str(e)))
if isinstance(session, Bot.MessageSession):
if msg_list:
if all([not render_infobox_list, not render_section_list,
@ -338,20 +335,20 @@ async def query_pages(session: Union[Bot.MessageSession, QueryInfo], title: Unio
wait_list_ = []
for w in wait_list:
for wd in w:
preset_message.append(f'(已指定[{w[wd]}]更正为[{wd}]。)')
preset_message.append(session.locale.t('wiki.message.redirect.autofix', title=w[wd], redirected_title=wd))
wait_list_.append(wd)
if auto_index:
for wp in wait_possible_list:
for wpk in wp:
keys = list(wp[wpk].keys())
preset_message.append(f'(已指定[{wpk}]更正为[{keys[0]}]。)')
preset_message.append(session.locale.t('wiki.message.redirect.autofix', title=wpk, redirected_title=keys[0]))
wait_list_.append(keys[0])
else:
for wp in wait_possible_list:
for wpk in wp:
keys = list(wp[wpk].keys())
if len(wp[wpk][keys[0]]) > index:
preset_message.append(f'(已指定[{wpk}]更正为[{wp[wpk][keys[0]][index]}]。)')
preset_message.append(session.locale.t('wiki.message.redirect.autofix', title=wpk, redirected_title=wp[wpk][keys[0]][index]))
wait_list_.append(wp[wpk][keys[0]][index])
if wait_list_: