diff --git a/ci.py b/ci.py
index 2f4812a..6e56c13 100644
--- a/ci.py
+++ b/ci.py
@@ -1,9 +1,10 @@
from configparser import RawConfigParser
from apscheduler.schedulers.asyncio import AsyncIOScheduler
-from httpx import get, AsyncClient
+from httpx import get
from os.path import exists
from os import mkdir, sep
+import pyromod.listen
from pyrogram import Client
from sqlitedict import SqliteDict
diff --git a/defs/need_char.py b/defs/need_char.py
new file mode 100644
index 0000000..b70d96c
--- /dev/null
+++ b/defs/need_char.py
@@ -0,0 +1,26 @@
+import json
+from typing import Optional
+from resources.Char import characters
+from os import sep
+
+
+def nic2name(name):
+ with open(f"resources{sep}nickname.json", 'r', encoding='utf-8') as f:
+ all_name = json.load(f)
+ f.close()
+ for i in all_name:
+ for x in i.values():
+ if name in x:
+ return x[0]
+ return name
+
+
+def get_character(name: str) -> Optional[int]:
+ # 角色常见昵称转换为官方角色名
+ nick_name = name
+ if name not in ["空", "荧"]:
+ nick_name = nic2name(name)
+ for key, value in characters.items():
+ if nick_name in value:
+ return key
+ return None
diff --git a/plugins/find.py b/plugins/find.py
index 3bfcd03..bb11079 100644
--- a/plugins/find.py
+++ b/plugins/find.py
@@ -9,7 +9,7 @@ from ci import me
async def find_thing(_: Client, message: Message):
if len(message.command) == 1:
await message.reply_text(
- "Please specify what you want to find."
+ "❌ 请指定要查找的内容"
)
else:
data = find(message.command[1:])
diff --git a/plugins/help.py b/plugins/help.py
index 32a68eb..4209043 100644
--- a/plugins/help.py
+++ b/plugins/help.py
@@ -8,6 +8,8 @@ help_msg = """
👩🏻💼 » /find <名称> - 查找物品/角色对应的 id <只显示前五个匹配项>
/find 枫原万叶
/find 枫原万叶的命座
+👩🏻💼 » /jc - 中文教程地址
+👩🏻💼 » 我想要角色 - 生成赋予角色命令
"""
diff --git a/plugins/need_char.py b/plugins/need_char.py
new file mode 100644
index 0000000..57b07e2
--- /dev/null
+++ b/plugins/need_char.py
@@ -0,0 +1,48 @@
+from asyncio import TimeoutError
+from defs.need_char import get_character
+import pyromod
+from pyrogram import Client, filters
+from pyrogram.types import Message
+
+
+@Client.on_message(filters.incoming &
+ filters.regex("我想要角色"))
+async def need_char(client: Client, message: Message):
+ # uid
+ msg = await message.reply("请输入您的游戏 uid 纯数字\n\n例如:10001", quote=True)
+ try:
+ answer = await client.listen(message.chat.id, filters=filters.user(message.from_user.id)) # noqa
+ uid = int(answer.text)
+ except TimeoutError:
+ return await msg.edit("会话超时,请重试")
+ except ValueError:
+ await answer.safe_delete() # noqa
+ return await msg.edit("请输入正确的 uid")
+ await msg.safe_delete() # noqa
+ await answer.safe_delete() # noqa
+ # char
+ msg = await message.reply("请输入角色名称", quote=True)
+ try:
+ answer = await client.listen(message.chat.id, filters=filters.user(message.from_user.id)) # noqa
+ except TimeoutError:
+ return await msg.edit("会话超时,请重试")
+ await msg.safe_delete() # noqa
+ await answer.safe_delete() # noqa
+ char = get_character(answer.text)
+ if not char:
+ return await message.reply("没有找到这个角色")
+ # level
+ msg = await message.reply("请输入角色等级 纯数字\n\n例如:90", quote=True)
+ try:
+ answer = await client.listen(message.chat.id, filters=filters.user(message.from_user.id)) # noqa
+ level = int(answer.text)
+ except TimeoutError:
+ return await msg.edit("会话超时,请重试")
+ except ValueError:
+ return await msg.edit("请输入正确的等级")
+ if level < 0 or level > 90:
+ return await msg.edit("请输入正确的等级")
+ await msg.safe_delete() # noqa
+ await answer.safe_delete() # noqa
+ # answer
+ await message.reply(f"您的角色生成命令为:`/givechar {uid} {char} {level}`", quote=True)
diff --git a/pyromod/__init__.py b/pyromod/__init__.py
new file mode 100644
index 0000000..c22821d
--- /dev/null
+++ b/pyromod/__init__.py
@@ -0,0 +1,21 @@
+"""
+pyromod - A monkeypatched add-on for Pyrogram
+Copyright (C) 2020 Cezar H.
+
+This file is part of pyromod.
+
+pyromod is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+pyromod is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pyromod. If not, see .
+"""
+
+__version__ = "1.5"
diff --git a/pyromod/filters/__init__.py b/pyromod/filters/__init__.py
new file mode 100644
index 0000000..f03398c
--- /dev/null
+++ b/pyromod/filters/__init__.py
@@ -0,0 +1,21 @@
+"""
+pyromod - A monkeypatcher add-on for Pyrogram
+Copyright (C) 2020 Cezar H.
+
+This file is part of pyromod.
+
+pyromod is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+pyromod is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pyromod. If not, see .
+"""
+
+from .filters import dice
\ No newline at end of file
diff --git a/pyromod/filters/filters.py b/pyromod/filters/filters.py
new file mode 100644
index 0000000..c50906b
--- /dev/null
+++ b/pyromod/filters/filters.py
@@ -0,0 +1,25 @@
+"""
+pyromod - A monkeypatcher add-on for Pyrogram
+Copyright (C) 2020 Cezar H.
+
+This file is part of pyromod.
+
+pyromod is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+pyromod is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pyromod. If not, see .
+"""
+
+import pyrogram
+
+def dice(ctx, message):
+ return hasattr(message, 'dice') and message.dice
+pyrogram.filters.dice = dice
diff --git a/pyromod/helpers/__init__.py b/pyromod/helpers/__init__.py
new file mode 100644
index 0000000..5b393e1
--- /dev/null
+++ b/pyromod/helpers/__init__.py
@@ -0,0 +1,20 @@
+"""
+pyromod - A monkeypatcher add-on for Pyrogram
+Copyright (C) 2020 Cezar H.
+
+This file is part of pyromod.
+
+pyromod is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+pyromod is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pyromod. If not, see .
+"""
+from .helpers import ikb, bki, ntb, btn, kb, kbtn, array_chunk, force_reply
\ No newline at end of file
diff --git a/pyromod/helpers/helpers.py b/pyromod/helpers/helpers.py
new file mode 100644
index 0000000..10682ea
--- /dev/null
+++ b/pyromod/helpers/helpers.py
@@ -0,0 +1,63 @@
+from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, ReplyKeyboardMarkup, ForceReply
+
+def ikb(rows = []):
+ lines = []
+ for row in rows:
+ line = []
+ for button in row:
+ button = btn(*button) # InlineKeyboardButton
+ line.append(button)
+ lines.append(line)
+ return InlineKeyboardMarkup(inline_keyboard=lines)
+ #return {'inline_keyboard': lines}
+
+def btn(text, value, type = 'callback_data'):
+ return InlineKeyboardButton(text, **{type: value})
+ #return {'text': text, type: value}
+
+# The inverse of above
+def bki(keyboard):
+ lines = []
+ for row in keyboard.inline_keyboard:
+ line = []
+ for button in row:
+ button = ntb(button) # btn() format
+ line.append(button)
+ lines.append(line)
+ return lines
+ #return ikb() format
+
+def ntb(button):
+ for btn_type in ['callback_data', 'url', 'switch_inline_query', 'switch_inline_query_current_chat', 'callback_game']:
+ value = getattr(button, btn_type)
+ if value:
+ break
+ button = [button.text, value]
+ if btn_type != 'callback_data':
+ button.append(btn_type)
+ return button
+ #return {'text': text, type: value}
+
+def kb(rows = [], **kwargs):
+ lines = []
+ for row in rows:
+ line = []
+ for button in row:
+ button_type = type(button)
+ if button_type == str:
+ button = KeyboardButton(button)
+ elif button_type == dict:
+ button = KeyboardButton(**button)
+
+ line.append(button)
+ lines.append(line)
+ return ReplyKeyboardMarkup(keyboard=lines, **kwargs)
+
+kbtn = KeyboardButton
+
+def force_reply(selective=True):
+ return ForceReply(selective=selective)
+
+def array_chunk(input, size):
+ return [input[i:i+size] for i in range(0, len(input), size)]
+
diff --git a/pyromod/listen/__init__.py b/pyromod/listen/__init__.py
new file mode 100644
index 0000000..150b549
--- /dev/null
+++ b/pyromod/listen/__init__.py
@@ -0,0 +1,21 @@
+"""
+pyromod - A monkeypatcher add-on for Pyrogram
+Copyright (C) 2020 Cezar H.
+
+This file is part of pyromod.
+
+pyromod is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+pyromod is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pyromod. If not, see .
+"""
+
+from .listen import Client, MessageHandler, Chat, User
\ No newline at end of file
diff --git a/pyromod/listen/listen.py b/pyromod/listen/listen.py
new file mode 100644
index 0000000..23a0e6c
--- /dev/null
+++ b/pyromod/listen/listen.py
@@ -0,0 +1,157 @@
+"""
+pyromod - A monkeypatcher add-on for Pyrogram
+Copyright (C) 2020 Cezar H.
+
+This file is part of pyromod.
+
+pyromod is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+pyromod is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pyromod. If not, see .
+"""
+
+import asyncio
+import functools
+from typing import Optional, List
+
+import pyrogram
+
+from ..utils import patch, patchable
+
+loop = asyncio.get_event_loop()
+
+
+class ListenerCanceled(Exception):
+ pass
+
+
+pyrogram.errors.ListenerCanceled = ListenerCanceled
+
+
+@patch(pyrogram.client.Client)
+class Client:
+ @patchable
+ def __init__(self, *args, **kwargs):
+ self.listening = {}
+ self.using_mod = True
+
+ self.old__init__(*args, **kwargs)
+
+ @patchable
+ async def listen(self, chat_id, filters=None, timeout=None):
+ if type(chat_id) != int:
+ chat = await self.get_chat(chat_id)
+ chat_id = chat.id
+
+ future = loop.create_future()
+ future.add_done_callback(
+ functools.partial(self.clear_listener, chat_id)
+ )
+ self.listening.update({
+ chat_id: {"future": future, "filters": filters}
+ })
+ return await asyncio.wait_for(future, timeout)
+
+ @patchable
+ async def ask(self, chat_id, text, filters=None, timeout=None, *args, **kwargs):
+ request = await self.send_message(chat_id, text, *args, **kwargs)
+ response = await self.listen(chat_id, filters, timeout)
+ response.request = request
+ return response
+
+ @patchable
+ def clear_listener(self, chat_id, future):
+ if future == self.listening[chat_id]["future"]:
+ self.listening.pop(chat_id, None)
+
+ @patchable
+ def cancel_listener(self, chat_id):
+ listener = self.listening.get(chat_id)
+ if not listener or listener['future'].done():
+ return
+
+ listener['future'].set_exception(ListenerCanceled())
+ self.clear_listener(chat_id, listener['future'])
+
+
+@patch(pyrogram.handlers.message_handler.MessageHandler)
+class MessageHandler:
+ @patchable
+ def __init__(self, callback: callable, filters=None):
+ self.user_callback = callback
+ self.old__init__(self.resolve_listener, filters)
+
+ @patchable
+ async def resolve_listener(self, client, message, *args):
+ listener = client.listening.get(message.chat.id)
+ if listener and not listener['future'].done():
+ listener['future'].set_result(message)
+ else:
+ if listener and listener['future'].done():
+ client.clear_listener(message.chat.id, listener['future'])
+ await self.user_callback(client, message, *args)
+
+ @patchable
+ async def check(self, client, update):
+ listener = client.listening.get(update.chat.id)
+
+ if listener and not listener['future'].done():
+ return await listener['filters'](client, update) if callable(listener['filters']) else True
+
+ return (
+ await self.filters(client, update)
+ if callable(self.filters)
+ else True
+ )
+
+
+@patch(pyrogram.types.user_and_chats.chat.Chat)
+class Chat(pyrogram.types.Chat):
+ @patchable
+ def listen(self, *args, **kwargs):
+ return self._client.listen(self.id, *args, **kwargs)
+
+ @patchable
+ def ask(self, *args, **kwargs):
+ return self._client.ask(self.id, *args, **kwargs)
+
+ @patchable
+ def cancel_listener(self):
+ return self._client.cancel_listener(self.id)
+
+
+@patch(pyrogram.types.user_and_chats.user.User)
+class User(pyrogram.types.User):
+ @patchable
+ def listen(self, *args, **kwargs):
+ return self._client.listen(self.id, *args, **kwargs)
+
+ @patchable
+ def ask(self, *args, **kwargs):
+ return self._client.ask(self.id, *args, **kwargs)
+
+ @patchable
+ def cancel_listener(self):
+ return self._client.cancel_listener(self.id)
+
+
+@patch(pyrogram.types.messages_and_media.Message)
+class Message(pyrogram.types.Message):
+ @patchable
+ async def safe_delete(self, revoke: bool = True):
+ try:
+ return await self._client.delete_messages(
+ chat_id=self.chat.id,
+ message_ids=self.id,
+ revoke=revoke
+ )
+ except Exception as e: # noqa
+ return False
diff --git a/pyromod/nav/__init__.py b/pyromod/nav/__init__.py
new file mode 100644
index 0000000..e917502
--- /dev/null
+++ b/pyromod/nav/__init__.py
@@ -0,0 +1,20 @@
+"""
+pyromod - A monkeypatcher add-on for Pyrogram
+Copyright (C) 2020 Cezar H.
+
+This file is part of pyromod.
+
+pyromod is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+pyromod is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pyromod. If not, see .
+"""
+from .pagination import Pagination
\ No newline at end of file
diff --git a/pyromod/nav/pagination.py b/pyromod/nav/pagination.py
new file mode 100644
index 0000000..3885de0
--- /dev/null
+++ b/pyromod/nav/pagination.py
@@ -0,0 +1,85 @@
+"""
+pyromod - A monkeypatcher add-on for Pyrogram
+Copyright (C) 2020 Cezar H.
+
+This file is part of pyromod.
+
+pyromod is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+pyromod is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pyromod. If not, see .
+"""
+import math
+from ..helpers import array_chunk
+
+class Pagination:
+ def __init__(self, objects, page_data=None, item_data=None, item_title=None):
+ default_page_callback = (lambda x: str(x))
+ default_item_callback = (lambda i, pg: f'[{pg}] {i}')
+ self.objects = objects
+ self.page_data = page_data or default_page_callback
+ self.item_data = item_data or default_item_callback
+ self.item_title = item_title or default_item_callback
+
+ def create(self, page, lines=5, columns=1):
+ quant_per_page = lines*columns
+ page = 1 if page <= 0 else page
+ offset = (page-1)*quant_per_page
+ stop = offset+quant_per_page
+ cutted = self.objects[offset:stop]
+
+ total = len(self.objects)
+ pages_range = [*range(1, math.ceil(total/quant_per_page)+1)] # each item is a page
+ last_page = len(pages_range)
+
+
+ nav = []
+ if page <= 3:
+ for n in [1,2,3]:
+ if n not in pages_range:
+ continue
+ text = f"· {n} ·" if n == page else n
+ nav.append( (text, self.page_data(n)) )
+ if last_page >= 4:
+ nav.append(
+ ('4 ›' if last_page > 5 else 4, self.page_data(4))
+ )
+ if last_page > 4:
+ nav.append(
+ (f'{last_page} »' if last_page > 5 else last_page, self.page_data(last_page))
+ )
+ elif page >= last_page-2:
+ nav.extend([
+ (f'« 1' if last_page-4 > 1 else 1, self.page_data(1)),
+ (f'‹ {last_page-3}' if last_page-4 > 1 else last_page-3, self.page_data(last_page-3))
+ ])
+ for n in range(last_page-2, last_page+1):
+ text = f"· {n} ·" if n == page else n
+ nav.append( (text, self.page_data(n)) )
+ else:
+ nav = [
+ (f'« 1', self.page_data(1)),
+ (f'‹ {page-1}', self.page_data(page-1)),
+ (f'· {page} ·', "noop"),
+ (f'{page+1} ›', self.page_data(page+1)),
+ (f'{last_page} »', self.page_data(last_page)),
+ ]
+
+ buttons = []
+ for item in cutted:
+ buttons.append(
+ (self.item_title(item, page), self.item_data(item, page))
+ )
+ kb_lines = array_chunk(buttons, columns)
+ if last_page > 1:
+ kb_lines.append(nav)
+
+ return kb_lines
\ No newline at end of file
diff --git a/pyromod/utils/__init__.py b/pyromod/utils/__init__.py
new file mode 100644
index 0000000..b743c60
--- /dev/null
+++ b/pyromod/utils/__init__.py
@@ -0,0 +1,21 @@
+"""
+pyromod - A monkeypatcher add-on for Pyrogram
+Copyright (C) 2020 Cezar H.
+
+This file is part of pyromod.
+
+pyromod is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+pyromod is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pyromod. If not, see .
+"""
+
+from .utils import patch, patchable
\ No newline at end of file
diff --git a/pyromod/utils/utils.py b/pyromod/utils/utils.py
new file mode 100644
index 0000000..6fc660a
--- /dev/null
+++ b/pyromod/utils/utils.py
@@ -0,0 +1,35 @@
+"""
+pyromod - A monkeypatcher add-on for Pyrogram
+Copyright (C) 2020 Cezar H.
+
+This file is part of pyromod.
+
+pyromod is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+pyromod is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pyromod. If not, see .
+"""
+
+def patch(obj):
+ def is_patchable(item):
+ return getattr(item[1], 'patchable', False)
+
+ def wrapper(container):
+ for name,func in filter(is_patchable, container.__dict__.items()):
+ old = getattr(obj, name, None)
+ setattr(obj, 'old'+name, old)
+ setattr(obj, name, func)
+ return container
+ return wrapper
+
+def patchable(func):
+ func.patchable = True
+ return func
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 27f8cb6..4680e31 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,4 @@
-pyrogram==2.0.13
+pyrogram==2.0.16
tgcrypto
httpx
sqlitedict
diff --git a/resources/Char.py b/resources/Char.py
new file mode 100644
index 0000000..05b5c63
--- /dev/null
+++ b/resources/Char.py
@@ -0,0 +1,50 @@
+characters = {10000001: "凯特",
+ 10000002: "神里绫华",
+ 10000003: "琴",
+ 10000005: "旅行者",
+ 10000006: "丽莎",
+ 10000007: "旅行者",
+ 10000014: "芭芭拉",
+ 10000015: "凯亚",
+ 10000016: "迪卢克",
+ 10000020: "雷泽",
+ 10000021: "安柏",
+ 10000022: "温迪",
+ 10000023: "香菱",
+ 10000024: "北斗",
+ 10000025: "行秋",
+ 10000026: "魈",
+ 10000027: "凝光",
+ 10000029: "可莉",
+ 10000030: "钟离",
+ 10000031: "菲谢尔",
+ 10000032: "班尼特",
+ 10000033: "达达利亚",
+ 10000034: "诺艾尔",
+ 10000035: "七七",
+ 10000036: "重云",
+ 10000037: "甘雨",
+ 10000038: "阿贝多",
+ 10000039: "迪奥娜",
+ 10000041: "莫娜",
+ 10000042: "刻晴",
+ 10000043: "砂糖",
+ 10000044: "辛焱",
+ 10000045: "罗莎莉亚",
+ 10000046: "胡桃",
+ 10000047: "枫原万叶",
+ 10000048: "烟绯",
+ 10000049: "宵宫",
+ 10000050: "托马",
+ 10000051: "优菈",
+ 10000052: "雷电将军",
+ 10000053: "早柚",
+ 10000054: "珊瑚宫心海",
+ 10000055: "五郎",
+ 10000056: "九条裟罗",
+ 10000057: "荒泷一斗",
+ 10000058: "八重神子",
+ 10000062: "埃洛伊",
+ 10000063: "申鹤",
+ 10000064: "云堇",
+ 10000066: "神里绫人", }
diff --git a/resources/nickname.json b/resources/nickname.json
new file mode 100644
index 0000000..51a702a
--- /dev/null
+++ b/resources/nickname.json
@@ -0,0 +1,205 @@
+[
+ {
+ "优菈": [
+ "尤拉"
+ ]
+ },
+ {
+ "罗莎莉亚": [
+ "修女"
+ ]
+ },
+ {
+ "胡桃": [
+ "胡桃",
+ "核桃",
+ "堂主",
+ "胡堂主"
+ ]
+ },
+ {
+ "魈": [
+ "魈",
+ "魈大人",
+ "魈师傅"
+ ]
+ },
+ {
+ "甘雨": [
+ "甘雨",
+ "王小美",
+ "甘师傅"
+ ]
+ },
+ {
+ "阿贝多": [
+ "阿贝多",
+ "abd"
+ ]
+ },
+ {
+ "辛焱": [
+ "辛焱",
+ "黑皮",
+ "黑妹"
+ ]
+ },
+ {
+ "钟离": [
+ "钟离",
+ "钟师傅",
+ "岩王爷",
+ "岩神",
+ "岩王"
+ ]
+ },
+ {
+ "迪奥娜": [
+ "迪奥娜",
+ "dio",
+ "Dio",
+ "dio娜"
+ ]
+ },
+ {
+ "达达利亚": [
+ "达达利亚",
+ "公子",
+ "达达鸭",
+ "达达利鸭"
+ ]
+ },
+ {
+ "可莉": [
+ "可莉"
+ ]
+ },
+ {
+ "温迪": [
+ "温迪",
+ "巴巴托斯",
+ "风神"
+ ]
+ },
+ {
+ "莫娜": [
+ "莫娜"
+ ]
+ },
+ {
+ "琴": [
+ "琴",
+ "琴团长"
+ ]
+ },
+ {
+ "雷泽": [
+ "雷泽"
+ ]
+ },
+ {
+ "诺艾尔": [
+ "诺艾尔",
+ "女仆"
+ ]
+ },
+ {
+ "菲谢尔": [
+ "菲谢尔",
+ "小艾咪",
+ "小艾米",
+ "皇女"
+ ]
+ },
+ {
+ "芭芭拉": [
+ "芭芭拉"
+ ]
+ },
+ {
+ "砂糖": [
+ "砂糖"
+ ]
+ },
+ {
+ "班尼特": [
+ "班尼特",
+ "点赞哥",
+ "点赞"
+ ]
+ },
+ {
+ "安柏": [
+ "安柏"
+ ]
+ },
+ {
+ "凯亚": [
+ "凯亚",
+ "凯子哥"
+ ]
+ },
+ {
+ "丽莎": [
+ "丽莎"
+ ]
+ },
+ {
+ "刻晴": [
+ "刻晴",
+ "刻师傅",
+ "啊晴"
+ ]
+ },
+ {
+ "七七": [
+ "七七"
+ ]
+ },
+ {
+ "香菱": [
+ "香菱",
+ "香师傅"
+ ]
+ },
+ {
+ "重云": [
+ "重云"
+ ]
+ },
+ {
+ "行秋": [
+ "行秋"
+ ]
+ },
+ {
+ "北斗": [
+ "北斗"
+ ]
+ },
+ {
+ "凝光": [
+ "凝光"
+ ]
+ },
+ {
+ "旅行者": [
+ "旅行者",
+ "空",
+ "莹",
+ "爷",
+ "玩家",
+ "荧"
+ ]
+ },
+ {
+ "迪卢克": [
+ "迪卢克",
+ "姥爷",
+ "卢姥爷",
+ "大棉袄",
+ "锅巴",
+ "卢锅巴"
+ ]
+ }
+]
\ No newline at end of file